mirror of
https://github.com/Microsoft/vscode
synced 2024-09-13 13:46:13 +00:00
parent
c5bf12802f
commit
9dbc765a38
|
@ -945,6 +945,9 @@ export class ExtHostVariableResolverService extends AbstractVariableResolverServ
|
|||
getConfigurationValue: (folderUri: URI | undefined, section: string): string | undefined => {
|
||||
return configurationService.getConfiguration(undefined, folderUri).get<string>(section);
|
||||
},
|
||||
getAppRoot: (): string | undefined => {
|
||||
return env ? env['VSCODE_CWD'] : undefined;
|
||||
},
|
||||
getExecPath: (): string | undefined => {
|
||||
return env ? env['VSCODE_EXEC_PATH'] : undefined;
|
||||
},
|
||||
|
|
|
@ -201,10 +201,11 @@ export class ExtHostTerminalService extends BaseExtHostTerminalService {
|
|||
|
||||
const envFromConfig = this._apiInspectConfigToPlain(configProvider.getConfiguration('terminal.integrated').inspect<ITerminalEnvironment>(`env.${platformKey}`));
|
||||
const baseEnv = terminalConfig.get<boolean>('inheritEnv', true) ? process.env as platform.IProcessEnvironment : await this._getNonInheritedEnv();
|
||||
const variableResolver = terminalEnvironment.createVariableResolver(lastActiveWorkspace, this._variableResolver);
|
||||
const env = terminalEnvironment.createTerminalEnvironment(
|
||||
shellLaunchConfig,
|
||||
envFromConfig,
|
||||
terminalEnvironment.createVariableResolver(lastActiveWorkspace, this._variableResolver),
|
||||
variableResolver,
|
||||
isWorkspaceShellAllowed,
|
||||
this._extHostInitDataService.version,
|
||||
terminalConfig.get<'auto' | 'off' | 'on'>('detectLocale', 'auto'),
|
||||
|
@ -214,7 +215,7 @@ export class ExtHostTerminalService extends BaseExtHostTerminalService {
|
|||
// Apply extension environment variable collections to the environment
|
||||
if (!shellLaunchConfig.strictEnv) {
|
||||
const mergedCollection = new MergedEnvironmentVariableCollection(this._environmentVariableCollections);
|
||||
mergedCollection.applyToProcessEnvironment(env);
|
||||
mergedCollection.applyToProcessEnvironment(env, variableResolver);
|
||||
}
|
||||
|
||||
this._proxy.$sendResolvedLaunchConfig(id, shellLaunchConfig);
|
||||
|
|
|
@ -248,7 +248,8 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce
|
|||
const isWorkspaceShellAllowed = this._configHelper.checkWorkspaceShellPermissions();
|
||||
this._configHelper.showRecommendations(shellLaunchConfig);
|
||||
const baseEnv = this._configHelper.config.inheritEnv ? processEnv : await this._terminalInstanceService.getMainProcessParentEnv();
|
||||
const env = terminalEnvironment.createTerminalEnvironment(shellLaunchConfig, envFromConfigValue, terminalEnvironment.createVariableResolver(lastActiveWorkspace, this._configurationResolverService), isWorkspaceShellAllowed, this._productService.version, this._configHelper.config.detectLocale, baseEnv);
|
||||
const variableResolver = terminalEnvironment.createVariableResolver(lastActiveWorkspace, this._configurationResolverService);
|
||||
const env = terminalEnvironment.createTerminalEnvironment(shellLaunchConfig, envFromConfigValue, variableResolver, isWorkspaceShellAllowed, this._productService.version, this._configHelper.config.detectLocale, baseEnv);
|
||||
|
||||
if (!shellLaunchConfig.strictEnv) {
|
||||
this._extEnvironmentVariableCollection = this._environmentVariableService.mergedCollection;
|
||||
|
@ -259,7 +260,7 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce
|
|||
// info widget. While technically these could differ due to the slight change of a race
|
||||
// condition, the chance is minimal plus the impact on the user is also not that great
|
||||
// if it happens - it's not worth adding plumbing to sync back the resolved collection.
|
||||
this._extEnvironmentVariableCollection.applyToProcessEnvironment(env);
|
||||
this._extEnvironmentVariableCollection.applyToProcessEnvironment(env, variableResolver);
|
||||
if (this._extEnvironmentVariableCollection.map.size > 0) {
|
||||
this._environmentVariableInfo = new EnvironmentVariableInfoChangesActive(this._extEnvironmentVariableCollection);
|
||||
this._onEnvironmentVariableInfoChange.fire(this._environmentVariableInfo);
|
||||
|
|
|
@ -48,8 +48,10 @@ export interface IMergedEnvironmentVariableCollection {
|
|||
|
||||
/**
|
||||
* Applies this collection to a process environment.
|
||||
* @param variableResolver An optional function to use to resolve variables within the
|
||||
* environment values.
|
||||
*/
|
||||
applyToProcessEnvironment(env: IProcessEnvironment): void;
|
||||
applyToProcessEnvironment(env: IProcessEnvironment, variableResolver?: (str: string) => string): void;
|
||||
|
||||
/**
|
||||
* Generates a diff of this connection against another. Returns undefined if the collections are
|
||||
|
|
|
@ -41,7 +41,7 @@ export class MergedEnvironmentVariableCollection implements IMergedEnvironmentVa
|
|||
});
|
||||
}
|
||||
|
||||
applyToProcessEnvironment(env: IProcessEnvironment): void {
|
||||
applyToProcessEnvironment(env: IProcessEnvironment, variableResolver?: (str: string) => string): void {
|
||||
let lowerToActualVariableNames: { [lowerKey: string]: string | undefined } | undefined;
|
||||
if (isWindows) {
|
||||
lowerToActualVariableNames = {};
|
||||
|
@ -50,15 +50,16 @@ export class MergedEnvironmentVariableCollection implements IMergedEnvironmentVa
|
|||
this.map.forEach((mutators, variable) => {
|
||||
const actualVariable = isWindows ? lowerToActualVariableNames![variable.toLowerCase()] || variable : variable;
|
||||
mutators.forEach(mutator => {
|
||||
const value = variableResolver ? variableResolver(mutator.value) : mutator.value;
|
||||
switch (mutator.type) {
|
||||
case EnvironmentVariableMutatorType.Append:
|
||||
env[actualVariable] = (env[actualVariable] || '') + mutator.value;
|
||||
env[actualVariable] = (env[actualVariable] || '') + value;
|
||||
break;
|
||||
case EnvironmentVariableMutatorType.Prepend:
|
||||
env[actualVariable] = mutator.value + (env[actualVariable] || '');
|
||||
env[actualVariable] = value + (env[actualVariable] || '');
|
||||
break;
|
||||
case EnvironmentVariableMutatorType.Replace:
|
||||
env[actualVariable] = mutator.value;
|
||||
env[actualVariable] = value;
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -27,7 +27,10 @@ export abstract class BaseConfigurationResolverService extends AbstractVariableR
|
|||
static readonly INPUT_OR_COMMAND_VARIABLES_PATTERN = /\${((input|command):(.*?))}/g;
|
||||
|
||||
constructor(
|
||||
context: { getExecPath: () => string | undefined },
|
||||
context: {
|
||||
getAppRoot: () => string | undefined,
|
||||
getExecPath: () => string | undefined
|
||||
},
|
||||
envVariables: IProcessEnvironment,
|
||||
editorService: IEditorService,
|
||||
private readonly configurationService: IConfigurationService,
|
||||
|
@ -47,6 +50,9 @@ export abstract class BaseConfigurationResolverService extends AbstractVariableR
|
|||
getConfigurationValue: (folderUri: uri | undefined, suffix: string): string | undefined => {
|
||||
return configurationService.getValue<string>(suffix, folderUri ? { resource: folderUri } : {});
|
||||
},
|
||||
getAppRoot: (): string | undefined => {
|
||||
return context.getAppRoot();
|
||||
},
|
||||
getExecPath: (): string | undefined => {
|
||||
return context.getExecPath();
|
||||
},
|
||||
|
@ -364,7 +370,7 @@ export class ConfigurationResolverService extends BaseConfigurationResolverServi
|
|||
@IQuickInputService quickInputService: IQuickInputService,
|
||||
@ILabelService labelService: ILabelService
|
||||
) {
|
||||
super({ getExecPath: () => undefined }, Object.create(null), editorService, configurationService, commandService, workspaceContextService, quickInputService, labelService);
|
||||
super({ getAppRoot: () => undefined, getExecPath: () => undefined }, Object.create(null), editorService, configurationService, commandService, workspaceContextService, quickInputService, labelService);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ export interface IVariableResolveContext {
|
|||
getFolderUri(folderName: string): uri | undefined;
|
||||
getWorkspaceFolderCount(): number;
|
||||
getConfigurationValue(folderUri: uri | undefined, section: string): string | undefined;
|
||||
getAppRoot(): string | undefined;
|
||||
getExecPath(): string | undefined;
|
||||
getFilePath(): string | undefined;
|
||||
getWorkspaceFolderPathForFile?(): string | undefined;
|
||||
|
@ -313,6 +314,13 @@ export class AbstractVariableResolverService implements IConfigurationResolverSe
|
|||
}
|
||||
return match;
|
||||
|
||||
case 'appDirname':
|
||||
const ar = this._context.getAppRoot();
|
||||
if (ar) {
|
||||
return ar;
|
||||
}
|
||||
return match;
|
||||
|
||||
case 'pathSeparator':
|
||||
return paths.sep;
|
||||
|
||||
|
|
|
@ -28,6 +28,9 @@ export class ConfigurationResolverService extends BaseConfigurationResolverServi
|
|||
@ILabelService labelService: ILabelService
|
||||
) {
|
||||
super({
|
||||
getAppRoot: (): string | undefined => {
|
||||
return environmentService.appRoot;
|
||||
},
|
||||
getExecPath: (): string | undefined => {
|
||||
return environmentService.execPath;
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ suite('Configuration Resolver Service', () => {
|
|||
labelService = new MockLabelService();
|
||||
containingWorkspace = testWorkspace(uri.parse('file:///VSCode/workspaceLocation'));
|
||||
workspace = containingWorkspace.folders[0];
|
||||
configurationResolverService = new TestConfigurationResolverService({ getExecPath: () => undefined }, environmentService.userEnv, editorService, new MockInputsConfigurationService(), mockCommandService, new TestContextService(containingWorkspace), quickInputService, labelService);
|
||||
configurationResolverService = new TestConfigurationResolverService({ getAppRoot: () => undefined, getExecPath: () => undefined }, environmentService.userEnv, editorService, new MockInputsConfigurationService(), mockCommandService, new TestContextService(containingWorkspace), quickInputService, labelService);
|
||||
});
|
||||
|
||||
teardown(() => {
|
||||
|
@ -211,7 +211,7 @@ suite('Configuration Resolver Service', () => {
|
|||
}
|
||||
});
|
||||
|
||||
let service = new TestConfigurationResolverService({ getExecPath: () => undefined }, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService);
|
||||
let service = new TestConfigurationResolverService({ getAppRoot: () => undefined, getExecPath: () => undefined }, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService);
|
||||
assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.fontFamily} xyz'), 'abc foo xyz');
|
||||
});
|
||||
|
||||
|
@ -222,7 +222,7 @@ suite('Configuration Resolver Service', () => {
|
|||
}
|
||||
});
|
||||
|
||||
let service = new TestConfigurationResolverService({ getExecPath: () => undefined }, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService);
|
||||
let service = new TestConfigurationResolverService({ getAppRoot: () => undefined, getExecPath: () => undefined }, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService);
|
||||
assert.strictEqual(service.resolve(undefined, 'abc ${config:editor.fontFamily} xyz'), 'abc foo xyz');
|
||||
});
|
||||
|
||||
|
@ -239,7 +239,7 @@ suite('Configuration Resolver Service', () => {
|
|||
}
|
||||
});
|
||||
|
||||
let service = new TestConfigurationResolverService({ getExecPath: () => undefined }, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService);
|
||||
let service = new TestConfigurationResolverService({ getAppRoot: () => undefined, getExecPath: () => undefined }, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService);
|
||||
assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.fontFamily} ${config:terminal.integrated.fontFamily} xyz'), 'abc foo bar xyz');
|
||||
});
|
||||
|
||||
|
@ -256,7 +256,7 @@ suite('Configuration Resolver Service', () => {
|
|||
}
|
||||
});
|
||||
|
||||
let service = new TestConfigurationResolverService({ getExecPath: () => undefined }, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService);
|
||||
let service = new TestConfigurationResolverService({ getAppRoot: () => undefined, getExecPath: () => undefined }, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService);
|
||||
if (platform.isWindows) {
|
||||
assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.fontFamily} ${workspaceFolder} ${env:key1} xyz'), 'abc foo \\VSCode\\workspaceLocation Value for key1 xyz');
|
||||
} else {
|
||||
|
@ -277,7 +277,7 @@ suite('Configuration Resolver Service', () => {
|
|||
}
|
||||
});
|
||||
|
||||
let service = new TestConfigurationResolverService({ getExecPath: () => undefined }, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService);
|
||||
let service = new TestConfigurationResolverService({ getAppRoot: () => undefined, getExecPath: () => undefined }, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService);
|
||||
if (platform.isWindows) {
|
||||
assert.strictEqual(service.resolve(workspace, '${config:editor.fontFamily} ${config:terminal.integrated.fontFamily} ${workspaceFolder} - ${workspaceFolder} ${env:key1} - ${env:key2}'), 'foo bar \\VSCode\\workspaceLocation - \\VSCode\\workspaceLocation Value for key1 - Value for key2');
|
||||
} else {
|
||||
|
@ -311,7 +311,7 @@ suite('Configuration Resolver Service', () => {
|
|||
}
|
||||
});
|
||||
|
||||
let service = new TestConfigurationResolverService({ getExecPath: () => undefined }, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService);
|
||||
let service = new TestConfigurationResolverService({ getAppRoot: () => undefined, getExecPath: () => undefined }, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService);
|
||||
assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.fontFamily} ${config:editor.lineNumbers} ${config:editor.insertSpaces} xyz'), 'abc foo 123 false xyz');
|
||||
});
|
||||
|
||||
|
@ -321,7 +321,7 @@ suite('Configuration Resolver Service', () => {
|
|||
editor: {}
|
||||
});
|
||||
|
||||
let service = new TestConfigurationResolverService({ getExecPath: () => undefined }, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService);
|
||||
let service = new TestConfigurationResolverService({ getAppRoot: () => undefined, getExecPath: () => undefined }, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService);
|
||||
assert.strictEqual(service.resolve(workspace, 'abc ${unknownVariable} xyz'), 'abc ${unknownVariable} xyz');
|
||||
assert.strictEqual(service.resolve(workspace, 'abc ${env:unknownVariable} xyz'), 'abc xyz');
|
||||
});
|
||||
|
@ -334,7 +334,7 @@ suite('Configuration Resolver Service', () => {
|
|||
}
|
||||
});
|
||||
|
||||
let service = new TestConfigurationResolverService({ getExecPath: () => undefined }, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService);
|
||||
let service = new TestConfigurationResolverService({ getAppRoot: () => undefined, getExecPath: () => undefined }, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService);
|
||||
|
||||
assert.throws(() => service.resolve(workspace, 'abc ${env} xyz'));
|
||||
assert.throws(() => service.resolve(workspace, 'abc ${env:} xyz'));
|
||||
|
|
Loading…
Reference in a new issue