diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 44acade03b1..e36f942c276 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -117,6 +117,7 @@ "./vs/workbench/api/node/extHostSearch.ts", "./vs/workbench/api/node/extHostStatusBar.ts", "./vs/workbench/api/node/extHostStorage.ts", + // "./vs/workbench/api/node/extHostTask.ts", "./vs/workbench/api/node/extHostTextEditor.ts", "./vs/workbench/api/node/extHostTextEditors.ts", "./vs/workbench/api/node/extHostTypeConverters.ts", diff --git a/src/vs/workbench/api/node/extHostTask.ts b/src/vs/workbench/api/node/extHostTask.ts index f0184406cab..11e2925e0cf 100644 --- a/src/vs/workbench/api/node/extHostTask.ts +++ b/src/vs/workbench/api/node/extHostTask.ts @@ -34,13 +34,13 @@ import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cance import { IDisposable, dispose } from 'vs/base/common/lifecycle'; namespace TaskDefinitionDTO { - export function from(value: vscode.TaskDefinition): TaskDefinitionDTO { + export function from(value: vscode.TaskDefinition): TaskDefinitionDTO | undefined { if (value === undefined || value === null) { return undefined; } return value; } - export function to(value: TaskDefinitionDTO): vscode.TaskDefinition { + export function to(value: TaskDefinitionDTO): vscode.TaskDefinition | undefined { if (value === undefined || value === null) { return undefined; } @@ -49,13 +49,13 @@ namespace TaskDefinitionDTO { } namespace TaskPresentationOptionsDTO { - export function from(value: vscode.TaskPresentationOptions): TaskPresentationOptionsDTO { + export function from(value: vscode.TaskPresentationOptions): TaskPresentationOptionsDTO | undefined { if (value === undefined || value === null) { return undefined; } return value; } - export function to(value: TaskPresentationOptionsDTO): vscode.TaskPresentationOptions { + export function to(value: TaskPresentationOptionsDTO): vscode.TaskPresentationOptions | undefined { if (value === undefined || value === null) { return undefined; } @@ -64,13 +64,13 @@ namespace TaskPresentationOptionsDTO { } namespace ProcessExecutionOptionsDTO { - export function from(value: vscode.ProcessExecutionOptions): ProcessExecutionOptionsDTO { + export function from(value: vscode.ProcessExecutionOptions): ProcessExecutionOptionsDTO | undefined { if (value === undefined || value === null) { return undefined; } return value; } - export function to(value: ProcessExecutionOptionsDTO): vscode.ProcessExecutionOptions { + export function to(value: ProcessExecutionOptionsDTO): vscode.ProcessExecutionOptions | undefined { if (value === undefined || value === null) { return undefined; } @@ -83,7 +83,7 @@ namespace ProcessExecutionDTO { const candidate = value as ProcessExecutionDTO; return candidate && !!candidate.process; } - export function from(value: vscode.ProcessExecution): ProcessExecutionDTO { + export function from(value: vscode.ProcessExecution): ProcessExecutionDTO | undefined { if (value === undefined || value === null) { return undefined; } @@ -96,7 +96,7 @@ namespace ProcessExecutionDTO { } return result; } - export function to(value: ProcessExecutionDTO): types.ProcessExecution { + export function to(value: ProcessExecutionDTO): types.ProcessExecution | undefined { if (value === undefined || value === null) { return undefined; } @@ -105,13 +105,13 @@ namespace ProcessExecutionDTO { } namespace ShellExecutionOptionsDTO { - export function from(value: vscode.ShellExecutionOptions): ShellExecutionOptionsDTO { + export function from(value: vscode.ShellExecutionOptions): ShellExecutionOptionsDTO | undefined { if (value === undefined || value === null) { return undefined; } return value; } - export function to(value: ShellExecutionOptionsDTO): vscode.ShellExecutionOptions { + export function to(value: ShellExecutionOptionsDTO): vscode.ShellExecutionOptions | undefined { if (value === undefined || value === null) { return undefined; } @@ -124,7 +124,7 @@ namespace ShellExecutionDTO { const candidate = value as ShellExecutionDTO; return candidate && (!!candidate.commandLine || !!candidate.command); } - export function from(value: vscode.ShellExecution): ShellExecutionDTO { + export function from(value: vscode.ShellExecution): ShellExecutionDTO | undefined { if (value === undefined || value === null) { return undefined; } @@ -141,14 +141,14 @@ namespace ShellExecutionDTO { } return result; } - export function to(value: ShellExecutionDTO): types.ShellExecution { - if (value === undefined || value === null) { + export function to(value: ShellExecutionDTO): types.ShellExecution | undefined { + if (value === undefined || value === null || (value.command === undefined && value.commandLine === undefined)) { return undefined; } if (value.commandLine) { return new types.ShellExecution(value.commandLine, value.options); } else { - return new types.ShellExecution(value.command, value.args ? value.args : [], value.options); + return new types.ShellExecution(value.command!, value.args ? value.args : [], value.options); } } } @@ -173,8 +173,8 @@ namespace TaskHandleDTO { folder = value.scope.uri; } return { - id: value._id, - workspaceFolder: folder + id: value._id!, + workspaceFolder: folder! }; } } @@ -195,7 +195,7 @@ namespace TaskDTO { return result; } - export function from(value: vscode.Task, extension: IExtensionDescription): TaskDTO { + export function from(value: vscode.Task, extension: IExtensionDescription): TaskDTO | undefined { if (value === undefined || value === null) { return undefined; } @@ -207,7 +207,7 @@ namespace TaskDTO { } else if ((value).execution2 && (value).execution2 instanceof types.CustomExecution) { execution = CustomExecutionDTO.from((value).execution2); } - const definition: TaskDefinitionDTO = TaskDefinitionDTO.from(value.definition); + const definition: TaskDefinitionDTO | undefined = TaskDefinitionDTO.from(value.definition); let scope: number | UriComponents; if (value.scope) { if (typeof value.scope === 'number') { @@ -224,7 +224,7 @@ namespace TaskDTO { } const group = (value.group as types.TaskGroup) ? (value.group as types.TaskGroup).id : undefined; const result: TaskDTO = { - _id: (value as types.Task)._id, + _id: (value as types.Task)._id!, definition, name: value.name, source: { @@ -232,7 +232,7 @@ namespace TaskDTO { label: value.source, scope: scope }, - execution, + execution: execution!, isBackground: value.isBackground, group: group, presentationOptions: TaskPresentationOptionsDTO.from(value.presentationOptions), @@ -242,7 +242,7 @@ namespace TaskDTO { }; return result; } - export async function to(value: TaskDTO, workspace: IExtHostWorkspaceProvider): Promise { + export async function to(value: TaskDTO | undefined, workspace: IExtHostWorkspaceProvider): Promise { if (value === undefined || value === null) { return undefined; } @@ -252,7 +252,7 @@ namespace TaskDTO { } else if (ShellExecutionDTO.is(value.execution)) { execution = ShellExecutionDTO.to(value.execution); } - const definition: vscode.TaskDefinition = TaskDefinitionDTO.to(value.definition); + const definition: vscode.TaskDefinition | undefined = TaskDefinitionDTO.to(value.definition); let scope: vscode.TaskScope.Global | vscode.TaskScope.Workspace | vscode.WorkspaceFolder | undefined; if (value.source) { if (value.source.scope !== undefined) { @@ -268,7 +268,7 @@ namespace TaskDTO { if (!definition || !scope) { return undefined; } - const result = new types.Task(definition, scope, value.name, value.source.label, execution, value.problemMatchers); + const result = new types.Task(definition, scope, value.name!, value.source.label, execution, value.problemMatchers); if (value.isBackground !== undefined) { result.isBackground = value.isBackground; } @@ -276,7 +276,7 @@ namespace TaskDTO { result.group = types.TaskGroup.from(value.group); } if (value.presentationOptions) { - result.presentationOptions = TaskPresentationOptionsDTO.to(value.presentationOptions); + result.presentationOptions = TaskPresentationOptionsDTO.to(value.presentationOptions)!; } if (value._id) { result._id = value._id; @@ -286,11 +286,11 @@ namespace TaskDTO { } namespace TaskFilterDTO { - export function from(value: vscode.TaskFilter): TaskFilterDTO { + export function from(value: vscode.TaskFilter | undefined): TaskFilterDTO | undefined { return value; } - export function to(value: TaskFilterDTO): vscode.TaskFilter { + export function to(value: TaskFilterDTO): vscode.TaskFilter | undefined { if (!value) { return undefined; } @@ -320,7 +320,11 @@ class TaskExecutionImpl implements vscode.TaskExecution { namespace TaskExecutionDTO { export async function to(value: TaskExecutionDTO, tasks: ExtHostTask, workspaceProvider: IExtHostWorkspaceProvider): Promise { - return new TaskExecutionImpl(tasks, value.id, await TaskDTO.to(value.task, workspaceProvider)); + const task = await TaskDTO.to(value.task, workspaceProvider); + if (!task) { + throw new Error('Unexpected: Task cannot be created.'); + } + return new TaskExecutionImpl(tasks, value.id, task); } export function from(value: vscode.TaskExecution): TaskExecutionDTO { return { @@ -358,7 +362,7 @@ class CustomExecutionData implements IDisposable { } private onDidCloseTerminal(terminal: vscode.Terminal): void { - if (this.terminal === terminal) { + if ((this.terminal === terminal) && this._cancellationSource) { this._cancellationSource.cancel(); } } @@ -624,27 +628,30 @@ export class ExtHostTask implements ExtHostTaskShape { const taskIdPromises: Promise[] = []; const fetchPromise = asPromise(() => handler.provider.provideTasks(CancellationToken.None)).then(value => { const taskDTOs: TaskDTO[] = []; - for (let task of value) { - if (!task.definition || !validTypes[task.definition.type]) { - console.warn(`The task [${task.source}, ${task.name}] uses an undefined task type. The task will be ignored in the future.`); - } + if (value) { + for (let task of value) { + if (!task.definition || !validTypes[task.definition.type]) { + console.warn(`The task [${task.source}, ${task.name}] uses an undefined task type. The task will be ignored in the future.`); + } - const taskDTO: TaskDTO = TaskDTO.from(task, handler.extension); - taskDTOs.push(taskDTO); + const taskDTO: TaskDTO | undefined = TaskDTO.from(task, handler.extension); + if (taskDTO) { + taskDTOs.push(taskDTO); - if (CustomExecutionDTO.is(taskDTO.execution)) { - taskIdPromises.push(new Promise((resolve) => { - // The ID is calculated on the main thread task side, so, let's call into it here. - // We need the task id's pre-computed for custom task executions because when OnDidStartTask - // is invoked, we have to be able to map it back to our data. - this._proxy.$createTaskId(taskDTO).then((taskId) => { - this._providedCustomExecutions.set(taskId, new CustomExecutionData((task).execution2, this._terminalService)); - resolve(); - }); - })); + if (CustomExecutionDTO.is(taskDTO.execution)) { + taskIdPromises.push(new Promise((resolve) => { + // The ID is calculated on the main thread task side, so, let's call into it here. + // We need the task id's pre-computed for custom task executions because when OnDidStartTask + // is invoked, we have to be able to map it back to our data. + this._proxy.$createTaskId(taskDTO).then((taskId) => { + this._providedCustomExecutions.set(taskId, new CustomExecutionData((task).execution2, this._terminalService)); + resolve(); + }); + })); + } + } } } - return { tasks: taskDTOs, extension: handler.extension @@ -664,11 +671,14 @@ export class ExtHostTask implements ExtHostTaskShape { const configProvider = await this._configurationService.getConfigProvider(); const uri: URI = URI.revive(uriComponents); const result = { - process: undefined as string, + process: undefined as string, variables: Object.create(null) }; const workspaceFolder = await this._workspaceProvider.resolveWorkspaceFolder(uri); const workspaceFolders = await this._workspaceProvider.getWorkspaceFolders2(); + 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 ws: IWorkspaceFolder = { uri: workspaceFolder.uri, @@ -704,16 +714,24 @@ export class ExtHostTask implements ExtHostTaskShape { private async getTaskExecution(execution: TaskExecutionDTO | string, task?: vscode.Task): Promise { if (typeof execution === 'string') { - return this._taskExecutions.get(execution); + const taskExecution = this._taskExecutions.get(execution); + if (!taskExecution) { + throw new Error('Unexpected: The specified task is missing an execution'); + } + return taskExecution; } - let result: TaskExecutionImpl = this._taskExecutions.get(execution.id); + let result: TaskExecutionImpl | undefined = this._taskExecutions.get(execution.id); if (result) { return result; } - result = new TaskExecutionImpl(this, execution.id, task ? task : await TaskDTO.to(execution.task, this._workspaceProvider)); - this._taskExecutions.set(execution.id, result); - return result; + const taskToCreate = task ? task : await TaskDTO.to(execution.task, this._workspaceProvider); + if (!taskToCreate) { + throw new Error('Unexpected: Task does not exist.'); + } + const createdResult: TaskExecutionImpl = new TaskExecutionImpl(this, execution.id, taskToCreate); + this._taskExecutions.set(execution.id, createdResult); + return createdResult; } private customExecutionComplete(execution: TaskExecutionDTO): void { diff --git a/src/vs/workbench/api/shared/tasks.ts b/src/vs/workbench/api/shared/tasks.ts index 0abf582d133..592929e503c 100644 --- a/src/vs/workbench/api/shared/tasks.ts +++ b/src/vs/workbench/api/shared/tasks.ts @@ -102,7 +102,7 @@ export interface TaskSetDTO { export interface TaskExecutionDTO { id: string; - task: TaskDTO; + task: TaskDTO | undefined; } export interface TaskProcessStartedDTO {