未验证 提交 44f8fcdd 编写于 作者: A Alex Dima

Avoid needing the entire `IConfigurationResolverService` for variable...

Avoid needing the entire `IConfigurationResolverService` for variable resolving & more explicit typing for `fetchSetting`
上级 eb9f3716
......@@ -73,8 +73,7 @@ export class ExtHostTerminalService extends BaseExtHostTerminalService {
getSystemShell(platform.platform),
process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432'),
process.env.windir,
this._lastActiveWorkspace,
this._variableResolver,
terminalEnvironment.createVariableResolver(this._lastActiveWorkspace, this._variableResolver),
this._logService,
useAutomationShell
);
......@@ -88,7 +87,7 @@ export class ExtHostTerminalService extends BaseExtHostTerminalService {
return this._apiInspectConfigToPlain<string | string[]>(setting);
};
return terminalEnvironment.getDefaultShellArgs(fetchSetting, this._isWorkspaceShellAllowed, useAutomationShell, this._lastActiveWorkspace, this._variableResolver, this._logService);
return terminalEnvironment.getDefaultShellArgs(fetchSetting, this._isWorkspaceShellAllowed, useAutomationShell, terminalEnvironment.createVariableResolver(this._lastActiveWorkspace, this._variableResolver), this._logService);
}
private _apiInspectConfigToPlain<T>(
......@@ -177,16 +176,15 @@ export class ExtHostTerminalService extends BaseExtHostTerminalService {
// Get the initial cwd
const terminalConfig = configProvider.getConfiguration('terminal.integrated');
const initialCwd = terminalEnvironment.getCwd(shellLaunchConfig, os.homedir(), lastActiveWorkspace, this._variableResolver, activeWorkspaceRootUri, terminalConfig.cwd, this._logService);
const initialCwd = terminalEnvironment.getCwd(shellLaunchConfig, os.homedir(), terminalEnvironment.createVariableResolver(lastActiveWorkspace, this._variableResolver), activeWorkspaceRootUri, terminalConfig.cwd, this._logService);
shellLaunchConfig.cwd = initialCwd;
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 env = terminalEnvironment.createTerminalEnvironment(
shellLaunchConfig,
lastActiveWorkspace,
envFromConfig,
this._variableResolver,
terminalEnvironment.createVariableResolver(lastActiveWorkspace, this._variableResolver),
isWorkspaceShellAllowed,
this._extHostInitDataService.version,
terminalConfig.get<'auto' | 'off' | 'on'>('detectLocale', 'auto'),
......
......@@ -98,7 +98,7 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce
@ITerminalInstanceService private readonly _terminalInstanceService: ITerminalInstanceService,
@IRemoteAgentService private readonly _remoteAgentService: IRemoteAgentService,
@IPathService private readonly _pathService: IPathService,
@IEnvironmentVariableService private readonly _environmentVariableService: IEnvironmentVariableService
@IEnvironmentVariableService private readonly _environmentVariableService: IEnvironmentVariableService,
) {
super();
this.ptyProcessReady = new Promise<void>(c => {
......@@ -240,8 +240,7 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce
const initialCwd = terminalEnvironment.getCwd(
shellLaunchConfig,
userHome,
lastActiveWorkspace,
this._configurationResolverService,
terminalEnvironment.createVariableResolver(lastActiveWorkspace, this._configurationResolverService),
activeWorkspaceRootUri,
this._configHelper.config.cwd,
this._logService
......@@ -250,7 +249,7 @@ 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, lastActiveWorkspace, envFromConfigValue, this._configurationResolverService, isWorkspaceShellAllowed, this._productService.version, this._configHelper.config.detectLocale, baseEnv);
const env = terminalEnvironment.createTerminalEnvironment(shellLaunchConfig, envFromConfigValue, terminalEnvironment.createVariableResolver(lastActiveWorkspace, this._configurationResolverService), isWorkspaceShellAllowed, this._productService.version, this._configHelper.config.detectLocale, baseEnv);
// Fetch any extension environment additions and apply them
if (!shellLaunchConfig.strictEnv) {
......
......@@ -74,12 +74,12 @@ function mergeNonNullKeys(env: platform.IProcessEnvironment, other: ITerminalEnv
}
}
function resolveConfigurationVariables(configurationResolverService: IConfigurationResolverService, env: ITerminalEnvironment, lastActiveWorkspaceRoot: IWorkspaceFolder | undefined): ITerminalEnvironment {
function resolveConfigurationVariables(variableResolver: VariableResolver, env: ITerminalEnvironment): ITerminalEnvironment {
Object.keys(env).forEach((key) => {
const value = env[key];
if (typeof value === 'string') {
try {
env[key] = configurationResolverService.resolve(lastActiveWorkspaceRoot, value);
env[key] = variableResolver(value);
} catch (e) {
env[key] = value;
}
......@@ -177,23 +177,22 @@ export function getLangEnvVariable(locale?: string): string {
export function getCwd(
shell: IShellLaunchConfig,
userHome: string | undefined,
lastActiveWorkspace: IWorkspaceFolder | undefined,
configurationResolverService: IConfigurationResolverService | undefined,
variableResolver: VariableResolver | undefined,
root: Uri | undefined,
customCwd: string | undefined,
logService?: ILogService
): string {
if (shell.cwd) {
const unresolved = (typeof shell.cwd === 'object') ? shell.cwd.fsPath : shell.cwd;
const resolved = _resolveCwd(unresolved, lastActiveWorkspace, configurationResolverService);
const resolved = _resolveCwd(unresolved, variableResolver);
return _sanitizeCwd(resolved || unresolved);
}
let cwd: string | undefined;
if (!shell.ignoreConfigurationCwd && customCwd) {
if (configurationResolverService) {
customCwd = _resolveCwd(customCwd, lastActiveWorkspace, configurationResolverService, logService);
if (variableResolver) {
customCwd = _resolveCwd(customCwd, variableResolver, logService);
}
if (customCwd) {
if (path.isAbsolute(customCwd)) {
......@@ -212,10 +211,10 @@ export function getCwd(
return _sanitizeCwd(cwd);
}
function _resolveCwd(cwd: string, lastActiveWorkspace: IWorkspaceFolder | undefined, configurationResolverService: IConfigurationResolverService | undefined, logService?: ILogService): string | undefined {
if (configurationResolverService) {
function _resolveCwd(cwd: string, variableResolver: VariableResolver | undefined, logService?: ILogService): string | undefined {
if (variableResolver) {
try {
return configurationResolverService.resolve(lastActiveWorkspace, cwd);
return variableResolver(cwd);
} catch (e) {
logService?.error('Could not resolve terminal cwd', e);
return undefined;
......@@ -245,14 +244,37 @@ export function escapeNonWindowsPath(path: string): string {
return newPath;
}
export type TerminalShellSetting = (
`terminal.integrated.automationShell.windows`
| `terminal.integrated.automationShell.osx`
| `terminal.integrated.automationShell.linux`
| `terminal.integrated.shell.windows`
| `terminal.integrated.shell.osx`
| `terminal.integrated.shell.linux`
);
export type TerminalShellArgsSetting = (
`terminal.integrated.shellArgs.windows`
| `terminal.integrated.shellArgs.osx`
| `terminal.integrated.shellArgs.linux`
);
export type VariableResolver = (str: string) => string;
export function createVariableResolver(lastActiveWorkspace: IWorkspaceFolder | undefined, configurationResolverService: IConfigurationResolverService | undefined): VariableResolver | undefined {
if (!configurationResolverService) {
return undefined;
}
return (str) => configurationResolverService.resolve(lastActiveWorkspace, str);
}
export function getDefaultShell(
fetchSetting: (key: string) => { userValue?: string | string[], value?: string | string[], defaultValue?: string | string[] },
fetchSetting: (key: TerminalShellSetting) => { userValue?: string | string[], value?: string | string[], defaultValue?: string | string[] },
isWorkspaceShellAllowed: boolean,
defaultShell: string,
isWoW64: boolean,
windir: string | undefined,
lastActiveWorkspace: IWorkspaceFolder | undefined,
configurationResolverService: IConfigurationResolverService | undefined,
variableResolver: VariableResolver | undefined,
logService: ILogService,
useAutomationShell: boolean,
platformOverride: platform.Platform = platform.platform
......@@ -282,9 +304,9 @@ export function getDefaultShell(
executable = executable.replace(/\//g, '\\');
}
if (configurationResolverService) {
if (variableResolver) {
try {
executable = configurationResolverService.resolve(lastActiveWorkspace, executable);
executable = variableResolver(executable);
} catch (e) {
logService.error(`Could not resolve shell`, e);
}
......@@ -294,11 +316,10 @@ export function getDefaultShell(
}
export function getDefaultShellArgs(
fetchSetting: (key: string) => { userValue?: string | string[], value?: string | string[], defaultValue?: string | string[] },
fetchSetting: (key: TerminalShellSetting | TerminalShellArgsSetting) => { userValue?: string | string[], value?: string | string[], defaultValue?: string | string[] },
isWorkspaceShellAllowed: boolean,
useAutomationShell: boolean,
lastActiveWorkspace: IWorkspaceFolder | undefined,
configurationResolverService: IConfigurationResolverService | undefined,
variableResolver: VariableResolver | undefined,
logService: ILogService,
platformOverride: platform.Platform = platform.platform,
): string | string[] {
......@@ -309,19 +330,19 @@ export function getDefaultShellArgs(
}
const platformKey = platformOverride === platform.Platform.Windows ? 'windows' : platformOverride === platform.Platform.Mac ? 'osx' : 'linux';
const shellArgsConfigValue = fetchSetting(`terminal.integrated.shellArgs.${platformKey}`);
const shellArgsConfigValue = fetchSetting(<TerminalShellArgsSetting>`terminal.integrated.shellArgs.${platformKey}`);
let args = ((isWorkspaceShellAllowed ? shellArgsConfigValue.value : shellArgsConfigValue.userValue) || shellArgsConfigValue.defaultValue);
if (!args) {
return [];
}
if (typeof args === 'string' && platformOverride === platform.Platform.Windows) {
return configurationResolverService ? configurationResolverService.resolve(lastActiveWorkspace, args) : args;
return variableResolver ? variableResolver(args) : args;
}
if (configurationResolverService) {
if (variableResolver) {
const resolvedArgs: string[] = [];
for (const arg of args) {
try {
resolvedArgs.push(configurationResolverService.resolve(lastActiveWorkspace, arg));
resolvedArgs.push(variableResolver(arg));
} catch (e) {
logService.error(`Could not resolve terminal.integrated.shellArgs.${platformKey}`, e);
resolvedArgs.push(arg);
......@@ -333,22 +354,21 @@ export function getDefaultShellArgs(
}
function getShellSetting(
fetchSetting: (key: string) => { userValue?: string | string[], value?: string | string[], defaultValue?: string | string[] },
fetchSetting: (key: TerminalShellSetting) => { userValue?: string | string[], value?: string | string[], defaultValue?: string | string[] },
isWorkspaceShellAllowed: boolean,
type: 'automationShell' | 'shell',
platformOverride: platform.Platform = platform.platform,
): string | null {
const platformKey = platformOverride === platform.Platform.Windows ? 'windows' : platformOverride === platform.Platform.Mac ? 'osx' : 'linux';
const shellConfigValue = fetchSetting(`terminal.integrated.${type}.${platformKey}`);
const shellConfigValue = fetchSetting(<TerminalShellSetting>`terminal.integrated.${type}.${platformKey}`);
const executable = (isWorkspaceShellAllowed ? <string>shellConfigValue.value : <string>shellConfigValue.userValue) || (<string | null>shellConfigValue.defaultValue);
return executable;
}
export function createTerminalEnvironment(
shellLaunchConfig: IShellLaunchConfig,
lastActiveWorkspace: IWorkspaceFolder | undefined,
envFromConfig: { userValue?: ITerminalEnvironment, value?: ITerminalEnvironment, defaultValue?: ITerminalEnvironment },
configurationResolverService: IConfigurationResolverService | undefined,
variableResolver: VariableResolver | undefined,
isWorkspaceShellAllowed: boolean,
version: string | undefined,
detectLocale: 'auto' | 'off' | 'on',
......@@ -368,12 +388,12 @@ export function createTerminalEnvironment(
const allowedEnvFromConfig = { ...(isWorkspaceShellAllowed ? envFromConfig.value : envFromConfig.userValue) };
// Resolve env vars from config and shell
if (configurationResolverService) {
if (variableResolver) {
if (allowedEnvFromConfig) {
resolveConfigurationVariables(configurationResolverService, allowedEnvFromConfig, lastActiveWorkspace);
resolveConfigurationVariables(variableResolver, allowedEnvFromConfig);
}
if (shellLaunchConfig.env) {
resolveConfigurationVariables(configurationResolverService, shellLaunchConfig.env, lastActiveWorkspace);
resolveConfigurationVariables(variableResolver, shellLaunchConfig.env);
}
}
......
......@@ -15,7 +15,7 @@ import type { SearchAddon as XTermSearchAddon } from 'xterm-addon-search';
import type { Unicode11Addon as XTermUnicode11Addon } from 'xterm-addon-unicode11';
import type { WebglAddon as XTermWebglAddon } from 'xterm-addon-webgl';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { getDefaultShell, getDefaultShellArgs } from 'vs/workbench/contrib/terminal/common/terminalEnvironment';
import { createVariableResolver, getDefaultShell, getDefaultShellArgs } from 'vs/workbench/contrib/terminal/common/terminalEnvironment';
import { StorageScope, IStorageService } from 'vs/platform/storage/common/storage';
import { getMainProcessParentEnv } from 'vs/workbench/contrib/terminal/node/terminalEnvironment';
import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver';
......@@ -93,8 +93,7 @@ export class TerminalInstanceService implements ITerminalInstanceService {
getSystemShell(platformOverride),
process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432'),
process.env.windir,
lastActiveWorkspace,
this._configurationResolverService,
createVariableResolver(lastActiveWorkspace, this._configurationResolverService),
this._logService,
useAutomationShell,
platformOverride
......@@ -103,8 +102,7 @@ export class TerminalInstanceService implements ITerminalInstanceService {
(key) => this._configurationService.inspect(key),
isWorkspaceShellAllowed,
useAutomationShell,
lastActiveWorkspace,
this._configurationResolverService,
createVariableResolver(lastActiveWorkspace, this._configurationResolverService),
this._logService,
platformOverride
);
......
......@@ -187,31 +187,31 @@ suite('Workbench - TerminalEnvironment', () => {
}
test('should default to userHome for an empty workspace', () => {
assertPathsMatch(getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, undefined, undefined, undefined), '/userHome/');
assertPathsMatch(getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, undefined, undefined), '/userHome/');
});
test('should use to the workspace if it exists', () => {
assertPathsMatch(getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, undefined, Uri.file('/foo'), undefined), '/foo');
assertPathsMatch(getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, Uri.file('/foo'), undefined), '/foo');
});
test('should use an absolute custom cwd as is', () => {
assertPathsMatch(getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, undefined, undefined, '/foo'), '/foo');
assertPathsMatch(getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, undefined, '/foo'), '/foo');
});
test('should normalize a relative custom cwd against the workspace path', () => {
assertPathsMatch(getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, undefined, Uri.file('/bar'), 'foo'), '/bar/foo');
assertPathsMatch(getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, undefined, Uri.file('/bar'), './foo'), '/bar/foo');
assertPathsMatch(getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, undefined, Uri.file('/bar'), '../foo'), '/foo');
assertPathsMatch(getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, Uri.file('/bar'), 'foo'), '/bar/foo');
assertPathsMatch(getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, Uri.file('/bar'), './foo'), '/bar/foo');
assertPathsMatch(getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, Uri.file('/bar'), '../foo'), '/foo');
});
test('should fall back for relative a custom cwd that doesn\'t have a workspace', () => {
assertPathsMatch(getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, undefined, undefined, 'foo'), '/userHome/');
assertPathsMatch(getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, undefined, undefined, './foo'), '/userHome/');
assertPathsMatch(getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, undefined, undefined, '../foo'), '/userHome/');
assertPathsMatch(getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, undefined, 'foo'), '/userHome/');
assertPathsMatch(getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, undefined, './foo'), '/userHome/');
assertPathsMatch(getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, undefined, '../foo'), '/userHome/');
});
test('should ignore custom cwd when told to ignore', () => {
assertPathsMatch(getCwd({ executable: undefined, args: [], ignoreConfigurationCwd: true }, '/userHome/', undefined, undefined, Uri.file('/bar'), '/foo'), '/bar');
assertPathsMatch(getCwd({ executable: undefined, args: [], ignoreConfigurationCwd: true }, '/userHome/', undefined, Uri.file('/bar'), '/foo'), '/bar');
});
});
......@@ -221,7 +221,7 @@ suite('Workbench - TerminalEnvironment', () => {
return ({
'terminal.integrated.shell.windows': { userValue: 'C:\\Windows\\Sysnative\\cmd.exe', value: undefined, defaultValue: undefined }
} as any)[key];
}, false, 'DEFAULT', false, 'C:\\Windows', undefined, undefined, {} as any, false, platform.Platform.Windows);
}, false, 'DEFAULT', false, 'C:\\Windows', undefined, {} as any, false, platform.Platform.Windows);
assert.equal(shell, 'C:\\Windows\\System32\\cmd.exe');
});
......@@ -230,7 +230,7 @@ suite('Workbench - TerminalEnvironment', () => {
return ({
'terminal.integrated.shell.windows': { userValue: 'C:\\Windows\\Sysnative\\cmd.exe', value: undefined, defaultValue: undefined }
} as any)[key];
}, false, 'DEFAULT', true, 'C:\\Windows', undefined, undefined, {} as any, false, platform.Platform.Windows);
}, false, 'DEFAULT', true, 'C:\\Windows', undefined, {} as any, false, platform.Platform.Windows);
assert.equal(shell, 'C:\\Windows\\Sysnative\\cmd.exe');
});
......@@ -240,21 +240,21 @@ suite('Workbench - TerminalEnvironment', () => {
'terminal.integrated.shell.windows': { userValue: 'shell', value: undefined, defaultValue: undefined },
'terminal.integrated.automationShell.windows': { userValue: undefined, value: undefined, defaultValue: undefined }
} as any)[key];
}, false, 'DEFAULT', false, 'C:\\Windows', undefined, undefined, {} as any, false, platform.Platform.Windows);
}, false, 'DEFAULT', false, 'C:\\Windows', undefined, {} as any, false, platform.Platform.Windows);
assert.equal(shell1, 'shell', 'automationShell was false');
const shell2 = getDefaultShell(key => {
return ({
'terminal.integrated.shell.windows': { userValue: 'shell', value: undefined, defaultValue: undefined },
'terminal.integrated.automationShell.windows': { userValue: undefined, value: undefined, defaultValue: undefined }
} as any)[key];
}, false, 'DEFAULT', false, 'C:\\Windows', undefined, undefined, {} as any, true, platform.Platform.Windows);
}, false, 'DEFAULT', false, 'C:\\Windows', undefined, {} as any, true, platform.Platform.Windows);
assert.equal(shell2, 'shell', 'automationShell was true');
const shell3 = getDefaultShell(key => {
return ({
'terminal.integrated.shell.windows': { userValue: 'shell', value: undefined, defaultValue: undefined },
'terminal.integrated.automationShell.windows': { userValue: 'automationShell', value: undefined, defaultValue: undefined }
} as any)[key];
}, false, 'DEFAULT', false, 'C:\\Windows', undefined, undefined, {} as any, true, platform.Platform.Windows);
}, false, 'DEFAULT', false, 'C:\\Windows', undefined, {} as any, true, platform.Platform.Windows);
assert.equal(shell3, 'automationShell', 'automationShell was true and specified in settings');
});
});
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册