未验证 提交 0a8ca638 编写于 作者: L Logan Ramos 提交者: GitHub

Resolve Terminal arguments (#76895)

* Resolved terminal argds

* Move location of resolution

* Fix routing of resolver in extHost

* Remove unnecessary comma

* Compilation errors

* some async stuff

* Undo changes

* Variable resolver in constructor

* Load resolver upon construction of extHostTerminalService

* Utilize last active workspace root

* Reevaluate variableReoslver whenever the workspace gets new folder

* Fix types for string shellArgs

* Use async one level higher

* Fix compile issue

* Initialize resolver when exthost is created

* Fix ext host in remote case with no folder open

* Resolve args that an ecxctension passes in

* Remove TODO

* Resolve extension arguments
上级 6d49c7a8
......@@ -286,6 +286,8 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
private _terminalProcesses: { [id: number]: ITerminalChildProcess } = {};
private _terminalRenderers: ExtHostTerminalRenderer[] = [];
private _getTerminalPromises: { [id: number]: Promise<ExtHostTerminal> } = {};
private _variableResolver: ExtHostVariableResolverService | undefined;
private _lastActiveWorkspace: IWorkspaceFolder | undefined;
// TODO: Pull this from main side
private _isWorkspaceShellAllowed: boolean = false;
......@@ -307,9 +309,12 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
private _extHostConfiguration: ExtHostConfiguration,
private _extHostWorkspace: ExtHostWorkspace,
private _extHostDocumentsAndEditors: ExtHostDocumentsAndEditors,
private _logService: ILogService,
private _logService: ILogService
) {
this._proxy = mainContext.getProxy(MainContext.MainThreadTerminalService);
this.updateLastActiveWorkspace();
this.updateVariableResolver();
this.registerListeners();
}
public createTerminal(name?: string, shellPath?: string, shellArgs?: string[] | string): vscode.Terminal {
......@@ -366,18 +371,21 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
this._isWorkspaceShellAllowed,
getSystemShell(platform.platform),
process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432'),
process.env.windir
process.env.windir,
this._lastActiveWorkspace,
this._variableResolver
);
}
private _getDefaultShellArgs(configProvider: ExtHostConfigProvider): string[] | string | undefined {
private _getDefaultShellArgs(configProvider: ExtHostConfigProvider): string[] | string {
const fetchSetting = (key: string) => {
const setting = configProvider
.getConfiguration(key.substr(0, key.lastIndexOf('.')))
.inspect<string | string[]>(key.substr(key.lastIndexOf('.') + 1));
return this._apiInspectConfigToPlain<string | string[]>(setting);
};
return terminalEnvironment.getDefaultShellArgs(fetchSetting, this._isWorkspaceShellAllowed);
return terminalEnvironment.getDefaultShellArgs(fetchSetting, this._isWorkspaceShellAllowed, this._lastActiveWorkspace, this._variableResolver);
}
public async resolveTerminalRenderer(id: number): Promise<vscode.TerminalRenderer> {
......@@ -526,6 +534,24 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
return env;
}
private registerListeners(): void {
this._extHostDocumentsAndEditors.onDidChangeActiveTextEditor(() => this.updateLastActiveWorkspace());
this._extHostWorkspace.onDidChangeWorkspace(() => this.updateVariableResolver());
}
private updateLastActiveWorkspace(): void {
const activeEditor = this._extHostDocumentsAndEditors.activeEditor();
if (activeEditor) {
this._lastActiveWorkspace = this._extHostWorkspace.getWorkspaceFolder(activeEditor.document.uri) as IWorkspaceFolder;
}
}
private async updateVariableResolver(): Promise<void> {
const configProvider = await this._extHostConfiguration.getConfigProvider();
const workspaceFolders = await this._extHostWorkspace.getWorkspaceFolders2();
this._variableResolver = new ExtHostVariableResolverService(workspaceFolders || [], this._extHostDocumentsAndEditors, configProvider);
}
public async $createProcess(id: number, shellLaunchConfigDto: ShellLaunchConfigDto, activeWorkspaceRootUriComponents: UriComponents, cols: number, rows: number, isWorkspaceShellAllowed: boolean): Promise<void> {
const shellLaunchConfig: IShellLaunchConfig = {
name: shellLaunchConfigDto.name,
......@@ -541,6 +567,21 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
if (!shellLaunchConfig.executable) {
shellLaunchConfig.executable = this.getDefaultShell(configProvider);
shellLaunchConfig.args = this._getDefaultShellArgs(configProvider);
} else {
if (this._variableResolver) {
shellLaunchConfig.executable = this._variableResolver.resolve(this._lastActiveWorkspace, shellLaunchConfig.executable);
if (shellLaunchConfig.args) {
if (Array.isArray(shellLaunchConfig.args)) {
const resolvedArgs: string[] = [];
for (const arg of shellLaunchConfig.args) {
resolvedArgs.push(this._variableResolver.resolve(this._lastActiveWorkspace, arg));
}
shellLaunchConfig.args = resolvedArgs;
} else {
shellLaunchConfig.args = this._variableResolver.resolve(this._lastActiveWorkspace, shellLaunchConfig.args);
}
}
}
}
// Get the initial cwd
......@@ -559,14 +600,12 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
}
} as IWorkspaceFolder : null;
const envFromConfig = this._apiInspectConfigToPlain(configProvider.getConfiguration('terminal.integrated').inspect<ITerminalEnvironment>(`env.${platformKey}`));
const workspaceFolders = await this._extHostWorkspace.getWorkspaceFolders2();
const variableResolver = workspaceFolders ? new ExtHostVariableResolverService(workspaceFolders, this._extHostDocumentsAndEditors, configProvider) : undefined;
const baseEnv = terminalConfig.get<boolean>('inheritEnv', true) ? process.env as platform.IProcessEnvironment : await this._getNonInheritedEnv();
const env = terminalEnvironment.createTerminalEnvironment(
shellLaunchConfig,
lastActiveWorkspace,
envFromConfig,
variableResolver,
this._variableResolver,
isWorkspaceShellAllowed,
pkg.version,
terminalConfig.get<boolean>('setLocaleVariables', false),
......
......@@ -184,17 +184,29 @@ export class TerminalProcessManager implements ITerminalProcessManager {
rows: number,
isScreenReaderModeEnabled: boolean
): Promise<ITerminalChildProcess> {
const activeWorkspaceRootUri = this._historyService.getLastActiveWorkspaceRoot(Schemas.file);
const platformKey = platform.isWindows ? 'windows' : (platform.isMacintosh ? 'osx' : 'linux');
const lastActiveWorkspace = activeWorkspaceRootUri ? this._workspaceContextService.getWorkspaceFolder(activeWorkspaceRootUri) : null;
if (!shellLaunchConfig.executable) {
const defaultConfig = await this._terminalInstanceService.getDefaultShellAndArgs();
shellLaunchConfig.executable = defaultConfig.shell;
shellLaunchConfig.args = defaultConfig.args;
} else {
shellLaunchConfig.executable = this._configurationResolverService.resolve(lastActiveWorkspace === null ? undefined : lastActiveWorkspace, shellLaunchConfig.executable);
if (shellLaunchConfig.args) {
if (Array.isArray(shellLaunchConfig.args)) {
const resolvedArgs: string[] = [];
for (const arg of shellLaunchConfig.args) {
resolvedArgs.push(this._configurationResolverService.resolve(lastActiveWorkspace === null ? undefined : lastActiveWorkspace, arg));
}
shellLaunchConfig.args = resolvedArgs;
} else {
shellLaunchConfig.args = this._configurationResolverService.resolve(lastActiveWorkspace === null ? undefined : lastActiveWorkspace, shellLaunchConfig.args);
}
}
}
const activeWorkspaceRootUri = this._historyService.getLastActiveWorkspaceRoot(Schemas.file);
const initialCwd = terminalEnvironment.getCwd(shellLaunchConfig, this._environmentService.userHome, activeWorkspaceRootUri, this._configHelper.config.cwd);
const platformKey = platform.isWindows ? 'windows' : (platform.isMacintosh ? 'osx' : 'linux');
const lastActiveWorkspace = activeWorkspaceRootUri ? this._workspaceContextService.getWorkspaceFolder(activeWorkspaceRootUri) : null;
const envFromConfigValue = this._workspaceConfigurationService.inspect<ITerminalEnvironment | undefined>(`terminal.integrated.env.${platformKey}`);
const isWorkspaceShellAllowed = this._configHelper.checkWorkspaceShellPermissions();
const baseEnv = this._configHelper.config.inheritEnv ? process.env as platform.IProcessEnvironment : await this._terminalInstanceService.getMainProcessParentEnv();
......
......@@ -169,7 +169,9 @@ export function getDefaultShell(
defaultShell: string,
isWoW64: boolean,
windir: string | undefined,
platformOverride: platform.Platform = platform.platform
lastActiveWorkspace: IWorkspaceFolder | undefined,
configurationResolverService: IConfigurationResolverService | undefined,
platformOverride: platform.Platform = platform.platform,
): string {
const platformKey = platformOverride === platform.Platform.Windows ? 'windows' : platformOverride === platform.Platform.Mac ? 'osx' : 'linux';
const shellConfigValue = fetchSetting(`terminal.integrated.shell.${platformKey}`);
......@@ -190,17 +192,33 @@ export function getDefaultShell(
executable = executable.replace(/\//g, '\\');
}
if (configurationResolverService) {
executable = configurationResolverService.resolve(lastActiveWorkspace, executable);
}
return executable;
}
export function getDefaultShellArgs(
fetchSetting: (key: string) => { user: string | string[] | undefined, value: string | string[] | undefined, default: string | string[] | undefined },
isWorkspaceShellAllowed: boolean,
platformOverride: platform.Platform = platform.platform
): string[] {
lastActiveWorkspace: IWorkspaceFolder | undefined,
configurationResolverService: IConfigurationResolverService | undefined,
platformOverride: platform.Platform = platform.platform,
): string | string[] {
const platformKey = platformOverride === platform.Platform.Windows ? 'windows' : platformOverride === platform.Platform.Mac ? 'osx' : 'linux';
const shellArgsConfigValue = fetchSetting(`terminal.integrated.shellArgs.${platformKey}`);
const args = (isWorkspaceShellAllowed ? <string[]>shellArgsConfigValue.value : <string[]>shellArgsConfigValue.user) || <string[]>shellArgsConfigValue.default;
let args = <string[] | string>((isWorkspaceShellAllowed ? shellArgsConfigValue.value : shellArgsConfigValue.user) || shellArgsConfigValue.default);
if (typeof args === 'string' && platformOverride === platform.Platform.Windows) {
return configurationResolverService ? configurationResolverService.resolve(lastActiveWorkspace, args) : args;
}
if (configurationResolverService) {
const resolvedArgs: string[] = [];
for (const arg of args) {
resolvedArgs.push(configurationResolverService.resolve(lastActiveWorkspace, arg));
}
args = resolvedArgs;
}
return args;
}
......
......@@ -17,6 +17,9 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
import { 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';
import { IHistoryService } from 'vs/workbench/services/history/common/history';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
let Terminal: typeof XTermTerminal;
let WebLinksAddon: typeof XTermWebLinksAddon;
......@@ -28,7 +31,10 @@ export class TerminalInstanceService implements ITerminalInstanceService {
constructor(
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@IConfigurationService private readonly _configurationService: IConfigurationService,
@IStorageService private readonly _storageService: IStorageService
@IStorageService private readonly _storageService: IStorageService,
@IConfigurationResolverService private readonly _configurationResolverService: IConfigurationResolverService,
@IWorkspaceContextService private readonly _workspaceContextService: IWorkspaceContextService,
@IHistoryService private readonly _historyService: IHistoryService
) {
}
......@@ -65,19 +71,26 @@ export class TerminalInstanceService implements ITerminalInstanceService {
return this._storageService.getBoolean(IS_WORKSPACE_SHELL_ALLOWED_STORAGE_KEY, StorageScope.WORKSPACE, false);
}
public getDefaultShellAndArgs(platformOverride: Platform = platform): Promise<{ shell: string, args: string[] | undefined }> {
public getDefaultShellAndArgs(platformOverride: Platform = platform): Promise<{ shell: string, args: string | string[] }> {
const isWorkspaceShellAllowed = this._isWorkspaceShellAllowed();
const activeWorkspaceRootUri = this._historyService.getLastActiveWorkspaceRoot();
let lastActiveWorkspace = activeWorkspaceRootUri ? this._workspaceContextService.getWorkspaceFolder(activeWorkspaceRootUri) : undefined;
lastActiveWorkspace = lastActiveWorkspace === null ? undefined : lastActiveWorkspace;
const shell = getDefaultShell(
(key) => this._configurationService.inspect(key),
isWorkspaceShellAllowed,
getSystemShell(platformOverride),
process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432'),
process.env.windir,
lastActiveWorkspace,
this._configurationResolverService,
platformOverride
);
const args = getDefaultShellArgs(
(key) => this._configurationService.inspect(key),
isWorkspaceShellAllowed,
lastActiveWorkspace,
this._configurationResolverService,
platformOverride
);
return Promise.resolve({ shell, args });
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册