in patched-vscode/src/vs/workbench/services/configurationResolver/common/variableResolver.ts [182:384]
private async evaluateSingleVariable(environment: Environment, match: string, variable: string, folderUri: uri | undefined, commandValueMapping: IStringDictionary<string> | undefined): Promise<string> {
// try to separate variable arguments from variable name
let argument: string | undefined;
const parts = variable.split(':');
if (parts.length > 1) {
variable = parts[0];
argument = parts[1];
}
// common error handling for all variables that require an open editor
const getFilePath = (variableKind: VariableKind): string => {
const filePath = this._context.getFilePath();
if (filePath) {
return normalizeDriveLetter(filePath);
}
throw new VariableError(variableKind, (localize('canNotResolveFile', "Variable {0} can not be resolved. Please open an editor.", match)));
};
// common error handling for all variables that require an open editor
const getFolderPathForFile = (variableKind: VariableKind): string => {
const filePath = getFilePath(variableKind); // throws error if no editor open
if (this._context.getWorkspaceFolderPathForFile) {
const folderPath = this._context.getWorkspaceFolderPathForFile();
if (folderPath) {
return normalizeDriveLetter(folderPath);
}
}
throw new VariableError(variableKind, localize('canNotResolveFolderForFile', "Variable {0}: can not find workspace folder of '{1}'.", match, paths.basename(filePath)));
};
// common error handling for all variables that require an open folder and accept a folder name argument
const getFolderUri = (variableKind: VariableKind): uri => {
if (argument) {
const folder = this._context.getFolderUri(argument);
if (folder) {
return folder;
}
throw new VariableError(variableKind, localize('canNotFindFolder', "Variable {0} can not be resolved. No such folder '{1}'.", match, argument));
}
if (folderUri) {
return folderUri;
}
if (this._context.getWorkspaceFolderCount() > 1) {
throw new VariableError(variableKind, localize('canNotResolveWorkspaceFolderMultiRoot', "Variable {0} can not be resolved in a multi folder workspace. Scope this variable using ':' and a workspace folder name.", match));
}
throw new VariableError(variableKind, localize('canNotResolveWorkspaceFolder', "Variable {0} can not be resolved. Please open a folder.", match));
};
switch (variable) {
case 'env':
if (argument) {
if (environment.env) {
// Depending on the source of the environment, on Windows, the values may all be lowercase.
const env = environment.env[isWindows ? argument.toLowerCase() : argument];
if (types.isString(env)) {
return env;
}
}
// For `env` we should do the same as a normal shell does - evaluates undefined envs to an empty string #46436
return '';
}
throw new VariableError(VariableKind.Env, localize('missingEnvVarName', "Variable {0} can not be resolved because no environment variable name is given.", match));
case 'config':
if (argument) {
const config = this._context.getConfigurationValue(folderUri, argument);
if (types.isUndefinedOrNull(config)) {
throw new VariableError(VariableKind.Config, localize('configNotFound', "Variable {0} can not be resolved because setting '{1}' not found.", match, argument));
}
if (types.isObject(config)) {
throw new VariableError(VariableKind.Config, localize('configNoString', "Variable {0} can not be resolved because '{1}' is a structured value.", match, argument));
}
return config;
}
throw new VariableError(VariableKind.Config, localize('missingConfigName', "Variable {0} can not be resolved because no settings name is given.", match));
case 'command':
return this.resolveFromMap(VariableKind.Command, match, argument, commandValueMapping, 'command');
case 'input':
return this.resolveFromMap(VariableKind.Input, match, argument, commandValueMapping, 'input');
case 'extensionInstallFolder':
if (argument) {
const ext = await this._context.getExtension(argument);
if (!ext) {
throw new VariableError(VariableKind.ExtensionInstallFolder, localize('extensionNotInstalled', "Variable {0} can not be resolved because the extension {1} is not installed.", match, argument));
}
return this.fsPath(ext.extensionLocation);
}
throw new VariableError(VariableKind.ExtensionInstallFolder, localize('missingExtensionName', "Variable {0} can not be resolved because no extension name is given.", match));
default: {
switch (variable) {
case 'workspaceRoot':
case 'workspaceFolder':
return normalizeDriveLetter(this.fsPath(getFolderUri(VariableKind.WorkspaceFolder)));
case 'cwd':
return ((folderUri || argument) ? normalizeDriveLetter(this.fsPath(getFolderUri(VariableKind.Cwd))) : process.cwd());
case 'workspaceRootFolderName':
case 'workspaceFolderBasename':
return normalizeDriveLetter(paths.basename(this.fsPath(getFolderUri(VariableKind.WorkspaceFolderBasename))));
case 'userHome': {
if (environment.userHome) {
return environment.userHome;
}
throw new VariableError(VariableKind.UserHome, localize('canNotResolveUserHome', "Variable {0} can not be resolved. UserHome path is not defined", match));
}
case 'lineNumber': {
const lineNumber = this._context.getLineNumber();
if (lineNumber) {
return lineNumber;
}
throw new VariableError(VariableKind.LineNumber, localize('canNotResolveLineNumber', "Variable {0} can not be resolved. Make sure to have a line selected in the active editor.", match));
}
case 'selectedText': {
const selectedText = this._context.getSelectedText();
if (selectedText) {
return selectedText;
}
throw new VariableError(VariableKind.SelectedText, localize('canNotResolveSelectedText', "Variable {0} can not be resolved. Make sure to have some text selected in the active editor.", match));
}
case 'file':
return getFilePath(VariableKind.File);
case 'fileWorkspaceFolder':
return getFolderPathForFile(VariableKind.FileWorkspaceFolder);
case 'fileWorkspaceFolderBasename':
return paths.basename(getFolderPathForFile(VariableKind.FileWorkspaceFolderBasename));
case 'relativeFile':
if (folderUri || argument) {
return paths.relative(this.fsPath(getFolderUri(VariableKind.RelativeFile)), getFilePath(VariableKind.RelativeFile));
}
return getFilePath(VariableKind.RelativeFile);
case 'relativeFileDirname': {
const dirname = paths.dirname(getFilePath(VariableKind.RelativeFileDirname));
if (folderUri || argument) {
const relative = paths.relative(this.fsPath(getFolderUri(VariableKind.RelativeFileDirname)), dirname);
return relative.length === 0 ? '.' : relative;
}
return dirname;
}
case 'fileDirname':
return paths.dirname(getFilePath(VariableKind.FileDirname));
case 'fileExtname':
return paths.extname(getFilePath(VariableKind.FileExtname));
case 'fileBasename':
return paths.basename(getFilePath(VariableKind.FileBasename));
case 'fileBasenameNoExtension': {
const basename = paths.basename(getFilePath(VariableKind.FileBasenameNoExtension));
return (basename.slice(0, basename.length - paths.extname(basename).length));
}
case 'fileDirnameBasename':
return paths.basename(paths.dirname(getFilePath(VariableKind.FileDirnameBasename)));
case 'execPath': {
const ep = this._context.getExecPath();
if (ep) {
return ep;
}
return match;
}
case 'execInstallFolder': {
const ar = this._context.getAppRoot();
if (ar) {
return ar;
}
return match;
}
case 'pathSeparator':
case '/':
return paths.sep;
default:
try {
const key = argument ? `${variable}:${argument}` : variable;
return this.resolveFromMap(VariableKind.Unknown, match, key, commandValueMapping, undefined);
} catch (error) {
return match;
}
}
}
}
}