variables: allow resolving extensionDir (#146274)

* variables: allow resolving `extensionDir`

This allows us to fix https://github.com/microsoft/vscode-remote-release/issues/5516#issuecomment-911597917

It enables a new replacement in the format `${extensionDir:<id>}` which
will expand to the filesystem path where the extension is stored. This
involved churn, since now resolution is always synchronous (where before
the terminal took a synchronous-only path.)

Additionally, changes were needed to inject this information in the
variable resolver. As part of this I made the extension host resolver
(used by debug and tasks) its own extension host service.

* fixup! preserve object key order in resolution, add extensionDir support

* fixup! address pr comments

* fixup! address pr comments

* fixup! address pr comments

* config: fix config replacement only working for first variable per line

* fixup! fix unit tests
This commit is contained in:
Connor Peet
2022-04-07 08:06:31 -07:00
committed by GitHub
parent 0fba8139ce
commit 0de44f9786
30 changed files with 450 additions and 298 deletions

View File

@@ -20,6 +20,8 @@ import { IExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePa
import { ExtensionStoragePaths } from 'vs/workbench/api/node/extHostStoragePaths';
import { ExtHostLoggerService } from 'vs/workbench/api/node/extHostLoggerService';
import { ILoggerService } from 'vs/platform/log/common/log';
import { NodeExtHostVariableResolverProviderService } from 'vs/workbench/api/node/extHostVariableResolverService';
import { IExtHostVariableResolverProvider } from 'vs/workbench/api/common/extHostVariableResolverService';
// #########################################################################
// ### ###
@@ -36,3 +38,4 @@ registerSingleton(IExtHostSearch, NativeExtHostSearch);
registerSingleton(IExtHostTask, ExtHostTask);
registerSingleton(IExtHostTerminalService, ExtHostTerminalService);
registerSingleton(IExtHostTunnelService, ExtHostTunnelService);
registerSingleton(IExtHostVariableResolverProvider, NodeExtHostVariableResolverProviderService);

View File

@@ -3,31 +3,29 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vs/nls';
import type * as vscode from 'vscode';
import { homedir } from 'os';
import { createCancelablePromise, firstParallel } from 'vs/base/common/async';
import { IDisposable } from 'vs/base/common/lifecycle';
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';
import { AbstractDebugAdapter } from 'vs/workbench/contrib/debug/common/abstractDebugAdapter';
import { IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
import { IExtHostExtensionService } from 'vs/workbench/api/common/extHostExtensionService';
import { IExtHostDocumentsAndEditors, ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
import { IAdapterDescriptor } from 'vs/workbench/contrib/debug/common/debug';
import { IExtHostConfiguration, ExtHostConfigProvider } from '../common/extHostConfiguration';
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry';
import { IExtHostTerminalService } from 'vs/workbench/api/common/extHostTerminalService';
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
import { ExtHostDebugServiceBase, ExtHostDebugSession, ExtHostVariableResolverService } from 'vs/workbench/api/common/extHostDebugService';
import * as nls from 'vs/nls';
import { IExternalTerminalService } from 'vs/platform/externalTerminal/common/externalTerminal';
import { LinuxExternalTerminalService, MacExternalTerminalService, WindowsExternalTerminalService } from 'vs/platform/externalTerminal/node/externalTerminalService';
import { ISignService } from 'vs/platform/sign/common/sign';
import { SignService } from 'vs/platform/sign/node/signService';
import { IDisposable } from 'vs/base/common/lifecycle';
import { AbstractVariableResolverService } from 'vs/workbench/services/configurationResolver/common/variableResolver';
import { createCancelablePromise, firstParallel } from 'vs/base/common/async';
import { hasChildProcesses, prepareCommand } from 'vs/workbench/contrib/debug/node/terminals';
import { ExtHostDebugServiceBase, ExtHostDebugSession } from 'vs/workbench/api/common/extHostDebugService';
import { IExtHostEditorTabs } from 'vs/workbench/api/common/extHostEditorTabs';
import { IExternalTerminalService } from 'vs/platform/externalTerminal/common/externalTerminal';
import { WindowsExternalTerminalService, MacExternalTerminalService, LinuxExternalTerminalService } from 'vs/platform/externalTerminal/node/externalTerminalService';
import { IExtHostExtensionService } from 'vs/workbench/api/common/extHostExtensionService';
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
import { IExtHostTerminalService } from 'vs/workbench/api/common/extHostTerminalService';
import { DebugAdapterExecutable, ThemeIcon } from 'vs/workbench/api/common/extHostTypes';
import { IExtHostVariableResolverProvider } from 'vs/workbench/api/common/extHostVariableResolverService';
import { IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
import { AbstractDebugAdapter } from 'vs/workbench/contrib/debug/common/abstractDebugAdapter';
import { IAdapterDescriptor } from 'vs/workbench/contrib/debug/common/debug';
import { ExecutableDebugAdapter, NamedPipeDebugAdapter, SocketDebugAdapter } from 'vs/workbench/contrib/debug/node/debugAdapter';
import { hasChildProcesses, prepareCommand } from 'vs/workbench/contrib/debug/node/terminals';
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry';
import type * as vscode from 'vscode';
import { ExtHostConfigProvider, IExtHostConfiguration } from '../common/extHostConfiguration';
export class ExtHostDebugService extends ExtHostDebugServiceBase {
@@ -40,12 +38,12 @@ export class ExtHostDebugService extends ExtHostDebugServiceBase {
@IExtHostRpcService extHostRpcService: IExtHostRpcService,
@IExtHostWorkspace workspaceService: IExtHostWorkspace,
@IExtHostExtensionService extensionService: IExtHostExtensionService,
@IExtHostDocumentsAndEditors editorsService: IExtHostDocumentsAndEditors,
@IExtHostConfiguration configurationService: IExtHostConfiguration,
@IExtHostTerminalService private _terminalService: IExtHostTerminalService,
@IExtHostEditorTabs editorTabs: IExtHostEditorTabs
@IExtHostEditorTabs editorTabs: IExtHostEditorTabs,
@IExtHostVariableResolverProvider variableResolver: IExtHostVariableResolverProvider,
) {
super(extHostRpcService, workspaceService, extensionService, editorsService, configurationService, editorTabs);
super(extHostRpcService, workspaceService, extensionService, configurationService, editorTabs, variableResolver);
}
protected override createDebugAdapter(adapter: IAdapterDescriptor, session: ExtHostDebugSession): AbstractDebugAdapter | undefined {
@@ -154,10 +152,6 @@ export class ExtHostDebugService extends ExtHostDebugServiceBase {
}
return super.$runInTerminal(args, sessionId);
}
protected createVariableResolver(folders: vscode.WorkspaceFolder[], editorService: ExtHostDocumentsAndEditors, configurationService: ExtHostConfigProvider): AbstractVariableResolverService {
return new ExtHostVariableResolverService(folders, editorService, configurationService, this._editorTabs, this._workspaceService, homedir());
}
}
let externalTerminalService: IExternalTerminalService | undefined = undefined;

View File

@@ -11,7 +11,6 @@ import * as types from 'vs/workbench/api/common/extHostTypes';
import { IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
import type * as vscode from 'vscode';
import * as tasks from '../common/shared/tasks';
import { ExtHostVariableResolverService } from 'vs/workbench/api/common/extHostDebugService';
import { IExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
import { IExtHostConfiguration } from 'vs/workbench/api/common/extHostConfiguration';
import { IWorkspaceFolder, WorkspaceFolder } from 'vs/platform/workspace/common/workspace';
@@ -23,13 +22,11 @@ import { ExtHostTaskBase, TaskHandleDTO, TaskDTO, CustomExecutionDTO, HandlerDat
import { Schemas } from 'vs/base/common/network';
import { ILogService } from 'vs/platform/log/common/log';
import { IExtHostApiDeprecationService } from 'vs/workbench/api/common/extHostApiDeprecationService';
import { IExtHostEditorTabs } from 'vs/workbench/api/common/extHostEditorTabs';
import * as resources from 'vs/base/common/resources';
import { homedir } from 'os';
import { IExtHostVariableResolverProvider } from 'vs/workbench/api/common/extHostVariableResolverService';
export class ExtHostTask extends ExtHostTaskBase {
private _variableResolver: ExtHostVariableResolverService | undefined;
constructor(
@IExtHostRpcService extHostRpc: IExtHostRpcService,
@IExtHostInitDataService initData: IExtHostInitDataService,
@@ -39,7 +36,7 @@ export class ExtHostTask extends ExtHostTaskBase {
@IExtHostTerminalService extHostTerminalService: IExtHostTerminalService,
@ILogService logService: ILogService,
@IExtHostApiDeprecationService deprecationService: IExtHostApiDeprecationService,
@IExtHostEditorTabs private readonly editorTabs: IExtHostEditorTabs,
@IExtHostVariableResolverProvider private readonly variableResolver: IExtHostVariableResolverProvider,
) {
super(extHostRpc, initData, workspaceService, editorService, configurationService, extHostTerminalService, logService, deprecationService);
if (initData.remote.isRemote && initData.remote.authority) {
@@ -128,14 +125,6 @@ export class ExtHostTask extends ExtHostTaskBase {
return resolvedTaskDTO;
}
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, homedir());
}
return this._variableResolver;
}
private async getAFolder(workspaceFolders: vscode.WorkspaceFolder[] | undefined): Promise<IWorkspaceFolder> {
let folder = (workspaceFolders && workspaceFolders.length > 0) ? workspaceFolders[0] : undefined;
if (!folder) {
@@ -161,7 +150,7 @@ export class ExtHostTask extends ExtHostTaskBase {
const workspaceFolder = await this._workspaceProvider.resolveWorkspaceFolder(uri);
const workspaceFolders = (await this._workspaceProvider.getWorkspaceFolders2()) ?? [];
const resolver = await this.getVariableResolver(workspaceFolders);
const resolver = await this.variableResolver.getResolver();
const ws: IWorkspaceFolder = workspaceFolder ? {
uri: workspaceFolder.uri,
name: workspaceFolder.name,

View File

@@ -0,0 +1,13 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { homedir } from 'os';
import { ExtHostVariableResolverProviderService } from 'vs/workbench/api/common/extHostVariableResolverService';
export class NodeExtHostVariableResolverProviderService extends ExtHostVariableResolverProviderService {
protected override homeDir(): string | undefined {
return homedir();
}
}