mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-08-04 10:50:15 +00:00
feat: Allow unsetting env vars in server.extraEnv
config
This commit is contained in:
parent
66e3b5819e
commit
05b374acd4
5 changed files with 38 additions and 20 deletions
|
@ -543,7 +543,8 @@
|
|||
"additionalProperties": {
|
||||
"type": [
|
||||
"string",
|
||||
"number"
|
||||
"number",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"default": null,
|
||||
|
|
|
@ -187,8 +187,16 @@ async function hasToolchainFileWithRaDeclared(uri: vscode.Uri): Promise<boolean>
|
|||
export async function isValidExecutable(path: string, extraEnv: Env): Promise<boolean> {
|
||||
log.debug("Checking availability of a binary at", path);
|
||||
|
||||
const newEnv = { ...process.env };
|
||||
for (const [k, v] of Object.entries(extraEnv)) {
|
||||
if (v) {
|
||||
newEnv[k] = v;
|
||||
} else if (k in newEnv) {
|
||||
delete newEnv[k];
|
||||
}
|
||||
}
|
||||
const res = await spawnAsync(path, ["--version"], {
|
||||
env: { ...process.env, ...extraEnv },
|
||||
env: newEnv,
|
||||
});
|
||||
|
||||
if (res.error) {
|
||||
|
|
|
@ -213,12 +213,13 @@ export class Config {
|
|||
|
||||
get serverExtraEnv(): Env {
|
||||
const extraEnv =
|
||||
this.get<{ [key: string]: string | number } | null>("server.extraEnv") ?? {};
|
||||
this.get<{ [key: string]: { toString(): string } | null } | null>("server.extraEnv") ??
|
||||
{};
|
||||
return substituteVariablesInEnv(
|
||||
Object.fromEntries(
|
||||
Object.entries(extraEnv).map(([k, v]) => [
|
||||
k,
|
||||
typeof v !== "string" ? v.toString() : v,
|
||||
typeof v === "string" ? v : v?.toString(),
|
||||
]),
|
||||
),
|
||||
);
|
||||
|
@ -398,6 +399,7 @@ export function prepareVSCodeConfig<T>(resp: T): T {
|
|||
|
||||
// FIXME: Merge this with `substituteVSCodeVariables` above
|
||||
export function substituteVariablesInEnv(env: Env): Env {
|
||||
const depRe = new RegExp(/\${(?<depName>.+?)}/g);
|
||||
const missingDeps = new Set<string>();
|
||||
// vscode uses `env:ENV_NAME` for env vars resolution, and it's easier
|
||||
// to follow the same convention for our dependency tracking
|
||||
|
@ -405,15 +407,16 @@ export function substituteVariablesInEnv(env: Env): Env {
|
|||
const envWithDeps = Object.fromEntries(
|
||||
Object.entries(env).map(([key, value]) => {
|
||||
const deps = new Set<string>();
|
||||
const depRe = new RegExp(/\${(?<depName>.+?)}/g);
|
||||
let match = undefined;
|
||||
while ((match = depRe.exec(value))) {
|
||||
const depName = unwrapUndefinable(match.groups?.["depName"]);
|
||||
deps.add(depName);
|
||||
// `depName` at this point can have a form of `expression` or
|
||||
// `prefix:expression`
|
||||
if (!definedEnvKeys.has(depName)) {
|
||||
missingDeps.add(depName);
|
||||
if (value) {
|
||||
let match = undefined;
|
||||
while ((match = depRe.exec(value))) {
|
||||
const depName = unwrapUndefinable(match.groups?.["depName"]);
|
||||
deps.add(depName);
|
||||
// `depName` at this point can have a form of `expression` or
|
||||
// `prefix:expression`
|
||||
if (!definedEnvKeys.has(depName)) {
|
||||
missingDeps.add(depName);
|
||||
}
|
||||
}
|
||||
}
|
||||
return [`env:${key}`, { deps: [...deps], value }];
|
||||
|
@ -454,11 +457,10 @@ export function substituteVariablesInEnv(env: Env): Env {
|
|||
do {
|
||||
leftToResolveSize = toResolve.size;
|
||||
for (const key of toResolve) {
|
||||
const item = unwrapUndefinable(envWithDeps[key]);
|
||||
if (item.deps.every((dep) => resolved.has(dep))) {
|
||||
item.value = item.value.replace(/\${(?<depName>.+?)}/g, (_wholeMatch, depName) => {
|
||||
const item = unwrapUndefinable(envWithDeps[depName]);
|
||||
return item.value;
|
||||
const item = envWithDeps[key];
|
||||
if (item && item.deps.every((dep) => resolved.has(dep))) {
|
||||
item.value = item.value?.replace(/\${(?<depName>.+?)}/g, (_wholeMatch, depName) => {
|
||||
return envWithDeps[depName]?.value ?? "";
|
||||
});
|
||||
resolved.add(key);
|
||||
toResolve.delete(key);
|
||||
|
|
|
@ -213,7 +213,14 @@ export class Ctx implements RustAnalyzerExtensionApi {
|
|||
this.refreshServerStatus();
|
||||
},
|
||||
);
|
||||
const newEnv = Object.assign({}, process.env, this.config.serverExtraEnv);
|
||||
const newEnv = { ...process.env };
|
||||
for (const [k, v] of Object.entries(this.config.serverExtraEnv)) {
|
||||
if (v) {
|
||||
newEnv[k] = v;
|
||||
} else if (k in newEnv) {
|
||||
delete newEnv[k];
|
||||
}
|
||||
}
|
||||
const run: lc.Executable = {
|
||||
command: this._serverPath,
|
||||
options: { env: newEnv },
|
||||
|
|
|
@ -14,7 +14,7 @@ export function assert(condition: boolean, explanation: string): asserts conditi
|
|||
}
|
||||
|
||||
export type Env = {
|
||||
[name: string]: string;
|
||||
[name: string]: string | undefined;
|
||||
};
|
||||
|
||||
class Log {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue