Add user home variable (#141902)

This commit is contained in:
Bruce Hopkins 2022-02-07 16:21:39 +01:00 committed by GitHub
parent 3381e7b20b
commit 1a17c0f2ef
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 39 additions and 14 deletions

View file

@ -69,7 +69,7 @@ class CustomVariableResolver extends AbstractVariableResolverService {
getLineNumber: (): string | undefined => {
return resolvedVariables['lineNumber'];
}
}, undefined, Promise.resolve(env));
}, undefined, Promise.resolve(os.homedir()), Promise.resolve(env));
}
}

View file

@ -941,7 +941,12 @@ export class ExtHostDebugConsole {
export class ExtHostVariableResolverService extends AbstractVariableResolverService {
constructor(folders: vscode.WorkspaceFolder[], editorService: ExtHostDocumentsAndEditors | undefined, configurationService: ExtHostConfigProvider, editorTabs: IExtHostEditorTabs, workspaceService?: IExtHostWorkspace) {
constructor(folders: vscode.WorkspaceFolder[],
editorService: ExtHostDocumentsAndEditors | undefined,
configurationService: ExtHostConfigProvider,
editorTabs: IExtHostEditorTabs,
workspaceService?: IExtHostWorkspace,
userHome?: string) {
function getActiveUri(): URI | undefined {
if (editorService) {
const activeEditor = editorService.activeEditor();
@ -1019,7 +1024,7 @@ export class ExtHostVariableResolverService extends AbstractVariableResolverServ
}
return undefined;
}
}, undefined, Promise.resolve(process.env));
}, undefined, userHome ? Promise.resolve(userHome) : undefined, Promise.resolve(process.env));
}
}

View file

@ -5,6 +5,7 @@
import * as nls from 'vs/nls';
import type * as vscode from 'vscode';
import { homedir } from 'os';
import * as platform from 'vs/base/common/platform';
import { DebugAdapterExecutable, ThemeIcon } from 'vs/workbench/api/common/extHostTypes';
import { ExecutableDebugAdapter, SocketDebugAdapter, NamedPipeDebugAdapter } from 'vs/workbench/contrib/debug/node/debugAdapter';
@ -155,7 +156,7 @@ export class ExtHostDebugService extends ExtHostDebugServiceBase {
}
protected createVariableResolver(folders: vscode.WorkspaceFolder[], editorService: ExtHostDocumentsAndEditors, configurationService: ExtHostConfigProvider): AbstractVariableResolverService {
return new ExtHostVariableResolverService(folders, editorService, configurationService, this._editorTabs, this._workspaceService);
return new ExtHostVariableResolverService(folders, editorService, configurationService, this._editorTabs, this._workspaceService, homedir());
}
}

View file

@ -131,7 +131,7 @@ export class ExtHostTask extends ExtHostTaskBase {
private async getVariableResolver(workspaceFolders: vscode.WorkspaceFolder[]): Promise<ExtHostVariableResolverService> {
if (this._variableResolver === undefined) {
const configProvider = await this._configurationService.getConfigProvider();
this._variableResolver = new ExtHostVariableResolverService(workspaceFolders, this._editorService, configProvider, this.editorTabs, this.workspaceService);
this._variableResolver = new ExtHostVariableResolverService(workspaceFolders, this._editorService, configProvider, this.editorTabs, this.workspaceService, homedir());
}
return this._variableResolver;
}

View file

@ -113,7 +113,7 @@ export abstract class BaseConfigurationResolverService extends AbstractVariableR
}
return undefined;
}
}, labelService, envVariablesPromise);
}, labelService, pathService.userHome().then(home => home.path), envVariablesPromise);
}
public override async resolveWithInteractionReplace(folder: IWorkspaceFolder | undefined, config: any, section?: string, variables?: IStringDictionary<string>, target?: ConfigurationTarget): Promise<any> {

View file

@ -28,6 +28,8 @@ export interface IVariableResolveContext {
getLineNumber(): string | undefined;
}
type Environment = { env?: IProcessEnvironment; userHome?: string };
export class AbstractVariableResolverService implements IConfigurationResolverService {
static readonly VARIABLE_LHS = '${';
@ -38,11 +40,13 @@ export class AbstractVariableResolverService implements IConfigurationResolverSe
private _context: IVariableResolveContext;
private _labelService?: ILabelService;
private _envVariablesPromise?: Promise<IProcessEnvironment>;
private _userHomePromise?: Promise<string>;
protected _contributedVariables: Map<string, () => Promise<string | undefined>> = new Map();
constructor(_context: IVariableResolveContext, _labelService?: ILabelService, _envVariablesPromise?: Promise<IProcessEnvironment>) {
constructor(_context: IVariableResolveContext, _labelService?: ILabelService, _userHomePromise?: Promise<string>, _envVariablesPromise?: Promise<IProcessEnvironment>) {
this._context = _context;
this._labelService = _labelService;
this._userHomePromise = _userHomePromise;
if (_envVariablesPromise) {
this._envVariablesPromise = _envVariablesPromise.then(envVariables => {
return this.prepareEnv(envVariables);
@ -70,7 +74,11 @@ export class AbstractVariableResolverService implements IConfigurationResolverSe
public async resolveAsync(root: IWorkspaceFolder | undefined, value: string[]): Promise<string[]>;
public async resolveAsync(root: IWorkspaceFolder | undefined, value: IStringDictionary<string>): Promise<IStringDictionary<string>>;
public async resolveAsync(root: IWorkspaceFolder | undefined, value: any): Promise<any> {
return this.recursiveResolve(await this._envVariablesPromise, root ? root.uri : undefined, value);
const environment: Environment = {
env: await this._envVariablesPromise,
userHome: await this._userHomePromise
};
return this.recursiveResolve(environment, root ? root.uri : undefined, value);
}
private async resolveAnyBase(workspaceFolder: IWorkspaceFolder | undefined, config: any, commandValueMapping?: IStringDictionary<string>, resolvedVariables?: Map<string, string>): Promise<any> {
@ -92,7 +100,11 @@ export class AbstractVariableResolverService implements IConfigurationResolverSe
delete result.linux;
// substitute all variables recursively in string values
return this.recursiveResolve(await this._envVariablesPromise, workspaceFolder ? workspaceFolder.uri : undefined, result, commandValueMapping, resolvedVariables);
const environmentPromises: Environment = {
env: await this._envVariablesPromise,
userHome: await this._userHomePromise
};
return this.recursiveResolve(environmentPromises, workspaceFolder ? workspaceFolder.uri : undefined, result, commandValueMapping, resolvedVariables);
}
public async resolveAnyAsync(workspaceFolder: IWorkspaceFolder | undefined, config: any, commandValueMapping?: IStringDictionary<string>): Promise<any> {
@ -121,7 +133,7 @@ export class AbstractVariableResolverService implements IConfigurationResolverSe
}
}
private recursiveResolve(environment: IProcessEnvironment | undefined, folderUri: uri | undefined, value: any, commandValueMapping?: IStringDictionary<string>, resolvedVariables?: Map<string, string>): any {
private recursiveResolve(environment: Environment, folderUri: uri | undefined, value: any, commandValueMapping?: IStringDictionary<string>, resolvedVariables?: Map<string, string>): any {
if (types.isString(value)) {
return this.resolveString(environment, folderUri, value, commandValueMapping, resolvedVariables);
} else if (types.isArray(value)) {
@ -137,7 +149,7 @@ export class AbstractVariableResolverService implements IConfigurationResolverSe
return value;
}
private resolveString(environment: IProcessEnvironment | undefined, folderUri: uri | undefined, value: string, commandValueMapping: IStringDictionary<string> | undefined, resolvedVariables?: Map<string, string>): string {
private resolveString(environment: Environment, folderUri: uri | undefined, value: string, commandValueMapping: IStringDictionary<string> | undefined, resolvedVariables?: Map<string, string>): string {
// loop through all variables occurrences in 'value'
const replaced = value.replace(AbstractVariableResolverService.VARIABLE_REGEXP, (match: string, variable: string) => {
@ -166,7 +178,7 @@ export class AbstractVariableResolverService implements IConfigurationResolverSe
return this._labelService ? this._labelService.getUriLabel(displayUri, { noPrefix: true }) : displayUri.fsPath;
}
private evaluateSingleVariable(environment: IProcessEnvironment | undefined, match: string, variable: string, folderUri: uri | undefined, commandValueMapping: IStringDictionary<string> | undefined): string {
private evaluateSingleVariable(environment: Environment, match: string, variable: string, folderUri: uri | undefined, commandValueMapping: IStringDictionary<string> | undefined): string {
// try to separate variable arguments from variable name
let argument: string | undefined;
@ -225,9 +237,9 @@ export class AbstractVariableResolverService implements IConfigurationResolverSe
case 'env':
if (argument) {
if (environment) {
if (environment.env) {
// Depending on the source of the environment, on Windows, the values may all be lowercase.
const env = environment[isWindows ? argument.toLowerCase() : argument];
const env = environment.env[isWindows ? argument.toLowerCase() : argument];
if (types.isString(env)) {
return env;
}
@ -270,6 +282,13 @@ export class AbstractVariableResolverService implements IConfigurationResolverSe
case 'workspaceFolderBasename':
return paths.basename(this.fsPath(getFolderUri()));
case 'userHome': {
if (environment.userHome) {
return environment.userHome;
}
throw new Error(localize('canNotResolveUserHome', "Variable {0} can not be resolved. UserHome path is not defined", match));
}
case 'lineNumber': {
const lineNumber = this._context.getLineNumber();
if (lineNumber) {