diff --git a/src/vs/workbench/api/node/extHostTask.ts b/src/vs/workbench/api/node/extHostTask.ts index 94e98f427f9de180592d9a76458cad8b7e5d531c..a174c82f1b7a235b62e50465325341c41de1105c 100644 --- a/src/vs/workbench/api/node/extHostTask.ts +++ b/src/vs/workbench/api/node/extHostTask.ts @@ -329,7 +329,7 @@ namespace Tasks { let source = { kind: TaskSystem.TaskSourceKind.Extension, label: typeof task.source === 'string' ? task.source : extension.name, - detail: extension.id + extension: extension.id }; let label = nls.localize('task.label', '{0}: {1}', source.label, task.name); let key = (task as types.Task).definitionKey; diff --git a/src/vs/workbench/parts/tasks/browser/quickOpen.ts b/src/vs/workbench/parts/tasks/browser/quickOpen.ts index 43100082a478e2521ee12c14228044c9de233275..08d7dda6710a1dabb76c3d4a585eb234c3ff75e4 100644 --- a/src/vs/workbench/parts/tasks/browser/quickOpen.ts +++ b/src/vs/workbench/parts/tasks/browser/quickOpen.ts @@ -15,13 +15,13 @@ import QuickOpen = require('vs/base/parts/quickopen/common/quickOpen'); import Model = require('vs/base/parts/quickopen/browser/quickOpenModel'); import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen'; -import { Task, TaskSourceKind } from 'vs/workbench/parts/tasks/common/tasks'; +import { Task, CustomTask, ContributedTask } from 'vs/workbench/parts/tasks/common/tasks'; import { ITaskService, RunOptions } from 'vs/workbench/parts/tasks/common/taskService'; import { ActionBarContributor, ContributableActionProvider } from 'vs/workbench/browser/actions'; export class TaskEntry extends Model.QuickOpenEntry { - constructor(protected taskService: ITaskService, protected quickOpenService: IQuickOpenService, protected _task: Task, highlights: Model.IHighlight[] = []) { + constructor(protected taskService: ITaskService, protected quickOpenService: IQuickOpenService, protected _task: CustomTask | ContributedTask, highlights: Model.IHighlight[] = []) { super(highlights); } @@ -33,11 +33,11 @@ export class TaskEntry extends Model.QuickOpenEntry { return nls.localize('entryAriaLabel', "{0}, tasks", this.getLabel()); } - public get task(): Task { + public get task(): CustomTask | ContributedTask { return this._task; } - protected doRun(task: Task, options?: RunOptions): boolean { + protected doRun(task: CustomTask | ContributedTask, options?: RunOptions): boolean { this.taskService.run(task, options); if (task.command.presentation.focus) { this.quickOpenService.close(); @@ -55,7 +55,7 @@ export class TaskGroupEntry extends Model.QuickOpenEntryGroup { export abstract class QuickOpenHandler extends Quickopen.QuickOpenHandler { - private tasks: TPromise; + private tasks: TPromise<(CustomTask | ContributedTask)[]>; constructor( @@ -83,10 +83,10 @@ export abstract class QuickOpenHandler extends Quickopen.QuickOpenHandler { return new Model.QuickOpenModel(entries); } let recentlyUsedTasks = this.taskService.getRecentlyUsedTasks(); - let recent: Task[] = []; - let configured: Task[] = []; - let detected: Task[] = []; - let taskMap: IStringDictionary = Object.create(null); + let recent: (CustomTask | ContributedTask)[] = []; + let configured: CustomTask[] = []; + let detected: ContributedTask[] = []; + let taskMap: IStringDictionary = Object.create(null); tasks.forEach(task => taskMap[Task.getKey(task)] = task); recentlyUsedTasks.keys().forEach(key => { let task = taskMap[key]; @@ -96,7 +96,7 @@ export abstract class QuickOpenHandler extends Quickopen.QuickOpenHandler { }); for (let task of tasks) { if (!recentlyUsedTasks.has(Task.getKey(task))) { - if (task._source.kind === TaskSourceKind.Workspace) { + if (CustomTask.is(task)) { configured.push(task); } else { detected.push(task); @@ -114,7 +114,7 @@ export abstract class QuickOpenHandler extends Quickopen.QuickOpenHandler { }); } - private fillEntries(entries: Model.QuickOpenEntry[], input: string, tasks: Task[], groupLabel: string, withBorder: boolean = false) { + private fillEntries(entries: Model.QuickOpenEntry[], input: string, tasks: (CustomTask | ContributedTask)[], groupLabel: string, withBorder: boolean = false) { let first = true; for (let task of tasks) { let highlights = Filters.matchesFuzzy(input, task._label); @@ -130,9 +130,9 @@ export abstract class QuickOpenHandler extends Quickopen.QuickOpenHandler { } } - protected abstract getTasks(): TPromise; + protected abstract getTasks(): TPromise<(CustomTask | ContributedTask)[]>; - protected abstract createEntry(task: Task, highlights: Model.IHighlight[]): TaskEntry; + protected abstract createEntry(task: CustomTask | ContributedTask, highlights: Model.IHighlight[]): TaskEntry; public getAutoFocus(input: string): QuickOpen.IAutoFocus { return { @@ -146,7 +146,7 @@ class CustomizeTaskAction extends Action { private static ID = 'workbench.action.tasks.customizeTask'; private static LABEL = nls.localize('customizeTask', "Configure Task"); - constructor(private taskService: ITaskService, private quickOpenService: IQuickOpenService, private task: Task) { + constructor(private taskService: ITaskService, private quickOpenService: IQuickOpenService, private task: CustomTask | ContributedTask) { super(CustomizeTaskAction.ID, CustomizeTaskAction.LABEL); this.updateClass(); } @@ -156,9 +156,15 @@ class CustomizeTaskAction extends Action { } public run(context: any): TPromise { - return this.taskService.customize(this.task, undefined, true).then(() => { - this.quickOpenService.close(); - }); + if (ContributedTask.is(this.task)) { + return this.taskService.customize(this.task, undefined, true).then(() => { + this.quickOpenService.close(); + }); + } else { + return this.taskService.openConfig(this.task).then(() => { + this.quickOpenService.close(); + }); + } } } @@ -177,13 +183,13 @@ export class QuickOpenActionContributor extends ActionBarContributor { public getActions(context: any): IAction[] { let actions: Action[] = []; let task = this.getTask(context); - if (task && task._source.kind === TaskSourceKind.Extension) { + if (task && ContributedTask.is(task) || CustomTask.is(task)) { actions.push(new CustomizeTaskAction(this.taskService, this.quickOpenService, task)); } return actions; } - private getTask(context: any): Task { + private getTask(context: any): CustomTask | ContributedTask { if (!context) { return undefined; } diff --git a/src/vs/workbench/parts/tasks/browser/taskQuickOpen.ts b/src/vs/workbench/parts/tasks/browser/taskQuickOpen.ts index fee8a1e6bbd1ce931c059536d6d968a9af0272a9..46d3c0232008f0a43d224ad96b45525616aefd8e 100644 --- a/src/vs/workbench/parts/tasks/browser/taskQuickOpen.ts +++ b/src/vs/workbench/parts/tasks/browser/taskQuickOpen.ts @@ -10,7 +10,7 @@ import QuickOpen = require('vs/base/parts/quickopen/common/quickOpen'); import Model = require('vs/base/parts/quickopen/browser/quickOpenModel'); import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen'; -import { Task } from 'vs/workbench/parts/tasks/common/tasks'; +import { CustomTask, ContributedTask } from 'vs/workbench/parts/tasks/common/tasks'; import { ITaskService } from 'vs/workbench/parts/tasks/common/taskService'; import { IExtensionService } from 'vs/platform/extensions/common/extensions'; @@ -18,7 +18,7 @@ import { IExtensionService } from 'vs/platform/extensions/common/extensions'; import * as base from './quickOpen'; class TaskEntry extends base.TaskEntry { - constructor(taskService: ITaskService, quickOpenService: IQuickOpenService, task: Task, highlights: Model.IHighlight[] = []) { + constructor(taskService: ITaskService, quickOpenService: IQuickOpenService, task: CustomTask | ContributedTask, highlights: Model.IHighlight[] = []) { super(taskService, quickOpenService, task, highlights); } @@ -47,13 +47,13 @@ export class QuickOpenHandler extends base.QuickOpenHandler { return nls.localize('tasksAriaLabel', "Type the name of a task to run"); } - protected getTasks(): TPromise { + protected getTasks(): TPromise<(CustomTask | ContributedTask)[]> { return this.activationPromise.then(() => { - return this.taskService.tasks(); + return this.taskService.tasks().then(tasks => tasks.filter((task): task is CustomTask | ContributedTask => ContributedTask.is(task) || CustomTask.is(task))); }); } - protected createEntry(task: Task, highlights: Model.IHighlight[]): base.TaskEntry { + protected createEntry(task: CustomTask | ContributedTask, highlights: Model.IHighlight[]): base.TaskEntry { return new TaskEntry(this.taskService, this.quickOpenService, task, highlights); } diff --git a/src/vs/workbench/parts/tasks/common/taskService.ts b/src/vs/workbench/parts/tasks/common/taskService.ts index a2cdeb91456373a7dae9ea8f6f1d8b0ab60333c7..7598b1703981a35b60f7769047f4339cfcc88d0c 100644 --- a/src/vs/workbench/parts/tasks/common/taskService.ts +++ b/src/vs/workbench/parts/tasks/common/taskService.ts @@ -9,7 +9,7 @@ import { Action } from 'vs/base/common/actions'; import { IEventEmitter } from 'vs/base/common/eventEmitter'; import { LinkedMap } from 'vs/base/common/map'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import { Task, TaskSet } from 'vs/workbench/parts/tasks/common/tasks'; +import { Task, ContributedTask, CustomTask, TaskSet } from 'vs/workbench/parts/tasks/common/tasks'; import { ITaskSummary, TaskEvent, TaskType, TaskTerminateResponse } from 'vs/workbench/parts/tasks/common/taskSystem'; export { ITaskSummary, Task, TaskEvent, TaskType, TaskTerminateResponse }; @@ -60,7 +60,8 @@ export interface ITaskService extends IEventEmitter { getRecentlyUsedTasks(): LinkedMap; canCustomize(): boolean; - customize(task: Task, properties?: {}, openConfig?: boolean): TPromise; + customize(task: ContributedTask | CustomTask, properties?: {}, openConfig?: boolean): TPromise; + openConfig(task: CustomTask): TPromise; registerTaskProvider(handle: number, taskProvider: ITaskProvider): void; unregisterTaskProvider(handle: number): boolean; diff --git a/src/vs/workbench/parts/tasks/common/tasks.ts b/src/vs/workbench/parts/tasks/common/tasks.ts index 04c51da7bebf8c92d0e367a9982abcef5c9386ad..9c9f0bbeb53ffbaae3e6c6039e0beb2f111e5f22 100644 --- a/src/vs/workbench/parts/tasks/common/tasks.ts +++ b/src/vs/workbench/parts/tasks/common/tasks.ts @@ -214,22 +214,38 @@ export namespace TaskGroup { export type TaskGroup = 'clean' | 'build' | 'rebuild' | 'test'; -export enum TaskSourceKind { - Workspace = 1, - Extension = 2, - Generic = 3 + +export namespace TaskSourceKind { + export const Workspace: 'workspace' = 'workspace'; + export const Extension: 'extension' = 'extension'; + export const Composite: 'composite' = 'composite'; +} + +export interface TaskSourceConfigElement { + file: string; + index: number; + element: any; +} + +export interface WorkspaceTaskSource { + kind: 'workspace'; + label: string; + config: TaskSourceConfigElement; } -export interface TaskSource { - kind: TaskSourceKind; +export interface ExtensionTaskSource { + kind: 'extension'; label: string; - detail?: string; - config?: { - index: number; - element: any; - }; + extension: string; } +export interface CompositeTaskSource { + kind: 'composite'; + label: string; +} + +export type TaskSource = WorkspaceTaskSource | ExtensionTaskSource | CompositeTaskSource; + export interface TaskIdentifier { _key: string; type: string; @@ -295,11 +311,6 @@ export interface CommonTask { */ _label: string; - /** - * Indicated the source of the task (e.g tasks.json or extension) - */ - _source: TaskSource; - type: string; } @@ -307,6 +318,11 @@ export interface CustomTask extends CommonTask, ConfigurationProperties { type: 'custom'; + /** + * Indicated the source of the task (e.g tasks.json or extension) + */ + _source: WorkspaceTaskSource; + name: string; identifier: string; @@ -326,6 +342,11 @@ export namespace CustomTask { export interface ConfiguringTask extends CommonTask, ConfigurationProperties { + /** + * Indicated the source of the task (e.g tasks.json or extension) + */ + _source: WorkspaceTaskSource; + configures: TaskIdentifier; } @@ -338,6 +359,11 @@ export namespace ConfiguringTask { export interface ContributedTask extends CommonTask, ConfigurationProperties { + /** + * Indicated the source of the task (e.g tasks.json or extension) + */ + _source: ExtensionTaskSource; + defines: TaskIdentifier; hasDefinedMatchers: boolean; @@ -355,11 +381,29 @@ export namespace ContributedTask { } } -export type Task = CustomTask | ContributedTask; +export interface CompositeTask extends CommonTask, ConfigurationProperties { + /** + * Indicated the source of the task (e.g tasks.json or extension) + */ + _source: CompositeTaskSource; + + type: 'composite'; + + identifier: string; +} + +export namespace CompositeTask { + export function is(value: any): value is CompositeTask { + let candidate = value as CompositeTask; + return candidate && candidate._source && candidate._source.kind === TaskSourceKind.Composite; + } +} + +export type Task = CustomTask | ContributedTask | CompositeTask; export namespace Task { export function getKey(task: Task): string { - if (CustomTask.is(task)) { + if (CustomTask.is(task) || CompositeTask.is(task)) { return task.identifier; } else { return task.defines._key; diff --git a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts index c7b53ce1d6be04bcf5a2ee1d5cafaf91faa0d102..3230d75c002f517d34a5d2d235d5322b50856e9f 100644 --- a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts +++ b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts @@ -76,7 +76,7 @@ import { Scope, IActionBarRegistry, Extensions as ActionBarExtensions } from 'vs import { ITerminalService } from 'vs/workbench/parts/terminal/common/terminal'; import { ITaskSystem, ITaskResolver, ITaskSummary, ITaskExecuteResult, TaskExecuteKind, TaskError, TaskErrors, TaskSystemEvents, TaskTerminateResponse } from 'vs/workbench/parts/tasks/common/taskSystem'; -import { Task, CustomTask, ConfiguringTask, ContributedTask, TaskSet, TaskGroup, ExecutionEngine, JsonSchemaVersion, TaskSourceKind, TaskIdentifier } from 'vs/workbench/parts/tasks/common/tasks'; +import { Task, CustomTask, ConfiguringTask, ContributedTask, CompositeTask, TaskSet, TaskGroup, ExecutionEngine, JsonSchemaVersion, TaskSourceKind, TaskIdentifier } from 'vs/workbench/parts/tasks/common/tasks'; import { ITaskService, TaskServiceEvents, ITaskProvider, TaskEvent, RunOptions, CustomizationProperties } from 'vs/workbench/parts/tasks/common/taskService'; import { templates as taskTemplates } from 'vs/workbench/parts/tasks/common/taskTemplates'; @@ -927,7 +927,7 @@ class TaskService extends EventEmitter implements ITaskService { if (!toExecute) { throw new TaskError(Severity.Info, nls.localize('TaskServer.noTask', 'Requested task {0} to execute not found.', requested), TaskErrors.TaskNotFound); } else { - if (options && options.attachProblemMatcher && this.shouldAttachProblemMatcher(toExecute)) { + if (options && options.attachProblemMatcher && this.shouldAttachProblemMatcher(toExecute) && !CompositeTask.is(toExecute)) { return this.attachProblemMatcher(toExecute).then((toExecute) => { if (toExecute) { return this.executeTask(toExecute, resolver); @@ -954,14 +954,17 @@ class TaskService extends EventEmitter implements ITaskService { if (task.problemMatchers !== void 0 && task.problemMatchers.length > 0) { return false; } - if (task._source.config === void 0 && ContributedTask.is(task)) { + if (ContributedTask.is(task)) { return !task.hasDefinedMatchers && task.problemMatchers.length === 0; } - let configProperties: TaskConfig.ConfigurationProperties = task._source.config.element; - return configProperties.problemMatcher === void 0; + if (CustomTask.is(task)) { + let configProperties: TaskConfig.ConfigurationProperties = task._source.config.element; + return configProperties.problemMatcher === void 0; + } + return false; } - private attachProblemMatcher(task: Task): TPromise { + private attachProblemMatcher(task: ContributedTask | CustomTask): TPromise { interface ProblemMatcherPickEntry extends IPickOpenEntry { matcher: NamedProblemMatcher; never?: boolean; @@ -1037,16 +1040,17 @@ class TaskService extends EventEmitter implements ITaskService { return this.getJsonSchemaVersion() === JsonSchemaVersion.V2_0_0; } - public customize(task: Task, properties?: CustomizationProperties, openConfig?: boolean): TPromise { + public customize(task: ContributedTask | CustomTask, properties?: CustomizationProperties, openConfig?: boolean): TPromise { let configuration = this.getConfiguration(); if (configuration.hasParseErrors) { this.messageService.show(Severity.Warning, nls.localize('customizeParseErrors', 'The current task configuration has errors. Please fix the errors first before customizing a task.')); return TPromise.as(undefined); } + let fileConfig = configuration.config; let index: number; let toCustomize: TaskConfig.CustomTask | TaskConfig.ConfiguringTask; - let taskConfig = task._source.config; + let taskConfig = CustomTask.is(task) ? task._source.config : undefined; if (taskConfig && taskConfig.element) { index = taskConfig.index; toCustomize = taskConfig.element; @@ -1142,6 +1146,17 @@ class TaskService extends EventEmitter implements ITaskService { }); } + public openConfig(task: CustomTask): TPromise { + let resource = this.contextService.toResource(task._source.config.file); + return this.editorService.openEditor({ + resource: resource, + options: { + forceOpen: true, + pinned: false + } + }, false).then(() => undefined); + } + private createRunnableTask(sets: TaskSet[], group: TaskGroup): { task: Task; resolver: ITaskResolver } { let idMap: IStringDictionary = Object.create(null); let labelMap: IStringDictionary = Object.create(null); @@ -1184,15 +1199,14 @@ class TaskService extends EventEmitter implements ITaskService { return { task: extensionTasks[0], resolver }; } else { let id: string = UUID.generateUuid(); - let task: CustomTask = { + let task: CompositeTask = { _id: id, - _source: { kind: TaskSourceKind.Generic, label: 'generic' }, + _source: { kind: TaskSourceKind.Composite, label: 'composite' }, _label: id, - type: 'custom', + type: 'composite', name: id, identifier: id, - dependsOn: extensionTasks.map(task => task._id), - command: undefined, + dependsOn: extensionTasks.map(task => task._id) }; return { task, resolver }; } @@ -1381,8 +1395,8 @@ class TaskService extends EventEmitter implements ITaskService { }); } - private getLegacyTaskConfigurations(workspaceTasks: TaskSet): IStringDictionary { - let result: IStringDictionary; + private getLegacyTaskConfigurations(workspaceTasks: TaskSet): IStringDictionary { + let result: IStringDictionary; function getResult() { if (result) { return result; @@ -1943,7 +1957,9 @@ class TaskService extends EventEmitter implements ITaskService { if (!task) { return; } - this.customize(task, { group: { kind: 'build', isDefault: true } }, true); + if (!CompositeTask.is(task)) { + this.customize(task, { group: { kind: 'build', isDefault: true } }, true); + } }); })); } else { @@ -1975,7 +1991,9 @@ class TaskService extends EventEmitter implements ITaskService { if (!task) { return; } - this.customize(task, { group: { kind: 'test', isDefault: true } }, true); + if (!CompositeTask.is(task)) { + this.customize(task, { group: { kind: 'test', isDefault: true } }, true); + } }); })); } else { diff --git a/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.ts b/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.ts index e77f0a6cf966cf4a5018f7cf4f22a7118aca6ac5..1bc9d5d626ae554c4c2a268d6f7ba5a5473eef05 100644 --- a/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.ts +++ b/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.ts @@ -34,7 +34,7 @@ import { IConfigurationResolverService } from 'vs/workbench/services/configurati import { ITerminalService, ITerminalInstance, IShellLaunchConfig } from 'vs/workbench/parts/terminal/common/terminal'; import { IOutputService, IOutputChannel } from 'vs/workbench/parts/output/common/output'; import { StartStopProblemCollector, WatchingProblemCollector, ProblemCollectorEvents } from 'vs/workbench/parts/tasks/common/problemCollectors'; -import { Task, RevealKind, CommandOptions, ShellConfiguration, RuntimeType, PanelKind } from 'vs/workbench/parts/tasks/common/tasks'; +import { Task, CustomTask, ContributedTask, RevealKind, CommandOptions, ShellConfiguration, RuntimeType, PanelKind } from 'vs/workbench/parts/tasks/common/tasks'; import { ITaskSystem, ITaskSummary, ITaskExecuteResult, TaskExecuteKind, TaskError, TaskErrors, ITaskResolver, TelemetryEvent, Triggers, TaskSystemEvents, TaskEvent, TaskType, TaskTerminateResponse @@ -140,8 +140,12 @@ export class TerminalTaskSystem extends EventEmitter implements ITaskSystem { public run(task: Task, resolver: ITaskResolver, trigger: string = Triggers.command): ITaskExecuteResult { let terminalData = this.activeTasks[task._id]; if (terminalData && terminalData.promise) { - let reveal = task.command.presentation.reveal; - let focus = task.command.presentation.focus; + let reveal = RevealKind.Always; + let focus = false; + if (CustomTask.is(task) || ContributedTask.is(task)) { + reveal = task.command.presentation.reveal; + focus = task.command.presentation.focus; + } if (reveal === RevealKind.Always || focus) { this.terminalService.setActiveInstance(terminalData.terminal); this.terminalService.showPanel(focus); @@ -171,7 +175,9 @@ export class TerminalTaskSystem extends EventEmitter implements ITaskSystem { return false; } this.terminalService.setActiveInstance(terminalData.terminal); - this.terminalService.showPanel(task.command.presentation.focus); + if (CustomTask.is(task) || ContributedTask.is(task)) { + this.terminalService.showPanel(task.command.presentation.focus); + } return true; } @@ -253,7 +259,7 @@ export class TerminalTaskSystem extends EventEmitter implements ITaskSystem { }); } - if (task.command) { + if (ContributedTask.is(task) || CustomTask.is(task)) { return TPromise.join(promises).then((summaries): TPromise | ITaskSummary => { for (let summary of summaries) { if (summary.exitCode !== 0) { @@ -274,7 +280,7 @@ export class TerminalTaskSystem extends EventEmitter implements ITaskSystem { } } - private executeCommand(task: Task, trigger: string): TPromise { + private executeCommand(task: CustomTask | ContributedTask, trigger: string): TPromise { let terminal: ITerminalInstance = undefined; let executedCommand: string = undefined; let promise: TPromise = undefined; @@ -420,7 +426,7 @@ export class TerminalTaskSystem extends EventEmitter implements ITaskSystem { }); } - private createTerminal(task: Task): [ITerminalInstance, string] { + private createTerminal(task: CustomTask | ContributedTask): [ITerminalInstance, string] { let options = this.resolveOptions(task.command.options); let { command, args } = this.resolveCommandAndArgs(task); let terminalName = nls.localize('TerminalTaskSystem.terminalName', 'Task - {0}', task.name); @@ -556,7 +562,7 @@ export class TerminalTaskSystem extends EventEmitter implements ITaskSystem { return [result, command]; } - private resolveCommandAndArgs(task: Task): { command: string, args: string[] } { + private resolveCommandAndArgs(task: CustomTask | ContributedTask): { command: string, args: string[] } { // First we need to use the command args: let args: string[] = task.command.args ? task.command.args.slice() : []; args = this.resolveVariables(args); diff --git a/src/vs/workbench/parts/tasks/node/processTaskSystem.ts b/src/vs/workbench/parts/tasks/node/processTaskSystem.ts index a33e32bf8ce0bf234812502e68aee1a30e0c6235..50d15ffa2bfbc6c0d49250feb60f866291a8c476 100644 --- a/src/vs/workbench/parts/tasks/node/processTaskSystem.ts +++ b/src/vs/workbench/parts/tasks/node/processTaskSystem.ts @@ -31,7 +31,7 @@ import { ITaskSystem, ITaskSummary, ITaskExecuteResult, TaskExecuteKind, TaskError, TaskErrors, TelemetryEvent, Triggers, TaskSystemEvents, TaskEvent, TaskType, TaskTerminateResponse } from 'vs/workbench/parts/tasks/common/taskSystem'; -import { Task, CommandOptions, RevealKind, CommandConfiguration, RuntimeType } from 'vs/workbench/parts/tasks/common/tasks'; +import { Task, CustomTask, CommandOptions, RevealKind, CommandConfiguration, RuntimeType } from 'vs/workbench/parts/tasks/common/tasks'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; @@ -50,7 +50,7 @@ export class ProcessTaskSystem extends EventEmitter implements ITaskSystem { private errorsShown: boolean; private childProcess: LineProcess; - private activeTask: Task; + private activeTask: CustomTask; private activeTaskPromise: TPromise; constructor(markerService: IMarkerService, modelService: IModelService, telemetryService: ITelemetryService, @@ -133,6 +133,9 @@ export class ProcessTaskSystem extends EventEmitter implements ITaskSystem { } private executeTask(task: Task, trigger: string = Triggers.command): ITaskExecuteResult { + if (!CustomTask.is(task)) { + throw new Error('The process task system can only execute custom tasks.'); + } let telemetryEvent: TelemetryEvent = { trigger: trigger, runner: 'output', @@ -166,7 +169,7 @@ export class ProcessTaskSystem extends EventEmitter implements ITaskSystem { } } - private doExecuteTask(task: Task, telemetryEvent: TelemetryEvent): ITaskExecuteResult { + private doExecuteTask(task: CustomTask, telemetryEvent: TelemetryEvent): ITaskExecuteResult { let taskSummary: ITaskSummary = {}; let commandConfig: CommandConfiguration = task.command; if (!this.errorsShown) { @@ -288,7 +291,7 @@ export class ProcessTaskSystem extends EventEmitter implements ITaskSystem { this.activeTaskPromise = null; } - private handleError(task: Task, errorData: ErrorData): Promise { + private handleError(task: CustomTask, errorData: ErrorData): Promise { let makeVisible = false; if (errorData.error && !errorData.terminated) { let args: string = task.command.args ? task.command.args.join(' ') : ''; diff --git a/src/vs/workbench/parts/tasks/node/taskConfiguration.ts b/src/vs/workbench/parts/tasks/node/taskConfiguration.ts index cc165901adc2772a926122b2bee0da14886d7164..f24a70ea5e1b3405284ca827db699fee1450241e 100644 --- a/src/vs/workbench/parts/tasks/node/taskConfiguration.ts +++ b/src/vs/workbench/parts/tasks/node/taskConfiguration.ts @@ -1019,7 +1019,7 @@ namespace TaskIdentifier { const source: Tasks.TaskSource = { kind: Tasks.TaskSourceKind.Workspace, label: 'Workspace', - detail: '.settins\\tasks.json' + config: undefined }; namespace GroupKind { @@ -1130,7 +1130,7 @@ namespace ConfiguringTask { } let typeDeclaration = TaskDefinitionRegistry.get(type); if (!typeDeclaration) { - let message = nls.localize('ConfigurationParser.noTypeDefinition', 'Error: there is not registered task type \'{0}\'. Did you miss to install an extension that provides a corresponding task provider?', type); + let message = nls.localize('ConfigurationParser.noTypeDefinition', 'Error: there is no registered task type \'{0}\'. Did you miss to install an extension that provides a corresponding task provider?', type); context.problemReporter.error(message); return undefined; } @@ -1159,11 +1159,16 @@ namespace ConfiguringTask { }); } let taskIdentifier = TaskIdentifier.from(identifier); + let configElement: Tasks.TaskSourceConfigElement = { + file: '.vscode\\tasks.json', + index, + element: external + }; let result: Tasks.ConfiguringTask = { type: type, configures: taskIdentifier, _id: taskIdentifier._key, - _source: Objects.assign({}, source, { config: { index, element: external } }), + _source: Objects.assign({}, source, { config: configElement }), _label: undefined }; let configuration = ConfigurationProperties.from(external, context, true); @@ -1215,7 +1220,7 @@ namespace CustomTask { let result: Tasks.CustomTask = { type: 'custom', _id: context.uuidMap.getUUID(taskName), - _source: Objects.assign({}, source, { config: { index, element: external } }), + _source: Objects.assign({}, source, { config: { index, element: external, file: '.vscode\\tasks.json' } }), _label: taskName, name: taskName, identifier: taskName, @@ -1278,7 +1283,7 @@ namespace CustomTask { } } - export function createCustomTask(contributedTask: Tasks.ContributedTask, configuredProps: Tasks.ConfigurationProperties & { _id: string, _source: Tasks.TaskSource }): Tasks.CustomTask { + export function createCustomTask(contributedTask: Tasks.ContributedTask, configuredProps: Tasks.ConfigurationProperties & { _id: string, _source: Tasks.WorkspaceTaskSource }): Tasks.CustomTask { let result: Tasks.CustomTask = { _id: configuredProps._id, _source: configuredProps._source, @@ -1788,7 +1793,7 @@ export function parse(configuration: ExternalTaskRunnerConfiguration, logger: IP } } -export function createCustomTask(contributedTask: Tasks.ContributedTask, configuredProps: Tasks.ConfigurationProperties & { _id: string; _source: Tasks.TaskSource }): Tasks.CustomTask { +export function createCustomTask(contributedTask: Tasks.ContributedTask, configuredProps: Tasks.ConfigurationProperties & { _id: string; _source: Tasks.WorkspaceTaskSource }): Tasks.CustomTask { return CustomTask.createCustomTask(contributedTask, configuredProps); } diff --git a/src/vs/workbench/parts/tasks/test/electron-browser/configuration.test.ts b/src/vs/workbench/parts/tasks/test/electron-browser/configuration.test.ts index 57cc1bd1b38d2f886774be684a3cc4d8911f8c22..c89319b81dde8b8d05a25cd0702b79e86fdc79c2 100644 --- a/src/vs/workbench/parts/tasks/test/electron-browser/configuration.test.ts +++ b/src/vs/workbench/parts/tasks/test/electron-browser/configuration.test.ts @@ -177,7 +177,7 @@ class CustomTaskBuilder { this.commandBuilder = new CommandConfigurationBuilder(this, command); this.result = { _id: name, - _source: { kind: Tasks.TaskSourceKind.Workspace, label: 'workspace' }, + _source: { kind: Tasks.TaskSourceKind.Workspace, label: 'workspace', config: { element: undefined, index: -1, file: '.vscode/tasks.json' } }, _label: name, type: 'custom', identifier: name, @@ -450,7 +450,9 @@ function assertConfiguration(result: ParseResult, expected: Tasks.Task[]): void function assertTask(actual: Tasks.Task, expected: Tasks.Task) { assert.ok(actual._id); assert.strictEqual(actual.name, expected.name, 'name'); - assertCommandConfiguration(actual.command, expected.command); + if (!Tasks.CompositeTask.is(actual) && !Tasks.CompositeTask.is(expected)) { + assertCommandConfiguration(actual.command, expected.command); + } assert.strictEqual(actual.isBackground, expected.isBackground, 'isBackground'); assert.strictEqual(typeof actual.problemMatchers, typeof expected.problemMatchers); assert.strictEqual(actual.promptOnClose, expected.promptOnClose, 'promptOnClose');