Skip to content

Commit 892b455

Browse files
authored
Merge pull request #20313 from Veykril/push-qmorsnlvwlrr
fix: Fix runnables extra env not substituting env vars
2 parents a7c07f6 + 7a767d0 commit 892b455

File tree

5 files changed

+50
-50
lines changed

5 files changed

+50
-50
lines changed

src/tools/rust-analyzer/editors/code/src/config.ts

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,9 @@ import type { Disposable } from "vscode";
88

99
export type RunnableEnvCfgItem = {
1010
mask?: string;
11-
env: Record<string, string>;
11+
env: { [key: string]: { toString(): string } | null };
1212
platform?: string | string[];
1313
};
14-
export type RunnableEnvCfg = Record<string, string> | RunnableEnvCfgItem[];
1514

1615
type ShowStatusBar = "always" | "never" | { documentSelector: vscode.DocumentSelector };
1716

@@ -261,18 +260,13 @@ export class Config {
261260
return this.get<boolean | undefined>("testExplorer");
262261
}
263262

264-
runnablesExtraEnv(label: string): Record<string, string> | undefined {
265-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
266-
const item = this.get<any>("runnables.extraEnv") ?? this.get<any>("runnableEnv");
267-
if (!item) return undefined;
268-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
269-
const fixRecord = (r: Record<string, any>) => {
270-
for (const key in r) {
271-
if (typeof r[key] !== "string") {
272-
r[key] = String(r[key]);
273-
}
274-
}
275-
};
263+
runnablesExtraEnv(label: string): Env {
264+
const serverEnv = this.serverExtraEnv;
265+
let extraEnv =
266+
this.get<
267+
RunnableEnvCfgItem[] | { [key: string]: { toString(): string } | null } | null
268+
>("runnables.extraEnv") ?? {};
269+
if (!extraEnv) return serverEnv;
276270

277271
const platform = process.platform;
278272
const checkPlatform = (it: RunnableEnvCfgItem) => {
@@ -283,19 +277,25 @@ export class Config {
283277
return true;
284278
};
285279

286-
if (item instanceof Array) {
280+
if (extraEnv instanceof Array) {
287281
const env = {};
288-
for (const it of item) {
282+
for (const it of extraEnv) {
289283
const masked = !it.mask || new RegExp(it.mask).test(label);
290284
if (masked && checkPlatform(it)) {
291285
Object.assign(env, it.env);
292286
}
293287
}
294-
fixRecord(env);
295-
return env;
288+
extraEnv = env;
296289
}
297-
fixRecord(item);
298-
return item;
290+
const runnableExtraEnv = substituteVariablesInEnv(
291+
Object.fromEntries(
292+
Object.entries(extraEnv).map(([k, v]) => [
293+
k,
294+
typeof v === "string" ? v : v?.toString(),
295+
]),
296+
),
297+
);
298+
return { ...runnableExtraEnv, ...serverEnv };
299299
}
300300

301301
get restartServerOnConfigChange() {

src/tools/rust-analyzer/editors/code/src/debug.ts

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,14 @@ import type * as ra from "./lsp_ext";
66
import { Cargo } from "./toolchain";
77
import type { Ctx } from "./ctx";
88
import { createTaskFromRunnable, prepareEnv } from "./run";
9-
import { execute, isCargoRunnableArgs, unwrapUndefinable, log, normalizeDriveLetter } from "./util";
9+
import {
10+
execute,
11+
isCargoRunnableArgs,
12+
unwrapUndefinable,
13+
log,
14+
normalizeDriveLetter,
15+
Env,
16+
} from "./util";
1017
import type { Config } from "./config";
1118

1219
// Here we want to keep track on everything that's currently running
@@ -206,10 +213,7 @@ type SourceFileMap = {
206213
destination: string;
207214
};
208215

209-
async function discoverSourceFileMap(
210-
env: Record<string, string>,
211-
cwd: string,
212-
): Promise<SourceFileMap | undefined> {
216+
async function discoverSourceFileMap(env: Env, cwd: string): Promise<SourceFileMap | undefined> {
213217
const sysroot = env["RUSTC_TOOLCHAIN"];
214218
if (sysroot) {
215219
// let's try to use the default toolchain
@@ -232,7 +236,7 @@ type PropertyFetcher<Config, Input, Key extends keyof Config> = (
232236

233237
type DebugConfigProvider<Type extends string, DebugConfig extends BaseDebugConfig<Type>> = {
234238
executableProperty: keyof DebugConfig;
235-
environmentProperty: PropertyFetcher<DebugConfig, Record<string, string>, keyof DebugConfig>;
239+
environmentProperty: PropertyFetcher<DebugConfig, Env, keyof DebugConfig>;
236240
runnableArgsProperty: PropertyFetcher<DebugConfig, ra.CargoRunnableArgs, keyof DebugConfig>;
237241
sourceFileMapProperty?: keyof DebugConfig;
238242
type: Type;
@@ -276,7 +280,7 @@ const knownEngines: {
276280
"environment",
277281
Object.entries(env).map((entry) => ({
278282
name: entry[0],
279-
value: entry[1],
283+
value: entry[1] ?? "",
280284
})),
281285
],
282286
runnableArgsProperty: (runnableArgs: ra.CargoRunnableArgs) => [
@@ -304,10 +308,7 @@ const knownEngines: {
304308
},
305309
};
306310

307-
async function getDebugExecutable(
308-
runnableArgs: ra.CargoRunnableArgs,
309-
env: Record<string, string>,
310-
): Promise<string> {
311+
async function getDebugExecutable(runnableArgs: ra.CargoRunnableArgs, env: Env): Promise<string> {
311312
const cargo = new Cargo(runnableArgs.workspaceRoot || ".", env);
312313
const executable = await cargo.executableFromArgs(runnableArgs);
313314

@@ -328,7 +329,7 @@ function getDebugConfig(
328329
runnable: ra.Runnable,
329330
runnableArgs: ra.CargoRunnableArgs,
330331
executable: string,
331-
env: Record<string, string>,
332+
env: Env,
332333
sourceFileMap?: Record<string, string>,
333334
): vscode.DebugConfiguration {
334335
const {
@@ -380,14 +381,14 @@ type CodeLldbDebugConfig = {
380381
args: string[];
381382
sourceMap: Record<string, string> | undefined;
382383
sourceLanguages: ["rust"];
383-
env: Record<string, string>;
384+
env: Env;
384385
} & BaseDebugConfig<"lldb">;
385386

386387
type NativeDebugConfig = {
387388
target: string;
388389
// See https://github.com/WebFreak001/code-debug/issues/359
389390
arguments: string;
390-
env: Record<string, string>;
391+
env: Env;
391392
valuesFormatting: "prettyPrinters";
392393
} & BaseDebugConfig<"gdb">;
393394

src/tools/rust-analyzer/editors/code/src/run.ts

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import type { CtxInit } from "./ctx";
77
import { makeDebugConfig } from "./debug";
88
import type { Config } from "./config";
99
import type { LanguageClient } from "vscode-languageclient/node";
10-
import { log, unwrapUndefinable, type RustEditor } from "./util";
10+
import { Env, log, unwrapUndefinable, type RustEditor } from "./util";
1111

1212
const quickPickButtons = [
1313
{ iconPath: new vscode.ThemeIcon("save"), tooltip: "Save as a launch.json configuration." },
@@ -122,11 +122,8 @@ export class RunnableQuickPick implements vscode.QuickPickItem {
122122
}
123123
}
124124

125-
export function prepareBaseEnv(
126-
inheritEnv: boolean,
127-
base?: Record<string, string>,
128-
): Record<string, string> {
129-
const env: Record<string, string> = { RUST_BACKTRACE: "short" };
125+
export function prepareBaseEnv(inheritEnv: boolean, base?: Env): Env {
126+
const env: Env = { RUST_BACKTRACE: "short" };
130127
if (inheritEnv) {
131128
Object.assign(env, process.env);
132129
}
@@ -136,11 +133,7 @@ export function prepareBaseEnv(
136133
return env;
137134
}
138135

139-
export function prepareEnv(
140-
inheritEnv: boolean,
141-
runnableEnv?: Record<string, string>,
142-
runnableEnvCfg?: Record<string, string>,
143-
): Record<string, string> {
136+
export function prepareEnv(inheritEnv: boolean, runnableEnv?: Env, runnableEnvCfg?: Env): Env {
144137
const env = prepareBaseEnv(inheritEnv, runnableEnv);
145138

146139
if (runnableEnvCfg) {

src/tools/rust-analyzer/editors/code/src/tasks.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as vscode from "vscode";
22
import type { Config } from "./config";
33
import * as toolchain from "./toolchain";
4+
import { Env } from "./util";
45

56
// This ends up as the `type` key in tasks.json. RLS also uses `cargo` and
67
// our configuration should be compatible with it so use the same key.
@@ -117,8 +118,8 @@ export async function buildRustTask(
117118
export async function targetToExecution(
118119
definition: TaskDefinition,
119120
options?: {
120-
env?: { [key: string]: string };
121121
cwd?: string;
122+
env?: Env;
122123
},
123124
cargo?: string,
124125
): Promise<vscode.ProcessExecution | vscode.ShellExecution> {
@@ -131,7 +132,12 @@ export async function targetToExecution(
131132
command = definition.command;
132133
args = definition.args || [];
133134
}
134-
return new vscode.ProcessExecution(command, args, options);
135+
return new vscode.ProcessExecution(command, args, {
136+
cwd: options?.cwd,
137+
env: Object.fromEntries(
138+
Object.entries(options?.env ?? {}).map(([key, value]) => [key, value ?? ""]),
139+
),
140+
});
135141
}
136142

137143
export function activateTaskProvider(config: Config): vscode.Disposable {

src/tools/rust-analyzer/editors/code/src/toolchain.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import * as os from "os";
33
import * as path from "path";
44
import * as readline from "readline";
55
import * as vscode from "vscode";
6-
import { log, memoizeAsync, unwrapUndefinable } from "./util";
6+
import { Env, log, memoizeAsync, unwrapUndefinable } from "./util";
77
import type { CargoRunnableArgs } from "./lsp_ext";
88

99
interface CompilationArtifact {
@@ -37,7 +37,7 @@ interface CompilerMessage {
3737
export class Cargo {
3838
constructor(
3939
readonly rootFolder: string,
40-
readonly env: Record<string, string>,
40+
readonly env: Env,
4141
) {}
4242

4343
// Made public for testing purposes
@@ -156,7 +156,7 @@ export class Cargo {
156156

157157
/** Mirrors `toolchain::cargo()` implementation */
158158
// FIXME: The server should provide this
159-
export function cargoPath(env?: Record<string, string>): Promise<string> {
159+
export function cargoPath(env?: Env): Promise<string> {
160160
if (env?.["RUSTC_TOOLCHAIN"]) {
161161
return Promise.resolve("cargo");
162162
}

0 commit comments

Comments
 (0)