diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 705dec9ada0af4f22bf7efaeb068ef1feb2d4844..2a268d8cf3a914d2cc6a12391a037eafb3429495 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -811,6 +811,18 @@ declare module 'vscode' { detail?: string; } + export class CustomExecution2 extends CustomExecution { + /** + * Constructs a CustomExecution task object. The callback will be executed the task is run, at which point the + * extension should return the Pseudoterminal it will "run in". The task should wait to do further execution until + * [Pseudoterminal.open](#Pseudoterminal.open) is called. Task cancellation should be handled using + * [Pseudoterminal.close](#Pseudoterminal.close). When the task is complete fire + * [Pseudoterminal.onDidClose](#Pseudoterminal.onDidClose). + * @param callback The callback that will be called when the task is started by a user. + */ + constructor(callback: (resolvedDefinition?: TaskDefinition) => Thenable); + } + export interface TaskPresentationOptions { /** * Controls whether the task is executed in a specific terminal group using split panes. diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 2bb2f6ef38ca1daf03073c638ee96d79c4662b8b..e578e636d44614a0738eac8cfa68979740cad428 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -865,6 +865,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I EventEmitter: Emitter, ExtensionKind: extHostTypes.ExtensionKind, CustomExecution: extHostTypes.CustomExecution, + CustomExecution2: extHostTypes.CustomExecution, FileChangeType: extHostTypes.FileChangeType, FileSystemError: extHostTypes.FileSystemError, FileType: files.FileType, diff --git a/src/vs/workbench/api/common/extHostTask.ts b/src/vs/workbench/api/common/extHostTask.ts index da3e935aaeb99fb11d52d9e38a82ba15e5a37cf7..944f6a196190554c6d08a0ae17a3cff702d0a7e7 100644 --- a/src/vs/workbench/api/common/extHostTask.ts +++ b/src/vs/workbench/api/common/extHostTask.ts @@ -457,6 +457,10 @@ export abstract class ExtHostTaskBase implements ExtHostTaskShape { return this._onDidExecuteTask.event; } + protected async resolveDefinition(uri: number | UriComponents | undefined, definition: vscode.TaskDefinition | undefined): Promise { + return definition; + } + public async $onDidStartTask(execution: tasks.TaskExecutionDTO, terminalId: number): Promise { const customExecution: types.CustomExecution | undefined = this._providedCustomExecutions2.get(execution.id); if (customExecution) { @@ -466,7 +470,7 @@ export abstract class ExtHostTaskBase implements ExtHostTaskShape { // Clone the custom execution to keep the original untouched. This is important for multiple runs of the same task. this._activeCustomExecutions2.set(execution.id, customExecution); - this._terminalService.attachPtyToTerminal(terminalId, await customExecution.callback()); + this._terminalService.attachPtyToTerminal(terminalId, await customExecution.callback(await this.resolveDefinition(execution.task?.source.scope, execution.task?.definition))); } this._lastStartedTask = execution.id; diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index acb45d7f250f62f78c6f2fef1fd65df3067d319f..ff4afdb3f049748dfc4583a96927404155b1f13e 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -1777,20 +1777,20 @@ export enum TaskScope { Workspace = 2 } -export class CustomExecution implements vscode.CustomExecution { - private _callback: () => Thenable; - constructor(callback: () => Thenable) { +export class CustomExecution implements vscode.CustomExecution2 { + private _callback: (resolvedDefintion?: vscode.TaskDefinition) => Thenable; + constructor(callback: (resolvedDefintion?: vscode.TaskDefinition) => Thenable) { this._callback = callback; } public computeId(): string { return 'customExecution' + generateUuid(); } - public set callback(value: () => Thenable) { + public set callback(value: (resolvedDefintion?: vscode.TaskDefinition) => Thenable) { this._callback = value; } - public get callback(): (() => Thenable) { + public get callback(): ((resolvedDefintion?: vscode.TaskDefinition) => Thenable) { return this._callback; } } diff --git a/src/vs/workbench/api/node/extHostTask.ts b/src/vs/workbench/api/node/extHostTask.ts index 1df1b4731ed4d054bb8d3467fa5a6e23c636cead..c7a2ea29e9d0e2fe70af6485a9128d18c6dda54b 100644 --- a/src/vs/workbench/api/node/extHostTask.ts +++ b/src/vs/workbench/api/node/extHostTask.ts @@ -11,6 +11,7 @@ import * as types from 'vs/workbench/api/common/extHostTypes'; import { IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace'; import * as vscode from 'vscode'; import * as tasks from '../common/shared/tasks'; +import * as Objects from 'vs/base/common/objects'; import { ExtHostVariableResolverService } from 'vs/workbench/api/node/extHostDebugService'; import { IExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors'; import { IExtHostConfiguration } from 'vs/workbench/api/common/extHostConfiguration'; @@ -23,6 +24,7 @@ import { ExtHostTaskBase, TaskHandleDTO, TaskDTO, CustomExecutionDTO, HandlerDat import { Schemas } from 'vs/base/common/network'; export class ExtHostTask extends ExtHostTaskBase { + private _variableResolver: ExtHostVariableResolverService | undefined; constructor( @IExtHostRpcService extHostRpc: IExtHostRpcService, @@ -95,8 +97,41 @@ export class ExtHostTask extends ExtHostTaskBase { return resolvedTaskDTO; } + private async getVariableResolver(workspaceFolders: vscode.WorkspaceFolder[]): Promise { + if (this._variableResolver === undefined) { + const configProvider = await this._configurationService.getConfigProvider(); + this._variableResolver = new ExtHostVariableResolverService(workspaceFolders, this._editorService, configProvider); + } + return this._variableResolver; + } + + protected async resolveDefinition(uri: number | UriComponents | undefined, definition: vscode.TaskDefinition | undefined): Promise { + if (!uri || (typeof uri === 'number') || !definition) { + return definition; + } + const workspaceFolder = await this._workspaceProvider.resolveWorkspaceFolder(URI.revive(uri)); + const workspaceFolders = await this._workspaceProvider.getWorkspaceFolders2(); + if (!workspaceFolders || !workspaceFolder) { + return definition; + } + const resolver = await this.getVariableResolver(workspaceFolders); + const ws: IWorkspaceFolder = { + uri: workspaceFolder.uri, + name: workspaceFolder.name, + index: workspaceFolder.index, + toResource: () => { + throw new Error('Not implemented'); + } + }; + const resolvedDefinition = Objects.deepClone(definition); + for (const key in resolvedDefinition) { + resolvedDefinition[key] = resolver.resolve(ws, resolvedDefinition[key]); + } + + return resolvedDefinition; + } + public async $resolveVariables(uriComponents: UriComponents, toResolve: { process?: { name: string; cwd?: string; path?: string }, variables: string[] }): Promise<{ process?: string, variables: { [key: string]: string; } }> { - const configProvider = await this._configurationService.getConfigProvider(); const uri: URI = URI.revive(uriComponents); const result = { process: undefined as string, @@ -107,7 +142,7 @@ export class ExtHostTask extends ExtHostTaskBase { if (!workspaceFolders || !workspaceFolder) { throw new Error('Unexpected: Tasks can only be run in a workspace folder'); } - const resolver = new ExtHostVariableResolverService(workspaceFolders, this._editorService, configProvider); + const resolver = await this.getVariableResolver(workspaceFolders); const ws: IWorkspaceFolder = { uri: workspaceFolder.uri, name: workspaceFolder.name,