VSCode variables support for substitutions

Tests now open Rust-Analyzer extension code in order to populate
VSCode variables.
This commit is contained in:
Andrei Listochkin 2022-05-11 13:34:43 +01:00
parent 6c769ac00d
commit 684fa2794f
3 changed files with 63 additions and 2 deletions

View file

@ -1,3 +1,4 @@
import path = require('path');
import * as vscode from 'vscode';
import { Env } from './client';
import { log } from "./util";
@ -253,7 +254,10 @@ export function substituteVariablesInEnv(env: Env): Env {
resolved.add(dep);
}
} else {
// TODO: handle VSCode variables
envWithDeps[dep] = {
value: computeVscodeVar(dep),
deps: []
};
}
}
const toResolve = new Set(Object.keys(envWithDeps));
@ -279,3 +283,52 @@ export function substituteVariablesInEnv(env: Env): Env {
}
return resolvedEnv;
}
function computeVscodeVar(varName: string): string {
// https://code.visualstudio.com/docs/editor/variables-reference
const supportedVariables: { [k: string]: () => string } = {
workspaceFolder: () => {
const folders = vscode.workspace.workspaceFolders ?? [];
if (folders.length === 1) {
// TODO: support for remote workspaces?
return folders[0].uri.fsPath;
} else if (folders.length > 1) {
// could use currently opened document to detect the correct
// workspace. However, that would be determined by the document
// user has opened on Editor startup. Could lead to
// unpredictable workspace selection in practice.
// It's better to pick the first one
return folders[0].uri.fsPath;
} else {
// no workspace opened
return '';
}
},
workspaceFolderBasename: () => {
const workspaceFolder = computeVscodeVar('workspaceFolder');
if (workspaceFolder) {
return path.basename(workspaceFolder);
} else {
return '';
}
},
cwd: () => process.cwd(),
// see
// https://github.com/microsoft/vscode/blob/08ac1bb67ca2459496b272d8f4a908757f24f56f/src/vs/workbench/api/common/extHostVariableResolverService.ts#L81
// or
// https://github.com/microsoft/vscode/blob/29eb316bb9f154b7870eb5204ec7f2e7cf649bec/src/vs/server/node/remoteTerminalChannel.ts#L56
execPath: () => process.env.VSCODE_EXEC_PATH ?? process.execPath,
pathSeparator: () => path.sep
};
if (varName in supportedVariables) {
return supportedVariables[varName]();
} else {
// can't resolve, keep the expression as is
return '${' + varName + '}';
}
}

View file

@ -14,7 +14,7 @@ async function main() {
let minimalVersion: string = json.engines.vscode;
if (minimalVersion.startsWith('^')) minimalVersion = minimalVersion.slice(1);
const launchArgs = ["--disable-extensions"];
const launchArgs = ["--disable-extensions", extensionDevelopmentPath];
// All test suites (either unit tests or integration tests) should be in subfolders.
const extensionTestsPath = path.resolve(__dirname, './unit/index');

View file

@ -49,5 +49,13 @@ export async function getTests(ctx: Context) {
const actualEnv = await substituteVariablesInEnv(envJson);
assert.deepStrictEqual(actualEnv, expectedEnv);
});
suite.addTest('should support VSCode variables', async () => {
const envJson = {
USING_VSCODE_VAR: "${workspaceFolderBasename}"
};
const actualEnv = await substituteVariablesInEnv(envJson);
assert.deepStrictEqual(actualEnv.USING_VSCODE_VAR, 'code');
});
});
}