diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/workspace.tasks.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/workspace.tasks.test.ts new file mode 100644 index 00000000000..67600f97cd6 --- /dev/null +++ b/extensions/vscode-api-tests/src/singlefolder-tests/workspace.tasks.test.ts @@ -0,0 +1,63 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as assert from 'assert'; +import * as vscode from 'vscode'; + +suite.only('workspace-namespace', () => { + + suite('Tasks', () => { + + test('CustomExecution2 task should start and shutdown successfully', (done) => { + interface CustomTestingTaskDefinition extends vscode.TaskDefinition { + /** + * One of the task properties. This can be used to customize the task in the tasks.json + */ + customProp1: string; + } + const taskType: string = 'customTesting'; + const taskName = 'First custom task'; + const reg1 = vscode.window.onDidOpenTerminal(term => { + reg1.dispose(); + const reg2 = term.onDidWriteData(e => { + reg2.dispose(); + assert.equal(e, 'testing\r\n'); + term.dispose(); + }); + }); + const exitEmitter = new vscode.EventEmitter(); + const taskProvider = vscode.tasks.registerTaskProvider(taskType, { + provideTasks: () => { + let result: vscode.Task[] = []; + let kind: CustomTestingTaskDefinition = { + type: taskType, + customProp1: 'testing task one' + }; + const writeEmitter = new vscode.EventEmitter(); + let execution = new vscode.CustomExecution2((): Thenable => { + return Promise.resolve({ + onDidWrite: writeEmitter.event, + start: () => { + writeEmitter.fire('testing\r\n'); + }, + onDidExit: exitEmitter.event, + shutdown: () => { + taskProvider.dispose(); + done(); + } + }); + }); + let task = new vscode.Task2(kind, vscode.TaskScope.Workspace, taskName, taskType, execution); + result.push(task); + return result; + }, + resolveTask(_task: vscode.Task): vscode.Task | undefined { + return undefined; + } + }); + vscode.commands.executeCommand('workbench.action.tasks.runTask', `${taskType}: ${taskName}`); + }); + }); +}); diff --git a/src/vs/workbench/api/node/extHostTask.ts b/src/vs/workbench/api/node/extHostTask.ts index a1e82957b48..0e7f5f9dd7a 100644 --- a/src/vs/workbench/api/node/extHostTask.ts +++ b/src/vs/workbench/api/node/extHostTask.ts @@ -588,7 +588,7 @@ export class ExtHostTask 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, execution2); - this._terminalService.attachVirtualProcessToTerminal(terminalId, await execution2.callback()); + await this._terminalService.attachVirtualProcessToTerminal(terminalId, await execution2.callback()); } // Once a terminal is spun up for the custom execution task this event will be fired. diff --git a/src/vs/workbench/api/node/extHostTerminalService.ts b/src/vs/workbench/api/node/extHostTerminalService.ts index 35884b08ba4..847bba891e8 100644 --- a/src/vs/workbench/api/node/extHostTerminalService.ts +++ b/src/vs/workbench/api/node/extHostTerminalService.ts @@ -337,8 +337,8 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape { return terminal; } - public attachVirtualProcessToTerminal(id: number, virtualProcess: vscode.TerminalVirtualProcess) { - const terminal = this._getTerminalById(id); + public async attachVirtualProcessToTerminal(id: number, virtualProcess: vscode.TerminalVirtualProcess): Promise { + const terminal = this._getTerminalByIdEventually(id); if (!terminal) { throw new Error(`Cannot resolve terminal with id ${id} for virtual process`); } @@ -619,6 +619,10 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape { } public async $startVirtualProcess(id: number, initialDimensions: ITerminalDimensionsDto | undefined): Promise { + // Make sure the ExtHostTerminal exists so onDidOpenTerminal has fired before we call + // TerminalVirtualProcess.start + await this._getTerminalByIdEventually(id); + // Processes should be initialized here for normal virtual process terminals, however for // tasks they are responsible for attaching the virtual process to a terminal so this // function may be called before tasks is able to attach to the terminal.