mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 11:31:15 +00:00
Merge pull request #20313 from Veykril/push-qmorsnlvwlrr
fix: Fix runnables extra env not substituting env vars
This commit is contained in:
commit
5c479edc49
@ -8,10 +8,9 @@ import type { Disposable } from "vscode";
|
|||||||
|
|
||||||
export type RunnableEnvCfgItem = {
|
export type RunnableEnvCfgItem = {
|
||||||
mask?: string;
|
mask?: string;
|
||||||
env: Record<string, string>;
|
env: { [key: string]: { toString(): string } | null };
|
||||||
platform?: string | string[];
|
platform?: string | string[];
|
||||||
};
|
};
|
||||||
export type RunnableEnvCfg = Record<string, string> | RunnableEnvCfgItem[];
|
|
||||||
|
|
||||||
type ShowStatusBar = "always" | "never" | { documentSelector: vscode.DocumentSelector };
|
type ShowStatusBar = "always" | "never" | { documentSelector: vscode.DocumentSelector };
|
||||||
|
|
||||||
@ -261,18 +260,13 @@ export class Config {
|
|||||||
return this.get<boolean | undefined>("testExplorer");
|
return this.get<boolean | undefined>("testExplorer");
|
||||||
}
|
}
|
||||||
|
|
||||||
runnablesExtraEnv(label: string): Record<string, string> | undefined {
|
runnablesExtraEnv(label: string): Env {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
const serverEnv = this.serverExtraEnv;
|
||||||
const item = this.get<any>("runnables.extraEnv") ?? this.get<any>("runnableEnv");
|
let extraEnv =
|
||||||
if (!item) return undefined;
|
this.get<
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
RunnableEnvCfgItem[] | { [key: string]: { toString(): string } | null } | null
|
||||||
const fixRecord = (r: Record<string, any>) => {
|
>("runnables.extraEnv") ?? {};
|
||||||
for (const key in r) {
|
if (!extraEnv) return serverEnv;
|
||||||
if (typeof r[key] !== "string") {
|
|
||||||
r[key] = String(r[key]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const platform = process.platform;
|
const platform = process.platform;
|
||||||
const checkPlatform = (it: RunnableEnvCfgItem) => {
|
const checkPlatform = (it: RunnableEnvCfgItem) => {
|
||||||
@ -283,19 +277,25 @@ export class Config {
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (item instanceof Array) {
|
if (extraEnv instanceof Array) {
|
||||||
const env = {};
|
const env = {};
|
||||||
for (const it of item) {
|
for (const it of extraEnv) {
|
||||||
const masked = !it.mask || new RegExp(it.mask).test(label);
|
const masked = !it.mask || new RegExp(it.mask).test(label);
|
||||||
if (masked && checkPlatform(it)) {
|
if (masked && checkPlatform(it)) {
|
||||||
Object.assign(env, it.env);
|
Object.assign(env, it.env);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fixRecord(env);
|
extraEnv = env;
|
||||||
return env;
|
|
||||||
}
|
}
|
||||||
fixRecord(item);
|
const runnableExtraEnv = substituteVariablesInEnv(
|
||||||
return item;
|
Object.fromEntries(
|
||||||
|
Object.entries(extraEnv).map(([k, v]) => [
|
||||||
|
k,
|
||||||
|
typeof v === "string" ? v : v?.toString(),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return { ...runnableExtraEnv, ...serverEnv };
|
||||||
}
|
}
|
||||||
|
|
||||||
get restartServerOnConfigChange() {
|
get restartServerOnConfigChange() {
|
||||||
|
@ -6,7 +6,14 @@ import type * as ra from "./lsp_ext";
|
|||||||
import { Cargo } from "./toolchain";
|
import { Cargo } from "./toolchain";
|
||||||
import type { Ctx } from "./ctx";
|
import type { Ctx } from "./ctx";
|
||||||
import { createTaskFromRunnable, prepareEnv } from "./run";
|
import { createTaskFromRunnable, prepareEnv } from "./run";
|
||||||
import { execute, isCargoRunnableArgs, unwrapUndefinable, log, normalizeDriveLetter } from "./util";
|
import {
|
||||||
|
execute,
|
||||||
|
isCargoRunnableArgs,
|
||||||
|
unwrapUndefinable,
|
||||||
|
log,
|
||||||
|
normalizeDriveLetter,
|
||||||
|
Env,
|
||||||
|
} from "./util";
|
||||||
import type { Config } from "./config";
|
import type { Config } from "./config";
|
||||||
|
|
||||||
// Here we want to keep track on everything that's currently running
|
// Here we want to keep track on everything that's currently running
|
||||||
@ -206,10 +213,7 @@ type SourceFileMap = {
|
|||||||
destination: string;
|
destination: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
async function discoverSourceFileMap(
|
async function discoverSourceFileMap(env: Env, cwd: string): Promise<SourceFileMap | undefined> {
|
||||||
env: Record<string, string>,
|
|
||||||
cwd: string,
|
|
||||||
): Promise<SourceFileMap | undefined> {
|
|
||||||
const sysroot = env["RUSTC_TOOLCHAIN"];
|
const sysroot = env["RUSTC_TOOLCHAIN"];
|
||||||
if (sysroot) {
|
if (sysroot) {
|
||||||
// let's try to use the default toolchain
|
// let's try to use the default toolchain
|
||||||
@ -232,7 +236,7 @@ type PropertyFetcher<Config, Input, Key extends keyof Config> = (
|
|||||||
|
|
||||||
type DebugConfigProvider<Type extends string, DebugConfig extends BaseDebugConfig<Type>> = {
|
type DebugConfigProvider<Type extends string, DebugConfig extends BaseDebugConfig<Type>> = {
|
||||||
executableProperty: keyof DebugConfig;
|
executableProperty: keyof DebugConfig;
|
||||||
environmentProperty: PropertyFetcher<DebugConfig, Record<string, string>, keyof DebugConfig>;
|
environmentProperty: PropertyFetcher<DebugConfig, Env, keyof DebugConfig>;
|
||||||
runnableArgsProperty: PropertyFetcher<DebugConfig, ra.CargoRunnableArgs, keyof DebugConfig>;
|
runnableArgsProperty: PropertyFetcher<DebugConfig, ra.CargoRunnableArgs, keyof DebugConfig>;
|
||||||
sourceFileMapProperty?: keyof DebugConfig;
|
sourceFileMapProperty?: keyof DebugConfig;
|
||||||
type: Type;
|
type: Type;
|
||||||
@ -276,7 +280,7 @@ const knownEngines: {
|
|||||||
"environment",
|
"environment",
|
||||||
Object.entries(env).map((entry) => ({
|
Object.entries(env).map((entry) => ({
|
||||||
name: entry[0],
|
name: entry[0],
|
||||||
value: entry[1],
|
value: entry[1] ?? "",
|
||||||
})),
|
})),
|
||||||
],
|
],
|
||||||
runnableArgsProperty: (runnableArgs: ra.CargoRunnableArgs) => [
|
runnableArgsProperty: (runnableArgs: ra.CargoRunnableArgs) => [
|
||||||
@ -304,10 +308,7 @@ const knownEngines: {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
async function getDebugExecutable(
|
async function getDebugExecutable(runnableArgs: ra.CargoRunnableArgs, env: Env): Promise<string> {
|
||||||
runnableArgs: ra.CargoRunnableArgs,
|
|
||||||
env: Record<string, string>,
|
|
||||||
): Promise<string> {
|
|
||||||
const cargo = new Cargo(runnableArgs.workspaceRoot || ".", env);
|
const cargo = new Cargo(runnableArgs.workspaceRoot || ".", env);
|
||||||
const executable = await cargo.executableFromArgs(runnableArgs);
|
const executable = await cargo.executableFromArgs(runnableArgs);
|
||||||
|
|
||||||
@ -328,7 +329,7 @@ function getDebugConfig(
|
|||||||
runnable: ra.Runnable,
|
runnable: ra.Runnable,
|
||||||
runnableArgs: ra.CargoRunnableArgs,
|
runnableArgs: ra.CargoRunnableArgs,
|
||||||
executable: string,
|
executable: string,
|
||||||
env: Record<string, string>,
|
env: Env,
|
||||||
sourceFileMap?: Record<string, string>,
|
sourceFileMap?: Record<string, string>,
|
||||||
): vscode.DebugConfiguration {
|
): vscode.DebugConfiguration {
|
||||||
const {
|
const {
|
||||||
@ -380,14 +381,14 @@ type CodeLldbDebugConfig = {
|
|||||||
args: string[];
|
args: string[];
|
||||||
sourceMap: Record<string, string> | undefined;
|
sourceMap: Record<string, string> | undefined;
|
||||||
sourceLanguages: ["rust"];
|
sourceLanguages: ["rust"];
|
||||||
env: Record<string, string>;
|
env: Env;
|
||||||
} & BaseDebugConfig<"lldb">;
|
} & BaseDebugConfig<"lldb">;
|
||||||
|
|
||||||
type NativeDebugConfig = {
|
type NativeDebugConfig = {
|
||||||
target: string;
|
target: string;
|
||||||
// See https://github.com/WebFreak001/code-debug/issues/359
|
// See https://github.com/WebFreak001/code-debug/issues/359
|
||||||
arguments: string;
|
arguments: string;
|
||||||
env: Record<string, string>;
|
env: Env;
|
||||||
valuesFormatting: "prettyPrinters";
|
valuesFormatting: "prettyPrinters";
|
||||||
} & BaseDebugConfig<"gdb">;
|
} & BaseDebugConfig<"gdb">;
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ import type { CtxInit } from "./ctx";
|
|||||||
import { makeDebugConfig } from "./debug";
|
import { makeDebugConfig } from "./debug";
|
||||||
import type { Config } from "./config";
|
import type { Config } from "./config";
|
||||||
import type { LanguageClient } from "vscode-languageclient/node";
|
import type { LanguageClient } from "vscode-languageclient/node";
|
||||||
import { log, unwrapUndefinable, type RustEditor } from "./util";
|
import { Env, log, unwrapUndefinable, type RustEditor } from "./util";
|
||||||
|
|
||||||
const quickPickButtons = [
|
const quickPickButtons = [
|
||||||
{ iconPath: new vscode.ThemeIcon("save"), tooltip: "Save as a launch.json configuration." },
|
{ iconPath: new vscode.ThemeIcon("save"), tooltip: "Save as a launch.json configuration." },
|
||||||
@ -122,11 +122,8 @@ export class RunnableQuickPick implements vscode.QuickPickItem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function prepareBaseEnv(
|
export function prepareBaseEnv(inheritEnv: boolean, base?: Env): Env {
|
||||||
inheritEnv: boolean,
|
const env: Env = { RUST_BACKTRACE: "short" };
|
||||||
base?: Record<string, string>,
|
|
||||||
): Record<string, string> {
|
|
||||||
const env: Record<string, string> = { RUST_BACKTRACE: "short" };
|
|
||||||
if (inheritEnv) {
|
if (inheritEnv) {
|
||||||
Object.assign(env, process.env);
|
Object.assign(env, process.env);
|
||||||
}
|
}
|
||||||
@ -136,11 +133,7 @@ export function prepareBaseEnv(
|
|||||||
return env;
|
return env;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function prepareEnv(
|
export function prepareEnv(inheritEnv: boolean, runnableEnv?: Env, runnableEnvCfg?: Env): Env {
|
||||||
inheritEnv: boolean,
|
|
||||||
runnableEnv?: Record<string, string>,
|
|
||||||
runnableEnvCfg?: Record<string, string>,
|
|
||||||
): Record<string, string> {
|
|
||||||
const env = prepareBaseEnv(inheritEnv, runnableEnv);
|
const env = prepareBaseEnv(inheritEnv, runnableEnv);
|
||||||
|
|
||||||
if (runnableEnvCfg) {
|
if (runnableEnvCfg) {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import * as vscode from "vscode";
|
import * as vscode from "vscode";
|
||||||
import type { Config } from "./config";
|
import type { Config } from "./config";
|
||||||
import * as toolchain from "./toolchain";
|
import * as toolchain from "./toolchain";
|
||||||
|
import { Env } from "./util";
|
||||||
|
|
||||||
// This ends up as the `type` key in tasks.json. RLS also uses `cargo` and
|
// This ends up as the `type` key in tasks.json. RLS also uses `cargo` and
|
||||||
// our configuration should be compatible with it so use the same key.
|
// our configuration should be compatible with it so use the same key.
|
||||||
@ -117,8 +118,8 @@ export async function buildRustTask(
|
|||||||
export async function targetToExecution(
|
export async function targetToExecution(
|
||||||
definition: TaskDefinition,
|
definition: TaskDefinition,
|
||||||
options?: {
|
options?: {
|
||||||
env?: { [key: string]: string };
|
|
||||||
cwd?: string;
|
cwd?: string;
|
||||||
|
env?: Env;
|
||||||
},
|
},
|
||||||
cargo?: string,
|
cargo?: string,
|
||||||
): Promise<vscode.ProcessExecution | vscode.ShellExecution> {
|
): Promise<vscode.ProcessExecution | vscode.ShellExecution> {
|
||||||
@ -131,7 +132,12 @@ export async function targetToExecution(
|
|||||||
command = definition.command;
|
command = definition.command;
|
||||||
args = definition.args || [];
|
args = definition.args || [];
|
||||||
}
|
}
|
||||||
return new vscode.ProcessExecution(command, args, options);
|
return new vscode.ProcessExecution(command, args, {
|
||||||
|
cwd: options?.cwd,
|
||||||
|
env: Object.fromEntries(
|
||||||
|
Object.entries(options?.env ?? {}).map(([key, value]) => [key, value ?? ""]),
|
||||||
|
),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function activateTaskProvider(config: Config): vscode.Disposable {
|
export function activateTaskProvider(config: Config): vscode.Disposable {
|
||||||
|
@ -3,7 +3,7 @@ import * as os from "os";
|
|||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
import * as readline from "readline";
|
import * as readline from "readline";
|
||||||
import * as vscode from "vscode";
|
import * as vscode from "vscode";
|
||||||
import { log, memoizeAsync, unwrapUndefinable } from "./util";
|
import { Env, log, memoizeAsync, unwrapUndefinable } from "./util";
|
||||||
import type { CargoRunnableArgs } from "./lsp_ext";
|
import type { CargoRunnableArgs } from "./lsp_ext";
|
||||||
|
|
||||||
interface CompilationArtifact {
|
interface CompilationArtifact {
|
||||||
@ -37,7 +37,7 @@ interface CompilerMessage {
|
|||||||
export class Cargo {
|
export class Cargo {
|
||||||
constructor(
|
constructor(
|
||||||
readonly rootFolder: string,
|
readonly rootFolder: string,
|
||||||
readonly env: Record<string, string>,
|
readonly env: Env,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
// Made public for testing purposes
|
// Made public for testing purposes
|
||||||
@ -156,7 +156,7 @@ export class Cargo {
|
|||||||
|
|
||||||
/** Mirrors `toolchain::cargo()` implementation */
|
/** Mirrors `toolchain::cargo()` implementation */
|
||||||
// FIXME: The server should provide this
|
// FIXME: The server should provide this
|
||||||
export function cargoPath(env?: Record<string, string>): Promise<string> {
|
export function cargoPath(env?: Env): Promise<string> {
|
||||||
if (env?.["RUSTC_TOOLCHAIN"]) {
|
if (env?.["RUSTC_TOOLCHAIN"]) {
|
||||||
return Promise.resolve("cargo");
|
return Promise.resolve("cargo");
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user