diff --git a/src/vs/workbench/api/electron-browser/mainThreadTask.ts b/src/vs/workbench/api/electron-browser/mainThreadTask.ts index 7cd98fc3b00..c583a9a4c23 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadTask.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadTask.ts @@ -297,18 +297,18 @@ namespace TaskDTO { } let result: TaskDTO = { _id: task._id, - name: task.name, - definition: TaskDefinitionDTO.from(Task.getTaskDefinition(task)), + name: task.configurationProperties.name, + definition: TaskDefinitionDTO.from(task.getDefinition()), source: TaskSourceDTO.from(task._source), execution: undefined, presentationOptions: task.command ? TaskPresentationOptionsDTO.from(task.command.presentation) : undefined, - isBackground: task.isBackground, + isBackground: task.configurationProperties.isBackground, problemMatchers: [], hasDefinedMatchers: ContributedTask.is(task) ? task.hasDefinedMatchers : false, runOptions: RunOptionsDTO.from(task.runOptions), }; - if (task.group) { - result.group = task.group; + if (task.configurationProperties.group) { + result.group = task.configurationProperties.group; } if (task.command) { if (task.command.runtime === RuntimeType.Process) { @@ -317,8 +317,8 @@ namespace TaskDTO { result.execution = ShellExecutionDTO.from(task.command); } } - if (task.problemMatchers) { - for (let matcher of task.problemMatchers) { + if (task.configurationProperties.problemMatchers) { + for (let matcher of task.configurationProperties.problemMatchers) { if (Types.isString(matcher)) { result.problemMatchers.push(matcher); } @@ -327,7 +327,7 @@ namespace TaskDTO { return result; } - export function to(task: TaskDTO, workspace: IWorkspaceContextService, executeOnly: boolean): Task { + export function to(task: TaskDTO, workspace: IWorkspaceContextService, executeOnly: boolean): ContributedTask { if (typeof task.name !== 'string') { return undefined; } @@ -346,21 +346,23 @@ namespace TaskDTO { let label = nls.localize('task.label', '{0}: {1}', source.label, task.name); let definition = TaskDefinitionDTO.to(task.definition, executeOnly); let id = `${task.source.extensionId}.${definition._key}`; - let result: ContributedTask = { - _id: id, // uuidMap.getUUID(identifier) - _source: source, - _label: label, - type: definition.type, - defines: definition, - name: task.name, - identifier: label, - group: task.group, - command: command, - isBackground: !!task.isBackground, - problemMatchers: task.problemMatchers.slice(), - hasDefinedMatchers: task.hasDefinedMatchers, - runOptions: RunOptionsDTO.to(task.runOptions), - }; + let result: ContributedTask = new ContributedTask( + id, // uuidMap.getUUID(identifier) + source, + label, + definition.type, + definition, + command, + task.hasDefinedMatchers, + RunOptionsDTO.to(task.runOptions), + { + name: task.name, + identifier: label, + group: task.group, + isBackground: !!task.isBackground, + problemMatchers: task.problemMatchers.slice(), + } + ); return result; } } @@ -392,13 +394,13 @@ export class MainThreadTask implements MainThreadTaskShape { this._taskService.onDidStateChange((event: TaskEvent) => { let task = event.__task; if (event.kind === TaskEventKind.Start) { - this._proxy.$onDidStartTask(TaskExecutionDTO.from(Task.getTaskExecution(task))); + this._proxy.$onDidStartTask(TaskExecutionDTO.from(task.getTaskExecution())); } else if (event.kind === TaskEventKind.ProcessStarted) { - this._proxy.$onDidStartTaskProcess(TaskProcessStartedDTO.from(Task.getTaskExecution(task), event.processId)); + this._proxy.$onDidStartTaskProcess(TaskProcessStartedDTO.from(task.getTaskExecution(), event.processId)); } else if (event.kind === TaskEventKind.ProcessEnded) { - this._proxy.$onDidEndTaskProcess(TaskProcessEndedDTO.from(Task.getTaskExecution(task), event.exitCode)); + this._proxy.$onDidEndTaskProcess(TaskProcessEndedDTO.from(task.getTaskExecution(), event.exitCode)); } else if (event.kind === TaskEventKind.End) { - this._proxy.$OnDidEndTask(TaskExecutionDTO.from(Task.getTaskExecution(task))); + this._proxy.$OnDidEndTask(TaskExecutionDTO.from(task.getTaskExecution())); } }); } diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index 59af82f655b..886396ea8e6 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -724,7 +724,7 @@ export class DebugService implements IDebugService { taskStarted = true; }); const taskPromise = this.taskService.run(task); - if (task.isBackground) { + if (task.configurationProperties.isBackground) { return new Promise((c, e) => once(e => e.kind === TaskEventKind.Inactive && e.taskId === task._id, this.taskService.onDidStateChange)(() => { taskStarted = true; c(void 0); diff --git a/src/vs/workbench/parts/tasks/browser/quickOpen.ts b/src/vs/workbench/parts/tasks/browser/quickOpen.ts index 6985df72811..fb5f8c33e84 100644 --- a/src/vs/workbench/parts/tasks/browser/quickOpen.ts +++ b/src/vs/workbench/parts/tasks/browser/quickOpen.ts @@ -13,7 +13,7 @@ import * as QuickOpen from 'vs/base/parts/quickopen/common/quickOpen'; import * as Model from 'vs/base/parts/quickopen/browser/quickOpenModel'; import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen'; -import { Task, CustomTask, ContributedTask } from 'vs/workbench/parts/tasks/common/tasks'; +import { CustomTask, ContributedTask } from 'vs/workbench/parts/tasks/common/tasks'; import { ITaskService, ProblemMatcherRunOptions } from 'vs/workbench/parts/tasks/common/taskService'; import { ActionBarContributor, ContributableActionProvider } from 'vs/workbench/browser/actions'; import { CancellationToken } from 'vs/base/common/cancellation'; @@ -32,7 +32,7 @@ export class TaskEntry extends Model.QuickOpenEntry { if (!this.taskService.needsFolderQualification()) { return null; } - let workspaceFolder = Task.getWorkspaceFolder(this.task); + let workspaceFolder = this.task.getWorkspaceFolder(); if (!workspaceFolder) { return null; } @@ -99,7 +99,7 @@ export abstract class QuickOpenHandler extends Quickopen.QuickOpenHandler { let detected: ContributedTask[] = []; let taskMap: IStringDictionary = Object.create(null); tasks.forEach(task => { - let key = Task.getRecentlyUsedKey(task); + let key = task.getRecentlyUsedKey(); if (key) { taskMap[key] = task; } @@ -111,7 +111,7 @@ export abstract class QuickOpenHandler extends Quickopen.QuickOpenHandler { } }); for (let task of tasks) { - let key = Task.getRecentlyUsedKey(task); + let key = task.getRecentlyUsedKey(); if (!key || !recentlyUsedTasks.has(key)) { if (CustomTask.is(task)) { configured.push(task); diff --git a/src/vs/workbench/parts/tasks/common/tasks.ts b/src/vs/workbench/parts/tasks/common/tasks.ts index d6ea120bd74..ebc5c4b352e 100644 --- a/src/vs/workbench/parts/tasks/common/tasks.ts +++ b/src/vs/workbench/parts/tasks/common/tasks.ts @@ -332,16 +332,19 @@ export interface TaskSourceConfigElement { element: any; } -export interface WorkspaceTaskSource { - readonly kind: 'workspace'; +interface BaseTaskSource { + readonly kind; readonly label: string; +} + +export interface WorkspaceTaskSource extends BaseTaskSource { + readonly kind: 'workspace'; readonly config: TaskSourceConfigElement; readonly customizes?: KeyedTaskIdentifier; } -export interface ExtensionTaskSource { +export interface ExtensionTaskSource extends BaseTaskSource { readonly kind: 'extension'; - readonly label: string; readonly extension: string; readonly scope: TaskScope; readonly workspaceFolder: IWorkspaceFolder | undefined; @@ -352,9 +355,8 @@ export interface ExtensionTaskSourceTransfer { __definition: { type: string;[name: string]: any }; } -export interface InMemoryTaskSource { +export interface InMemoryTaskSource extends BaseTaskSource { readonly kind: 'inMemory'; - readonly label: string; } export type TaskSource = WorkspaceTaskSource | ExtensionTaskSource | InMemoryTaskSource; @@ -445,7 +447,7 @@ export namespace RunOptions { export const defaults: RunOptions = { reevaluateOnRerun: true, runOn: RunOnOptions.default }; } -export interface CommonTask { +export abstract class CommonTask { /** * The task's internal id @@ -457,12 +459,80 @@ export interface CommonTask { */ _label: string; - type: string; + type; runOptions: RunOptions; + + configurationProperties: ConfigurationProperties; + + _source: BaseTaskSource; + + protected constructor(id: string, label: string, type, runOptions: RunOptions, + configurationProperties: ConfigurationProperties, source: BaseTaskSource) { + this._id = id; + this._label = label; + if (type) { + this.type = type; + } + this.runOptions = runOptions; + this.configurationProperties = configurationProperties; + this._source = source; + } + + public getDefinition(useSource?: boolean): KeyedTaskIdentifier | undefined { + return undefined; + } + + public getMapKey(): string { + return this._id; + } + + public getRecentlyUsedKey(): string | undefined { + return undefined; + } + + public clone(): Task { + return Objects.assign({}, this); + } + + public getWorkspaceFolder(): IWorkspaceFolder | undefined { + return undefined; + } + + public getTelemetryKind(): string { + return 'unknown'; + } + + public matches(key: string | KeyedTaskIdentifier, compareId: boolean = false): boolean { + if (key === void 0) { + return false; + } + if (Types.isString(key)) { + return key === this._label || key === this.configurationProperties.identifier || (compareId && key === this._id); + } + let identifier = this.getDefinition(true); + return identifier !== void 0 && identifier._key === key._key; + } + + public getQualifiedLabel(): string { + let workspaceFolder = this.getWorkspaceFolder(); + if (workspaceFolder) { + return `${this._label} (${workspaceFolder.name})`; + } else { + return this._label; + } + } + + public getTaskExecution(): TaskExecution { + let result: TaskExecution = { + id: this._id, + task: this + }; + return result; + } } -export interface CustomTask extends CommonTask, ConfigurationProperties { +export class CustomTask extends CommonTask { type: '$customized'; // CUSTOMIZED_TASK_TYPE @@ -471,46 +541,84 @@ export interface CustomTask extends CommonTask, ConfigurationProperties { */ _source: WorkspaceTaskSource; - name: string; - - identifier: string; - hasDefinedMatchers: boolean; /** * The command configuration */ command: CommandConfiguration; -} -export namespace CustomTask { - export function is(value: any): value is CustomTask { - let candidate: CustomTask = value; - return candidate && candidate.type === CUSTOMIZED_TASK_TYPE; + public constructor(id: string, source: WorkspaceTaskSource, label: string, type, command: CommandConfiguration, + hasDefinedMatchers: boolean, runOptions: RunOptions, configurationProperties: ConfigurationProperties) { + super(id, label, undefined, runOptions, configurationProperties, source); + this._source = source; + this.hasDefinedMatchers = hasDefinedMatchers; + this.command = command; } - export function getDefinition(task: CustomTask): KeyedTaskIdentifier { - let type: string; - if (task.command !== void 0) { - type = task.command.runtime === RuntimeType.Shell ? 'shell' : 'process'; - } else { - type = '$composite'; - } - let result: KeyedTaskIdentifier = { - type, - _key: task._id, - id: task._id - }; - return result; - } - export function customizes(task: CustomTask): KeyedTaskIdentifier | undefined { - if (task._source && task._source.customizes) { - return task._source.customizes; + + public customizes(): KeyedTaskIdentifier | undefined { + if (this._source && this._source.customizes) { + return this._source.customizes; } return undefined; } + + public getDefinition(useSource: boolean = false): KeyedTaskIdentifier { + if (useSource && this._source.customizes !== void 0) { + return this._source.customizes; + } else { + let type: string; + if (this.command !== void 0) { + type = this.command.runtime === RuntimeType.Shell ? 'shell' : 'process'; + } else { + type = '$composite'; + } + let result: KeyedTaskIdentifier = { + type, + _key: this._id, + id: this._id + }; + return result; + } + } + + public static is(value: any): value is CustomTask { + return value instanceof CustomTask; + } + + public getMapKey(): string { + let workspaceFolder = this._source.config.workspaceFolder; + return workspaceFolder ? `${workspaceFolder.uri.toString()}|${this._id}` : this._id; + } + + public getRecentlyUsedKey(): string | undefined { + interface CustomKey { + type: string; + folder: string; + id: string; + } + let workspaceFolder = this._source.config.workspaceFolder; + if (!workspaceFolder) { + return undefined; + } + let key: CustomKey = { type: CUSTOMIZED_TASK_TYPE, folder: workspaceFolder.uri.toString(), id: this.configurationProperties.identifier! }; + return JSON.stringify(key); + } + + public getWorkspaceFolder(): IWorkspaceFolder | undefined { + return this._source.config.workspaceFolder; + } + + public getTelemetryKind(): string { + if (this._source.customizes) { + return 'workspace>extension'; + } else { + return 'workspace'; + } + } } -export interface ConfiguringTask extends CommonTask, ConfigurationProperties { +export class ConfiguringTask extends CommonTask { /** * Indicated the source of the task (e.g tasks.json or extension) @@ -518,16 +626,20 @@ export interface ConfiguringTask extends CommonTask, ConfigurationProperties { _source: WorkspaceTaskSource; configures: KeyedTaskIdentifier; -} -export namespace ConfiguringTask { - export function is(value: any): value is ConfiguringTask { - let candidate: ConfiguringTask = value; - return candidate && candidate.configures && Types.isString(candidate.configures.type) && value.command === void 0; + public constructor(id: string, source: WorkspaceTaskSource, label: string, type, + configures: KeyedTaskIdentifier, runOptions: RunOptions, configurationProperties: ConfigurationProperties) { + super(id, label, type, runOptions, configurationProperties, source); + this._source = source; + this.configures = configures; + } + + public static is(value: any): value is ConfiguringTask { + return value instanceof ConfiguringTask; } } -export interface ContributedTask extends CommonTask, ConfigurationProperties { +export class ContributedTask extends CommonTask { /** * Indicated the source of the task (e.g tasks.json or extension) @@ -542,16 +654,56 @@ export interface ContributedTask extends CommonTask, ConfigurationProperties { * The command configuration */ command: CommandConfiguration; -} -export namespace ContributedTask { - export function is(value: any): value is ContributedTask { - let candidate: ContributedTask = value; - return candidate && candidate.defines && Types.isString(candidate.defines.type) && candidate.command !== void 0; + public constructor(id: string, source: ExtensionTaskSource, label: string, type, defines: KeyedTaskIdentifier, + command: CommandConfiguration, hasDefinedMatchers: boolean, runOptions: RunOptions, + configurationProperties: ConfigurationProperties) { + super(id, label, type, runOptions, configurationProperties, source); + this.defines = defines; + this.hasDefinedMatchers = hasDefinedMatchers; + this.command = command; + } + + public getDefinition(): KeyedTaskIdentifier { + return this.defines; + } + + public static is(value: any): value is ContributedTask { + return value instanceof ContributedTask; + } + + public getMapKey(): string { + let workspaceFolder = this._source.workspaceFolder; + return workspaceFolder + ? `${this._source.scope.toString()}|${workspaceFolder.uri.toString()}|${this._id}` + : `${this._source.scope.toString()}|${this._id}`; + } + + public getRecentlyUsedKey(): string | undefined { + interface ContributedKey { + type: string; + scope: number; + folder?: string; + id: string; + } + + let key: ContributedKey = { type: 'contributed', scope: this._source.scope, id: this._id }; + if (this._source.scope === TaskScope.Folder && this._source.workspaceFolder) { + key.folder = this._source.workspaceFolder.uri.toString(); + } + return JSON.stringify(key); + } + + public getWorkspaceFolder(): IWorkspaceFolder | undefined { + return this._source.workspaceFolder; + } + + public getTelemetryKind(): string { + return 'extension'; } } -export interface InMemoryTask extends CommonTask, ConfigurationProperties { +export class InMemoryTask extends CommonTask { /** * Indicated the source of the task (e.g tasks.json or extension) */ @@ -559,139 +711,23 @@ export interface InMemoryTask extends CommonTask, ConfigurationProperties { type: 'inMemory'; - identifier: string; -} + public constructor(id: string, source: InMemoryTaskSource, label: string, type, + runOptions: RunOptions, configurationProperties: ConfigurationProperties) { + super(id, label, type, runOptions, configurationProperties, source); + this._source = source; + } -export namespace InMemoryTask { - export function is(value: any): value is InMemoryTask { - let candidate = value as InMemoryTask; - return candidate && candidate._source && candidate._source.kind === TaskSourceKind.InMemory; + public static is(value: any): value is InMemoryTask { + return value instanceof InMemoryTask; + } + + public getTelemetryKind(): string { + return 'composite'; } } export type Task = CustomTask | ContributedTask | InMemoryTask; -export namespace Task { - export function getRecentlyUsedKey(task: Task): string | undefined { - interface CustomKey { - type: string; - folder: string; - id: string; - } - interface ContributedKey { - type: string; - scope: number; - folder?: string; - id: string; - } - if (InMemoryTask.is(task)) { - return undefined; - } - if (CustomTask.is(task)) { - let workspaceFolder = task._source.config.workspaceFolder; - if (!workspaceFolder) { - return undefined; - } - let key: CustomKey = { type: CUSTOMIZED_TASK_TYPE, folder: workspaceFolder.uri.toString(), id: task.identifier }; - return JSON.stringify(key); - } - if (ContributedTask.is(task)) { - let key: ContributedKey = { type: 'contributed', scope: task._source.scope, id: task._id }; - if (task._source.scope === TaskScope.Folder && task._source.workspaceFolder) { - key.folder = task._source.workspaceFolder.uri.toString(); - } - return JSON.stringify(key); - } - return undefined; - } - - export function getMapKey(task: Task): string { - if (CustomTask.is(task)) { - let workspaceFolder = task._source.config.workspaceFolder; - return workspaceFolder ? `${workspaceFolder.uri.toString()}|${task._id}` : task._id; - } else if (ContributedTask.is(task)) { - let workspaceFolder = task._source.workspaceFolder; - return workspaceFolder - ? `${task._source.scope.toString()}|${workspaceFolder.uri.toString()}|${task._id}` - : `${task._source.scope.toString()}|${task._id}`; - } else { - return task._id; - } - } - - export function getWorkspaceFolder(task: Task): IWorkspaceFolder | undefined { - if (CustomTask.is(task)) { - return task._source.config.workspaceFolder; - } else if (ContributedTask.is(task)) { - return task._source.workspaceFolder; - } else { - return undefined; - } - } - - export function clone(task: Task): Task { - return Objects.assign({}, task); - } - - export function getTelemetryKind(task: Task): string { - if (ContributedTask.is(task)) { - return 'extension'; - } else if (CustomTask.is(task)) { - if (task._source.customizes) { - return 'workspace>extension'; - } else { - return 'workspace'; - } - } else if (InMemoryTask.is(task)) { - return 'composite'; - } else { - return 'unknown'; - } - } - - export function matches(task: Task, key: string | KeyedTaskIdentifier, compareId: boolean = false): boolean { - if (key === void 0) { - return false; - } - if (Types.isString(key)) { - return key === task._label || key === task.identifier || (compareId && key === task._id); - } - let identifier = Task.getTaskDefinition(task, true); - return identifier !== void 0 && identifier._key === key._key; - } - - export function getQualifiedLabel(task: Task): string { - let workspaceFolder = getWorkspaceFolder(task); - if (workspaceFolder) { - return `${task._label} (${workspaceFolder.name})`; - } else { - return task._label; - } - } - - export function getTaskDefinition(task: Task, useSource: boolean = false): KeyedTaskIdentifier | undefined { - if (ContributedTask.is(task)) { - return task.defines; - } else if (CustomTask.is(task)) { - if (useSource && task._source.customizes !== void 0) { - return task._source.customizes; - } else { - return CustomTask.getDefinition(task); - } - } else { - return undefined; - } - } - - export function getTaskExecution(task: Task): TaskExecution { - let result: TaskExecution = { - id: task._id, - task: task - }; - return result; - } -} - export interface TaskExecution { id: string; task: Task; @@ -734,8 +770,8 @@ export class TaskSorter { } public compare(a: Task, b: Task): number { - let aw = Task.getWorkspaceFolder(a); - let bw = Task.getWorkspaceFolder(b); + let aw = a.getWorkspaceFolder(); + let bw = b.getWorkspaceFolder(); if (aw && bw) { let ai = this._order.get(aw.uri.toString()); ai = ai === void 0 ? 0 : ai + 1; @@ -800,9 +836,9 @@ export namespace TaskEvent { let result = { kind: kind, taskId: task._id, - taskName: task.name, - runType: task.isBackground ? TaskRunType.Background : TaskRunType.SingleRun, - group: task.group, + taskName: task.configurationProperties.name, + runType: task.configurationProperties.isBackground ? TaskRunType.Background : TaskRunType.SingleRun, + group: task.configurationProperties.group, processId: undefined as number | undefined, exitCode: undefined as number | undefined, __task: task, 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 f905a6fd77e..96978b89523 100644 --- a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts +++ b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts @@ -281,7 +281,7 @@ class BuildStatusBarItem extends Themable implements IStatusbarItem { if (!event.__task) { return false; } - return event.__task.problemMatchers === void 0 || event.__task.problemMatchers.length === 0; + return event.__task.configurationProperties.problemMatchers === void 0 || event.__task.configurationProperties.problemMatchers.length === 0; } } @@ -720,7 +720,7 @@ class TaskService extends Disposable implements ITaskService { return undefined; } for (let task of values) { - if (Task.matches(task, key, compareId)) { + if (task.matches(key, compareId)) { return task; } } @@ -748,7 +748,7 @@ class TaskService extends Disposable implements ITaskService { if (task.type === filter.type) { result.push(task); } else { - let customizes = CustomTask.customizes(task); + let customizes = task.customizes(); if (customizes && customizes.type === filter.type) { result.push(task); } @@ -851,7 +851,7 @@ class TaskService extends Disposable implements ITaskService { public run(task: Task, options?: ProblemMatcherRunOptions): Promise { return this.getGroupedTasks().then((grouped) => { if (!task) { - throw new TaskError(Severity.Info, nls.localize('TaskServer.noTask', 'Requested task {0} to execute not found.', task.name), TaskErrors.TaskNotFound); + throw new TaskError(Severity.Info, nls.localize('TaskServer.noTask', 'Requested task {0} to execute not found.', task.configurationProperties.name), TaskErrors.TaskNotFound); } else { let resolver = this.createResolver(grouped); if (options && options.attachProblemMatcher && this.shouldAttachProblemMatcher(task) && !InMemoryTask.is(task)) { @@ -875,14 +875,14 @@ class TaskService extends Disposable implements ITaskService { if (!this.canCustomize(task)) { return false; } - if (task.group !== void 0 && task.group !== TaskGroup.Build) { + if (task.configurationProperties.group !== void 0 && task.configurationProperties.group !== TaskGroup.Build) { return false; } - if (task.problemMatchers !== void 0 && task.problemMatchers.length > 0) { + if (task.configurationProperties.problemMatchers !== void 0 && task.configurationProperties.problemMatchers.length > 0) { return false; } if (ContributedTask.is(task)) { - return !task.hasDefinedMatchers && task.problemMatchers.length === 0; + return !task.hasDefinedMatchers && task.configurationProperties.problemMatchers.length === 0; } if (CustomTask.is(task)) { let configProperties: TaskConfig.ConfigurationProperties = task._source.config.element; @@ -932,14 +932,14 @@ class TaskService extends Disposable implements ITaskService { this.customize(task, { problemMatcher: [] }, true); return task; } else if (selected.matcher) { - let newTask = Task.clone(task); + let newTask = task.clone(); let matcherReference = `$${selected.matcher.name}`; let properties: CustomizationProperties = { problemMatcher: [matcherReference] }; - newTask.problemMatchers = [matcherReference]; + newTask.configurationProperties.problemMatchers = [matcherReference]; let matcher = ProblemMatcherRegistry.get(selected.matcher.name); if (matcher && matcher.watching !== void 0) { properties.isBackground = true; - newTask.isBackground = true; + newTask.configurationProperties.isBackground = true; } this.customize(task, properties, true); return newTask; @@ -959,7 +959,7 @@ class TaskService extends Disposable implements ITaskService { let result: Task[] = []; groups.forEach((tasks) => { for (let task of tasks) { - if (task.group === group) { + if (task.configurationProperties.group === group) { result.push(task); } } @@ -980,13 +980,13 @@ class TaskService extends Disposable implements ITaskService { return true; } if (ContributedTask.is(task)) { - return !!Task.getWorkspaceFolder(task); + return !!task.getWorkspaceFolder(); } return false; } public customize(task: ContributedTask | CustomTask, properties?: CustomizationProperties, openConfig?: boolean): Promise { - let workspaceFolder = Task.getWorkspaceFolder(task); + let workspaceFolder = task.getWorkspaceFolder(); if (!workspaceFolder) { return Promise.resolve(undefined); } @@ -1009,8 +1009,8 @@ class TaskService extends Disposable implements ITaskService { let identifier: TaskConfig.TaskIdentifier = Objects.assign(Object.create(null), task.defines); delete identifier['_key']; Object.keys(identifier).forEach(key => toCustomize[key] = identifier[key]); - if (task.problemMatchers && task.problemMatchers.length > 0 && Types.isStringArray(task.problemMatchers)) { - toCustomize.problemMatcher = task.problemMatchers; + if (task.configurationProperties.problemMatchers && task.configurationProperties.problemMatchers.length > 0 && Types.isStringArray(task.configurationProperties.problemMatchers)) { + toCustomize.problemMatcher = task.configurationProperties.problemMatchers; } } if (!toCustomize) { @@ -1024,7 +1024,7 @@ class TaskService extends Disposable implements ITaskService { } } } else { - if (toCustomize.problemMatcher === void 0 && task.problemMatchers === void 0 || task.problemMatchers.length === 0) { + if (toCustomize.problemMatcher === void 0 && task.configurationProperties.problemMatchers === void 0 || task.configurationProperties.problemMatchers.length === 0) { toCustomize.problemMatcher = []; } } @@ -1106,7 +1106,7 @@ class TaskService extends Disposable implements ITaskService { public openConfig(task: CustomTask | undefined): Promise { let resource: URI; if (task) { - resource = Task.getWorkspaceFolder(task).toResource(task._source.config.file); + resource = task.getWorkspaceFolder().toResource(task._source.config.file); } else { resource = (this._workspaceFolders && (this._workspaceFolders.length > 0)) ? this._workspaceFolders[0].toResource('.vscode/tasks.json') : undefined; } @@ -1141,8 +1141,8 @@ class TaskService extends Disposable implements ITaskService { for (let task of tasks) { data.id.set(task._id, task); data.label.set(task._label, task); - data.identifier.set(task.identifier, task); - if (group && task.group === group) { + data.identifier.set(task.configurationProperties.identifier, task); + if (group && task.configurationProperties.group === group) { if (task._source.kind === TaskSourceKind.Workspace) { workspaceTasks.push(task); } else { @@ -1176,16 +1176,18 @@ class TaskService extends Disposable implements ITaskService { return { task: extensionTasks[0], resolver }; } else { let id: string = UUID.generateUuid(); - let task: InMemoryTask = { - _id: id, - _source: { kind: TaskSourceKind.InMemory, label: 'inMemory' }, - _label: id, - type: 'inMemory', - name: id, - identifier: id, - dependsOn: extensionTasks.map((task) => { return { workspaceFolder: Task.getWorkspaceFolder(task), task: task._id }; }), - runOptions: { reevaluateOnRerun: true }, - }; + let task: InMemoryTask = new InMemoryTask( + id, + { kind: TaskSourceKind.InMemory, label: 'inMemory' }, + id, + 'inMemory', + { reevaluateOnRerun: true }, + { + identifier: id, + dependsOn: extensionTasks.map((task) => { return { workspaceFolder: task.getWorkspaceFolder(), task: task._id }; }), + name: id, + } + ); return { task, resolver }; } } @@ -1206,8 +1208,8 @@ class TaskService extends Disposable implements ITaskService { } for (let task of tasks) { data.label.set(task._label, task); - data.identifier.set(task.identifier, task); - let keyedIdentifier = Task.getTaskDefinition(task, true); + data.identifier.set(task.configurationProperties.identifier, task); + let keyedIdentifier = task.getDefinition(true); if (keyedIdentifier !== void 0) { data.taskIdentifier.set(keyedIdentifier._key, task); } @@ -1239,7 +1241,7 @@ class TaskService extends Disposable implements ITaskService { } private handleExecuteResult(executeResult: ITaskExecuteResult): Promise { - let key = Task.getRecentlyUsedKey(executeResult.task); + let key = executeResult.task.getRecentlyUsedKey(); if (key) { this.getRecentlyUsedTasks().set(key, key, Touch.AsOld); } @@ -1248,9 +1250,9 @@ class TaskService extends Disposable implements ITaskService { if (active.same) { let message; if (active.background) { - message = nls.localize('TaskSystem.activeSame.background', 'The task \'{0}\' is already active and in background mode.', Task.getQualifiedLabel(executeResult.task)); + message = nls.localize('TaskSystem.activeSame.background', 'The task \'{0}\' is already active and in background mode.', executeResult.task.getQualifiedLabel()); } else { - message = nls.localize('TaskSystem.activeSame.noBackground', 'The task \'{0}\' is already active.', Task.getQualifiedLabel(executeResult.task)); + message = nls.localize('TaskSystem.activeSame.noBackground', 'The task \'{0}\' is already active.', executeResult.task.getQualifiedLabel()); } this.notificationService.prompt(Severity.Info, message, [{ @@ -1280,7 +1282,7 @@ class TaskService extends Disposable implements ITaskService { // eat the error, it has already been surfaced to the user and we don't care about it here }); } else { - this.notificationService.warn(nls.localize('TaskSystem.restartFailed', 'Failed to terminate and restart task {0}', Types.isString(task) ? task : task.name)); + this.notificationService.warn(nls.localize('TaskSystem.restartFailed', 'Failed to terminate and restart task {0}', Types.isString(task) ? task : task.configurationProperties.name)); } return response; }); @@ -1379,7 +1381,7 @@ class TaskService extends Disposable implements ITaskService { let contributedTasks: TaskMap = new TaskMap(); for (let set of contributedTaskSets) { for (let task of set.tasks) { - let workspaceFolder = Task.getWorkspaceFolder(task); + let workspaceFolder = task.getWorkspaceFolder(); if (workspaceFolder) { contributedTasks.add(workspaceFolder, task); } @@ -1466,7 +1468,7 @@ class TaskService extends Disposable implements ITaskService { let result: TaskMap = new TaskMap(); for (let set of contributedTaskSets) { for (let task of set.tasks) { - result.add(Task.getWorkspaceFolder(task), task); + result.add(task.getWorkspaceFolder(), task); } } return result; @@ -1491,7 +1493,7 @@ class TaskService extends Disposable implements ITaskService { if (commandName === 'gulp' || commandName === 'grunt' || commandName === 'jake') { let identifier = NKeyedTaskIdentifier.create({ type: commandName, - task: task.name + task: task.configurationProperties.name }); getResult()[identifier._key] = task; } @@ -1835,7 +1837,7 @@ class TaskService extends Disposable implements ITaskService { const TaskQuickPickEntry = (task: Task): TaskQuickPickEntry => { let description: string; if (this.needsFolderQualification()) { - let workspaceFolder = Task.getWorkspaceFolder(task); + let workspaceFolder = task.getWorkspaceFolder(); if (workspaceFolder) { description = workspaceFolder.name; } @@ -1868,7 +1870,7 @@ class TaskService extends Disposable implements ITaskService { let detected: Task[] = []; let taskMap: IStringDictionary = Object.create(null); tasks.forEach(task => { - let key = Task.getRecentlyUsedKey(task); + let key = task.getRecentlyUsedKey(); if (key) { taskMap[key] = task; } @@ -1880,7 +1882,7 @@ class TaskService extends Disposable implements ITaskService { } }); for (let task of tasks) { - let key = Task.getRecentlyUsedKey(task); + let key = task.getRecentlyUsedKey(); if (!key || !recentlyUsedTasks.has(key)) { if (task._source.kind === TaskSourceKind.Workspace) { configured.push(task); @@ -2029,9 +2031,9 @@ class TaskService extends Disposable implements ITaskService { let defaults: Task[] = []; let users: Task[] = []; for (let task of tasks) { - if (task.groupType === GroupType.default) { + if (task.configurationProperties.groupType === GroupType.default) { defaults.push(task); - } else if (task.groupType === GroupType.user) { + } else if (task.configurationProperties.groupType === GroupType.user) { users.push(task); } else { none.push(task); @@ -2162,7 +2164,7 @@ class TaskService extends Disposable implements ITaskService { promise = this.getActiveTasks(); promise.then((tasks) => { for (let task of tasks) { - if (Task.matches(task, identifier)) { + if (task.matches(identifier)) { this.terminate(task); return; } @@ -2218,7 +2220,7 @@ class TaskService extends Disposable implements ITaskService { promise = this.getActiveTasks(); promise.then((tasks) => { for (let task of tasks) { - if (Task.matches(task, identifier)) { + if (task.matches(identifier)) { this.restart(task); return; } @@ -2402,14 +2404,14 @@ class TaskService extends Disposable implements ITaskService { let selectedTask: Task; let selectedEntry: TaskQuickPickEntry; for (let task of tasks) { - if (task.group === TaskGroup.Build && task.groupType === GroupType.default) { + if (task.configurationProperties.group === TaskGroup.Build && task.configurationProperties.groupType === GroupType.default) { selectedTask = task; break; } } if (selectedTask) { selectedEntry = { - label: nls.localize('TaskService.defaultBuildTaskExists', '{0} is already marked as the default build task', Task.getQualifiedLabel(selectedTask)), + label: nls.localize('TaskService.defaultBuildTaskExists', '{0} is already marked as the default build task', selectedTask.getQualifiedLabel()), task: selectedTask }; } @@ -2452,14 +2454,14 @@ class TaskService extends Disposable implements ITaskService { let selectedEntry: TaskQuickPickEntry; for (let task of tasks) { - if (task.group === TaskGroup.Test && task.groupType === GroupType.default) { + if (task.configurationProperties.group === TaskGroup.Test && task.configurationProperties.groupType === GroupType.default) { selectedTask = task; break; } } if (selectedTask) { selectedEntry = { - label: nls.localize('TaskService.defaultTestTaskExists', '{0} is already marked as the default test task.', Task.getQualifiedLabel(selectedTask)), + label: nls.localize('TaskService.defaultTestTaskExists', '{0} is already marked as the default test task.', selectedTask.getQualifiedLabel()), task: selectedTask }; } diff --git a/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.ts b/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.ts index 2dee666eedb..468d130372c 100644 --- a/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.ts +++ b/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.ts @@ -183,7 +183,7 @@ export class TerminalTaskSystem implements ITaskSystem { public run(task: Task, resolver: ITaskResolver, trigger: string = Triggers.command): ITaskExecuteResult { this.currentTask = new VerifiedTask(task, resolver, trigger); - let terminalData = this.activeTasks[Task.getMapKey(task)]; + let terminalData = this.activeTasks[task.getMapKey()]; if (terminalData && terminalData.promise) { let reveal = RevealKind.Always; let focus = false; @@ -196,7 +196,7 @@ export class TerminalTaskSystem implements ITaskSystem { this.terminalService.showPanel(focus); } this.lastTask = this.currentTask; - return { kind: TaskExecuteKind.Active, task, active: { same: true, background: task.isBackground }, promise: terminalData.promise }; + return { kind: TaskExecuteKind.Active, task, active: { same: true, background: task.configurationProperties.isBackground }, promise: terminalData.promise }; } try { @@ -234,7 +234,7 @@ export class TerminalTaskSystem implements ITaskSystem { } public revealTask(task: Task): boolean { - let terminalData = this.activeTasks[Task.getMapKey(task)]; + let terminalData = this.activeTasks[task.getMapKey()]; if (!terminalData) { return false; } @@ -254,7 +254,7 @@ export class TerminalTaskSystem implements ITaskSystem { } public canAutoTerminate(): boolean { - return Object.keys(this.activeTasks).every(key => !this.activeTasks[key].task.promptOnClose); + return Object.keys(this.activeTasks).every(key => !this.activeTasks[key].task.configurationProperties.promptOnClose); } public getActiveTasks(): Task[] { @@ -262,7 +262,7 @@ export class TerminalTaskSystem implements ITaskSystem { } public terminate(task: Task): Promise { - let activeTerminal = this.activeTasks[Task.getMapKey(task)]; + let activeTerminal = this.activeTasks[task.getMapKey()]; if (!activeTerminal) { return Promise.resolve({ success: false, task: undefined }); } @@ -307,11 +307,11 @@ export class TerminalTaskSystem implements ITaskSystem { private executeTask(task: Task, resolver: ITaskResolver, trigger: string): Promise { let promises: Promise[] = []; - if (task.dependsOn) { - task.dependsOn.forEach((dependency) => { + if (task.configurationProperties.dependsOn) { + task.configurationProperties.dependsOn.forEach((dependency) => { let task = resolver.resolve(dependency.workspaceFolder, dependency.task); if (task) { - let key = Task.getMapKey(task); + let key = task.getMapKey(); let promise = this.activeTasks[key] ? this.activeTasks[key].promise : undefined; if (!promise) { promise = this.executeTask(task, resolver, trigger); @@ -426,7 +426,7 @@ export class TerminalTaskSystem implements ITaskSystem { } private executeCommand(task: CustomTask | ContributedTask, trigger: string): Promise { - this.currentTask.workspaceFolder = Task.getWorkspaceFolder(task); + this.currentTask.workspaceFolder = task.getWorkspaceFolder(); if (this.currentTask.workspaceFolder) { this.currentTask.systemInfo = this.taskSystemInfoResolver(this.currentTask.workspaceFolder); } @@ -478,9 +478,9 @@ export class TerminalTaskSystem implements ITaskSystem { let executedCommand: string | undefined = undefined; let error: TaskError | undefined = undefined; let promise: Promise | undefined = undefined; - if (task.isBackground) { + if (task.configurationProperties.isBackground) { promise = new Promise((resolve, reject) => { - const problemMatchers = this.resolveMatchers(resolver, task.problemMatchers); + const problemMatchers = this.resolveMatchers(resolver, task.configurationProperties.problemMatchers); let watchingProblemMatcher = new WatchingProblemCollector(problemMatchers, this.markerService, this.modelService); let toDispose: IDisposable[] = []; let eventCounter: number = 0; @@ -530,7 +530,7 @@ export class TerminalTaskSystem implements ITaskSystem { const onExit = terminal.onExit((exitCode) => { onData.dispose(); onExit.dispose(); - let key = Task.getMapKey(task); + let key = task.getMapKey(); delete this.activeTasks[key]; this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.Changed)); switch (task.command.presentation.panel) { @@ -583,7 +583,7 @@ export class TerminalTaskSystem implements ITaskSystem { }); this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.Start, task)); this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.Active, task)); - let problemMatchers = this.resolveMatchers(resolver, task.problemMatchers); + let problemMatchers = this.resolveMatchers(resolver, task.configurationProperties.problemMatchers); let startStopProblemMatcher = new StartStopProblemCollector(problemMatchers, this.markerService, this.modelService); const registeredLinkMatchers = this.registerLinkMatchers(terminal, problemMatchers); const onData = terminal.onLineData((line) => { @@ -592,7 +592,7 @@ export class TerminalTaskSystem implements ITaskSystem { const onExit = terminal.onExit((exitCode) => { onData.dispose(); onExit.dispose(); - let key = Task.getMapKey(task); + let key = task.getMapKey(); delete this.activeTasks[key]; this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.Changed)); switch (task.command.presentation.panel) { @@ -632,14 +632,14 @@ export class TerminalTaskSystem implements ITaskSystem { this.terminalService.setActiveInstance(terminal); this.terminalService.showPanel(task.command.presentation.focus); } - this.activeTasks[Task.getMapKey(task)] = { terminal, task, promise }; + this.activeTasks[task.getMapKey()] = { terminal, task, promise }; this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.Changed)); return promise.then((summary) => { try { let telemetryEvent: TelemetryEvent = { trigger: trigger, runner: 'terminal', - taskKind: Task.getTelemetryKind(task), + taskKind: task.getTelemetryKind(), command: this.getSanitizedCommand(executedCommand), success: true, exitCode: summary.exitCode @@ -660,7 +660,7 @@ export class TerminalTaskSystem implements ITaskSystem { let telemetryEvent: TelemetryEvent = { trigger: trigger, runner: 'terminal', - taskKind: Task.getTelemetryKind(task), + taskKind: task.getTelemetryKind(), command: this.getSanitizedCommand(executedCommand), success: false }; @@ -682,7 +682,7 @@ export class TerminalTaskSystem implements ITaskSystem { let shellLaunchConfig: IShellLaunchConfig | undefined = undefined; let isShellCommand = task.command.runtime === RuntimeType.Shell; let needsFolderQualification = this.currentTask.workspaceFolder && this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE; - let terminalName = nls.localize('TerminalTaskSystem.terminalName', 'Task - {0}', needsFolderQualification ? Task.getQualifiedLabel(task) : task.name); + let terminalName = nls.localize('TerminalTaskSystem.terminalName', 'Task - {0}', needsFolderQualification ? task.getQualifiedLabel() : task.configurationProperties.name); let originalCommand = task.command.name; if (isShellCommand) { shellLaunchConfig = { name: terminalName, executable: null, args: null, waitOnExit }; @@ -806,7 +806,7 @@ export class TerminalTaskSystem implements ITaskSystem { p = path; } if (!p.isAbsolute(cwd)) { - let workspaceFolder = Task.getWorkspaceFolder(task); + let workspaceFolder = task.getWorkspaceFolder(); if (workspaceFolder.uri.scheme === 'file') { cwd = p.join(workspaceFolder.uri.fsPath, cwd); } @@ -827,7 +827,7 @@ export class TerminalTaskSystem implements ITaskSystem { let { command, args } = this.resolveCommandAndArgs(resolver, task.command); let commandExecutable = CommandString.value(command); - if (task.command.presentation.reveal !== RevealKind.Never || !task.isBackground) { + if (task.command.presentation.reveal !== RevealKind.Never || !task.configurationProperties.isBackground) { if (task.command.presentation.panel === PanelKind.New) { waitOnExit = nls.localize('closeTerminal', 'Press any key to close the terminal.'); } else if (task.command.presentation.showReuseMessage) { @@ -843,7 +843,7 @@ export class TerminalTaskSystem implements ITaskSystem { let prefersSameTerminal = task.command.presentation.panel === PanelKind.Dedicated; let allowsSharedTerminal = task.command.presentation.panel === PanelKind.Shared; - let taskKey = Task.getMapKey(task); + let taskKey = task.getMapKey(); let terminalToReuse: TerminalData; if (prefersSameTerminal) { let terminalId = this.sameTaskTerminals[taskKey]; @@ -877,7 +877,7 @@ export class TerminalTaskSystem implements ITaskSystem { // This can happen if the terminal wasn't shutdown with an "immediate" flag and is expected. // For correct terminal re-use, the task needs to be deleted immediately. // Note that this shouldn't be a problem anymore since user initiated terminal kills are now immediate. - delete this.activeTasks[Task.getMapKey(task)]; + delete this.activeTasks[task.getMapKey()]; } }); this.terminals[terminalKey] = { terminal: result, lastTask: taskKey }; @@ -997,7 +997,7 @@ export class TerminalTaskSystem implements ITaskSystem { if (task.command) { this.collectCommandVariables(variables, task.command, task); } - this.collectMatcherVariables(variables, task.problemMatchers); + this.collectMatcherVariables(variables, task.configurationProperties.problemMatchers); } private collectCommandVariables(variables: Set, command: CommandConfiguration, task: CustomTask | ContributedTask): void { diff --git a/src/vs/workbench/parts/tasks/node/processTaskSystem.ts b/src/vs/workbench/parts/tasks/node/processTaskSystem.ts index d625df1615c..acb29cb1c0e 100644 --- a/src/vs/workbench/parts/tasks/node/processTaskSystem.ts +++ b/src/vs/workbench/parts/tasks/node/processTaskSystem.ts @@ -92,7 +92,7 @@ export class ProcessTaskSystem implements ITaskSystem { public run(task: Task): ITaskExecuteResult { if (this.activeTask) { - return { kind: TaskExecuteKind.Active, task, active: { same: this.activeTask._id === task._id, background: this.activeTask.isBackground }, promise: this.activeTaskPromise }; + return { kind: TaskExecuteKind.Active, task, active: { same: this.activeTask._id === task._id, background: this.activeTask.configurationProperties.isBackground }, promise: this.activeTaskPromise }; } return this.executeTask(task); } @@ -109,7 +109,7 @@ export class ProcessTaskSystem implements ITaskSystem { public canAutoTerminate(): boolean { if (this.childProcess) { if (this.activeTask) { - return !this.activeTask.promptOnClose; + return !this.activeTask.configurationProperties.promptOnClose; } return false; } @@ -117,7 +117,7 @@ export class ProcessTaskSystem implements ITaskSystem { } public terminate(task: Task): Promise { - if (!this.activeTask || Task.getMapKey(this.activeTask) !== Task.getMapKey(task)) { + if (!this.activeTask || this.activeTask.getMapKey() !== task.getMapKey()) { return Promise.resolve({ success: false, task: undefined }); } return this.terminateAll().then(values => values[0]); @@ -142,7 +142,7 @@ export class ProcessTaskSystem implements ITaskSystem { let telemetryEvent: TelemetryEvent = { trigger: trigger, runner: 'output', - taskKind: Task.getTelemetryKind(task), + taskKind: task.getTelemetryKind(), command: 'other', success: true }; @@ -225,7 +225,7 @@ export class ProcessTaskSystem implements ITaskSystem { telemetryEvent.command = this.childProcess.getSanitizedCommand(); // we have no problem matchers defined. So show the output log let reveal = task.command.presentation.reveal; - if (reveal === RevealKind.Always || (reveal === RevealKind.Silent && task.problemMatchers.length === 0)) { + if (reveal === RevealKind.Always || (reveal === RevealKind.Silent && task.configurationProperties.problemMatchers.length === 0)) { this.showOutput(); } @@ -233,8 +233,8 @@ export class ProcessTaskSystem implements ITaskSystem { let prompt: string = Platform.isWindows ? '>' : '$'; this.log(`running command${prompt} ${command} ${args.join(' ')}`); } - if (task.isBackground) { - let watchingProblemMatcher = new WatchingProblemCollector(this.resolveMatchers(task, task.problemMatchers), this.markerService, this.modelService); + if (task.configurationProperties.isBackground) { + let watchingProblemMatcher = new WatchingProblemCollector(this.resolveMatchers(task, task.configurationProperties.problemMatchers), this.markerService, this.modelService); let toDispose: IDisposable[] = []; let eventCounter: number = 0; toDispose.push(watchingProblemMatcher.onDidStateChange((event) => { @@ -311,7 +311,7 @@ export class ProcessTaskSystem implements ITaskSystem { } else { this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.Start, task)); this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.Active, task)); - let startStopProblemMatcher = new StartStopProblemCollector(this.resolveMatchers(task, task.problemMatchers), this.markerService, this.modelService); + let startStopProblemMatcher = new StartStopProblemCollector(this.resolveMatchers(task, task.configurationProperties.problemMatchers), this.markerService, this.modelService); this.activeTask = task; const inactiveEvent = TaskEvent.create(TaskEventKind.Inactive, task); let processStartedSignaled: boolean = false; @@ -390,7 +390,7 @@ export class ProcessTaskSystem implements ITaskSystem { private checkTerminated(task: Task, data: SuccessData | ErrorData): boolean { if (data.terminated) { - this.log(nls.localize('TaskRunnerSystem.cancelRequested', '\nThe task \'{0}\' was terminated per user request.', task.name)); + this.log(nls.localize('TaskRunnerSystem.cancelRequested', '\nThe task \'{0}\' was terminated per user request.', task.configurationProperties.name)); return true; } return false; @@ -448,7 +448,7 @@ export class ProcessTaskSystem implements ITaskSystem { } private resolveVariable(task: CustomTask, value: string): string { - return this.configurationResolverService.resolve(Task.getWorkspaceFolder(task), value); + return this.configurationResolverService.resolve(task.getWorkspaceFolder(), value); } public log(value: string): void { diff --git a/src/vs/workbench/parts/tasks/node/taskConfiguration.ts b/src/vs/workbench/parts/tasks/node/taskConfiguration.ts index b6993b9c75a..42b1efaa571 100644 --- a/src/vs/workbench/parts/tasks/node/taskConfiguration.ts +++ b/src/vs/workbench/parts/tasks/node/taskConfiguration.ts @@ -1320,19 +1320,20 @@ namespace ConfiguringTask { index, element: external }; - let result: Tasks.ConfiguringTask = { - type: type, - configures: taskIdentifier, - _id: `${typeDeclaration.extensionId}.${taskIdentifier._key}`, - _source: Objects.assign({} as Tasks.WorkspaceTaskSource, source, { config: configElement }), - _label: undefined, - runOptions: RunOptions.fromConfiguration(external.runOptions) - }; + let result: Tasks.ConfiguringTask = new Tasks.ConfiguringTask( + `${typeDeclaration.extensionId}.${taskIdentifier._key}`, + Objects.assign({} as Tasks.WorkspaceTaskSource, source, { config: configElement }), + undefined, + type, + taskIdentifier, + RunOptions.fromConfiguration(external.runOptions), + {} + ); let configuration = ConfigurationProperties.from(external, context, true); if (configuration) { - result = Objects.assign(result, configuration); - if (result.name) { - result._label = result.name; + result.configurationProperties = Objects.assign(result, configuration); + if (result.configurationProperties.name) { + result._label = result.configurationProperties.name; } else { let label = result.configures.type; if (typeDeclaration.required && typeDeclaration.required.length > 0) { @@ -1346,8 +1347,8 @@ namespace ConfiguringTask { } result._label = label; } - if (!result.identifier) { - result.identifier = taskIdentifier._key; + if (!result.configurationProperties.identifier) { + result.configurationProperties.identifier = taskIdentifier._key; } } return result; @@ -1377,32 +1378,34 @@ namespace CustomTask { return undefined; } - let result: Tasks.CustomTask = { - type: Tasks.CUSTOMIZED_TASK_TYPE, - _id: context.uuidMap.getUUID(taskName), - _source: Objects.assign({} as Tasks.WorkspaceTaskSource, source, { config: { index, element: external, file: '.vscode\\tasks.json', workspaceFolder: context.workspaceFolder } }), - _label: taskName, - name: taskName, - identifier: taskName, - hasDefinedMatchers: false, - command: undefined, - runOptions: RunOptions.fromConfiguration(external.runOptions) - }; + let result: Tasks.CustomTask = new Tasks.CustomTask( + context.uuidMap.getUUID(taskName), + Objects.assign({} as Tasks.WorkspaceTaskSource, source, { config: { index, element: external, file: '.vscode\\tasks.json', workspaceFolder: context.workspaceFolder } }), + taskName, + Tasks.CUSTOMIZED_TASK_TYPE, + undefined, + false, + RunOptions.fromConfiguration(external.runOptions), + { + name: taskName, + identifier: taskName, + } + ); let configuration = ConfigurationProperties.from(external, context, false); if (configuration) { - result = Objects.assign(result, configuration); + result.configurationProperties = Objects.assign(result, configuration); } let supportLegacy: boolean = true; //context.schemaVersion === Tasks.JsonSchemaVersion.V2_0_0; if (supportLegacy) { let legacy: LegacyTaskProperties = external as LegacyTaskProperties; - if (result.isBackground === void 0 && legacy.isWatching !== void 0) { - result.isBackground = !!legacy.isWatching; + if (result.configurationProperties.isBackground === void 0 && legacy.isWatching !== void 0) { + result.configurationProperties.isBackground = !!legacy.isWatching; } - if (result.group === void 0) { + if (result.configurationProperties.group === void 0) { if (legacy.isBuildCommand === true) { - result.group = Tasks.TaskGroup.Build; + result.configurationProperties.group = Tasks.TaskGroup.Build; } else if (legacy.isTestCommand === true) { - result.group = Tasks.TaskGroup.Test; + result.configurationProperties.group = Tasks.TaskGroup.Test; } } } @@ -1421,48 +1424,50 @@ namespace CustomTask { export function fillGlobals(task: Tasks.CustomTask, globals: Globals): void { // We only merge a command from a global definition if there is no dependsOn // or there is a dependsOn and a defined command. - if (CommandConfiguration.hasCommand(task.command) || task.dependsOn === void 0) { - task.command = CommandConfiguration.fillGlobals(task.command, globals.command, task.name); + if (CommandConfiguration.hasCommand(task.command) || task.configurationProperties.dependsOn === void 0) { + task.command = CommandConfiguration.fillGlobals(task.command, globals.command, task.configurationProperties.name); } - if (task.problemMatchers === void 0 && globals.problemMatcher !== void 0) { - task.problemMatchers = Objects.deepClone(globals.problemMatcher); + if (task.configurationProperties.problemMatchers === void 0 && globals.problemMatcher !== void 0) { + task.configurationProperties.problemMatchers = Objects.deepClone(globals.problemMatcher); task.hasDefinedMatchers = true; } // promptOnClose is inferred from isBackground if available - if (task.promptOnClose === void 0 && task.isBackground === void 0 && globals.promptOnClose !== void 0) { - task.promptOnClose = globals.promptOnClose; + if (task.configurationProperties.promptOnClose === void 0 && task.configurationProperties.isBackground === void 0 && globals.promptOnClose !== void 0) { + task.configurationProperties.promptOnClose = globals.promptOnClose; } } export function fillDefaults(task: Tasks.CustomTask, context: ParseContext): void { CommandConfiguration.fillDefaults(task.command, context); - if (task.promptOnClose === void 0) { - task.promptOnClose = task.isBackground !== void 0 ? !task.isBackground : true; + if (task.configurationProperties.promptOnClose === void 0) { + task.configurationProperties.promptOnClose = task.configurationProperties.isBackground !== void 0 ? !task.configurationProperties.isBackground : true; } - if (task.isBackground === void 0) { - task.isBackground = false; + if (task.configurationProperties.isBackground === void 0) { + task.configurationProperties.isBackground = false; } - if (task.problemMatchers === void 0) { - task.problemMatchers = EMPTY_ARRAY; + if (task.configurationProperties.problemMatchers === void 0) { + task.configurationProperties.problemMatchers = EMPTY_ARRAY; } - if (task.group !== void 0 && task.groupType === void 0) { - task.groupType = Tasks.GroupType.user; + if (task.configurationProperties.group !== void 0 && task.configurationProperties.groupType === void 0) { + task.configurationProperties.groupType = Tasks.GroupType.user; } } export function createCustomTask(contributedTask: Tasks.ContributedTask, configuredProps: Tasks.ConfigurationProperties & { _id: string, _source: Tasks.WorkspaceTaskSource }): Tasks.CustomTask { - let result: Tasks.CustomTask = { - _id: configuredProps._id, - _source: Objects.assign({}, configuredProps._source, { customizes: contributedTask.defines }), - _label: configuredProps.name || contributedTask._label, - type: Tasks.CUSTOMIZED_TASK_TYPE, - command: contributedTask.command, - name: configuredProps.name || contributedTask.name, - identifier: configuredProps.identifier || contributedTask.identifier, - hasDefinedMatchers: false, - runOptions: contributedTask.runOptions, - }; - let resultConfigProps: Tasks.ConfigurationProperties = result; + let result: Tasks.CustomTask = new Tasks.CustomTask( + configuredProps._id, + Objects.assign({}, configuredProps._source, { customizes: contributedTask.defines }), + configuredProps.name || contributedTask._label, + Tasks.CUSTOMIZED_TASK_TYPE, + contributedTask.command, + false, + contributedTask.runOptions, + { + name: configuredProps.name || contributedTask.configurationProperties.name, + identifier: configuredProps.identifier || contributedTask.configurationProperties.identifier, + } + ); + let resultConfigProps: Tasks.ConfigurationProperties = result.configurationProperties; assignProperty(resultConfigProps, configuredProps, 'group'); assignProperty(resultConfigProps, configuredProps, 'groupType'); @@ -1474,7 +1479,7 @@ namespace CustomTask { result.command.presentation, configuredProps.presentation); result.command.options = CommandOptions.assignProperties(result.command.options, configuredProps.options); - let contributedConfigProps: Tasks.ConfigurationProperties = contributedTask; + let contributedConfigProps: Tasks.ConfigurationProperties = contributedTask.configurationProperties; fillProperty(resultConfigProps, contributedConfigProps, 'group'); fillProperty(resultConfigProps, contributedConfigProps, 'groupType'); fillProperty(resultConfigProps, contributedConfigProps, 'isBackground'); @@ -1523,10 +1528,10 @@ namespace TaskParser { CustomTask.fillGlobals(customTask, globals); CustomTask.fillDefaults(customTask, context); if (schema2_0_0) { - if ((customTask.command === void 0 || customTask.command.name === void 0) && (customTask.dependsOn === void 0 || customTask.dependsOn.length === 0)) { + if ((customTask.command === void 0 || customTask.command.name === void 0) && (customTask.configurationProperties.dependsOn === void 0 || customTask.configurationProperties.dependsOn.length === 0)) { context.problemReporter.error(nls.localize( 'taskConfiguration.noCommandOrDependsOn', 'Error: the task \'{0}\' neither specifies a command nor a dependsOn property. The task will be ignored. Its definition is:\n{1}', - customTask.name, JSON.stringify(external, undefined, 4) + customTask.configurationProperties.name, JSON.stringify(external, undefined, 4) )); continue; } @@ -1534,21 +1539,21 @@ namespace TaskParser { if (customTask.command === void 0 || customTask.command.name === void 0) { context.problemReporter.warn(nls.localize( 'taskConfiguration.noCommand', 'Error: the task \'{0}\' doesn\'t define a command. The task will be ignored. Its definition is:\n{1}', - customTask.name, JSON.stringify(external, undefined, 4) + customTask.configurationProperties.name, JSON.stringify(external, undefined, 4) )); continue; } } - if (customTask.group === Tasks.TaskGroup.Build && defaultBuildTask.rank < 2) { + if (customTask.configurationProperties.group === Tasks.TaskGroup.Build && defaultBuildTask.rank < 2) { defaultBuildTask.task = customTask; defaultBuildTask.rank = 2; - } else if (customTask.group === Tasks.TaskGroup.Test && defaultTestTask.rank < 2) { + } else if (customTask.configurationProperties.group === Tasks.TaskGroup.Test && defaultTestTask.rank < 2) { defaultTestTask.task = customTask; defaultTestTask.rank = 2; - } else if (customTask.name === 'build' && defaultBuildTask.rank < 1) { + } else if (customTask.configurationProperties.name === 'build' && defaultBuildTask.rank < 1) { defaultBuildTask.task = customTask; defaultBuildTask.rank = 1; - } else if (customTask.name === 'test' && defaultTestTask.rank < 1) { + } else if (customTask.configurationProperties.name === 'test' && defaultTestTask.rank < 1) { defaultTestTask.task = customTask; defaultTestTask.rank = 1; } @@ -1562,11 +1567,11 @@ namespace TaskParser { } } if (defaultBuildTask.rank > -1 && defaultBuildTask.rank < 2) { - defaultBuildTask.task.group = Tasks.TaskGroup.Build; - defaultBuildTask.task.groupType = Tasks.GroupType.user; + defaultBuildTask.task.configurationProperties.group = Tasks.TaskGroup.Build; + defaultBuildTask.task.configurationProperties.groupType = Tasks.GroupType.user; } else if (defaultTestTask.rank > -1 && defaultTestTask.rank < 2) { - defaultTestTask.task.group = Tasks.TaskGroup.Test; - defaultTestTask.task.groupType = Tasks.GroupType.user; + defaultTestTask.task.configurationProperties.group = Tasks.TaskGroup.Test; + defaultTestTask.task.configurationProperties.groupType = Tasks.GroupType.user; } return result; @@ -1584,16 +1589,16 @@ namespace TaskParser { // Tasks are keyed by ID but we need to merge by name let map: IStringDictionary = Object.create(null); target.forEach((task) => { - map[task.name] = task; + map[task.configurationProperties.name] = task; }); source.forEach((task) => { - map[task.name] = task; + map[task.configurationProperties.name] = task; }); let newTarget: Tasks.CustomTask[] = []; target.forEach(task => { - newTarget.push(map[task.name]); - delete map[task.name]; + newTarget.push(map[task.configurationProperties.name]); + delete map[task.configurationProperties.name]; }); Object.keys(map).forEach(key => newTarget.push(map[key])); target = newTarget; @@ -1878,31 +1883,33 @@ class ConfigurationParser { let matchers: ProblemMatcher[] = ProblemMatcherConverter.from(fileConfig.problemMatcher, context); let isBackground = fileConfig.isBackground ? !!fileConfig.isBackground : fileConfig.isWatching ? !!fileConfig.isWatching : undefined; let name = Tasks.CommandString.value(globals.command.name); - let task: Tasks.CustomTask = { - _id: context.uuidMap.getUUID(name), - _source: Objects.assign({} as Tasks.WorkspaceTaskSource, source, { config: { index: -1, element: fileConfig, workspaceFolder: context.workspaceFolder } }), - _label: name, - type: Tasks.CUSTOMIZED_TASK_TYPE, - name: name, - identifier: name, - group: Tasks.TaskGroup.Build, - command: { + let task: Tasks.CustomTask = new Tasks.CustomTask( + context.uuidMap.getUUID(name), + Objects.assign({} as Tasks.WorkspaceTaskSource, source, { config: { index: -1, element: fileConfig, workspaceFolder: context.workspaceFolder } }), + name, + Tasks.CUSTOMIZED_TASK_TYPE, + { name: undefined, runtime: undefined, presentation: undefined, suppressTaskName: true }, - isBackground: isBackground, - problemMatchers: matchers, - hasDefinedMatchers: false, - runOptions: { reevaluateOnRerun: true }, - }; + false, + { reevaluateOnRerun: true }, + { + name: name, + identifier: name, + group: Tasks.TaskGroup.Build, + isBackground: isBackground, + problemMatchers: matchers, + } + ); let value = GroupKind.from(fileConfig.group); if (value) { - task.group = value[0]; - task.groupType = value[1]; + task.configurationProperties.group = value[0]; + task.configurationProperties.groupType = value[1]; } else if (fileConfig.group === 'none') { - task.group = undefined; + task.configurationProperties.group = undefined; } CustomTask.fillGlobals(task, globals); CustomTask.fillDefaults(task, context); 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 918665d5e38..986a57782a9 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 @@ -181,51 +181,53 @@ class CustomTaskBuilder { constructor(public parent: ConfiguationBuilder, name: string, command: string) { this.commandBuilder = new CommandConfigurationBuilder(this, command); - this.result = { - _id: name, - _source: { kind: Tasks.TaskSourceKind.Workspace, label: 'workspace', config: { workspaceFolder: workspaceFolder, element: undefined, index: -1, file: '.vscode/tasks.json' } }, - _label: name, - type: Tasks.CUSTOMIZED_TASK_TYPE, - identifier: name, - name: name, - command: this.commandBuilder.result, - isBackground: false, - promptOnClose: true, - problemMatchers: [], - hasDefinedMatchers: false, - runOptions: { reevaluateOnRerun: true }, - }; + this.result = new Tasks.CustomTask( + name, + { kind: Tasks.TaskSourceKind.Workspace, label: 'workspace', config: { workspaceFolder: workspaceFolder, element: undefined, index: -1, file: '.vscode/tasks.json' } }, + name, + Tasks.CUSTOMIZED_TASK_TYPE, + this.commandBuilder.result, + false, + { reevaluateOnRerun: true }, + { + identifier: name, + name: name, + isBackground: false, + promptOnClose: true, + problemMatchers: [], + } + ); } public identifier(value: string): CustomTaskBuilder { - this.result.identifier = value; + this.result.configurationProperties.identifier = value; return this; } public group(value: Tasks.TaskGroup): CustomTaskBuilder { - this.result.group = value; - this.result.groupType = Tasks.GroupType.user; + this.result.configurationProperties.group = value; + this.result.configurationProperties.groupType = Tasks.GroupType.user; return this; } public groupType(value: Tasks.GroupType): CustomTaskBuilder { - this.result.groupType = value; + this.result.configurationProperties.groupType = value; return this; } public isBackground(value: boolean): CustomTaskBuilder { - this.result.isBackground = value; + this.result.configurationProperties.isBackground = value; return this; } public promptOnClose(value: boolean): CustomTaskBuilder { - this.result.promptOnClose = value; + this.result.configurationProperties.promptOnClose = value; return this; } public problemMatcher(): ProblemMatcherBuilder { let builder = new ProblemMatcherBuilder(this); - this.result.problemMatchers.push(builder.result); + this.result.configurationProperties.problemMatchers.push(builder.result); return builder; } @@ -234,7 +236,7 @@ class CustomTaskBuilder { } public done(): void { - this.commandBuilder.done(this.result.name); + this.commandBuilder.done(this.result.configurationProperties.name); } } @@ -360,7 +362,7 @@ function testDefaultProblemMatcher(external: ExternalTaskRunnerConfiguration, re assert.strictEqual(result.custom.length, 1); let task = result.custom[0]; assert.ok(task); - assert.strictEqual(task.problemMatchers.length, resolved); + assert.strictEqual(task.configurationProperties.problemMatchers.length, resolved); } function testConfiguration(external: ExternalTaskRunnerConfiguration, builder: ConfiguationBuilder): void { @@ -403,12 +405,12 @@ class TaskGroupMap { let expectedTasks = expected._store[key]; assert.strictEqual(actualTasks.length, expectedTasks.length); if (actualTasks.length === 1) { - assert.strictEqual(actualTasks[0].name, expectedTasks[0].name); + assert.strictEqual(actualTasks[0].configurationProperties.name, expectedTasks[0].configurationProperties.name); return; } let expectedTaskMap: { [key: string]: boolean } = Object.create(null); - expectedTasks.forEach(task => expectedTaskMap[task.name] = true); - actualTasks.forEach(task => delete expectedTaskMap[task.name]); + expectedTasks.forEach(task => expectedTaskMap[task.configurationProperties.name] = true); + actualTasks.forEach(task => delete expectedTaskMap[task.configurationProperties.name]); assert.strictEqual(Object.keys(expectedTaskMap).length, 0); }); } @@ -428,20 +430,20 @@ function assertConfiguration(result: ParseResult, expected: Tasks.Task[]): void let actualId2Name: { [key: string]: string; } = Object.create(null); let actualTaskGroups = new TaskGroupMap(); actual.forEach(task => { - assert.ok(!actualTasks[task.name]); - actualTasks[task.name] = task; - actualId2Name[task._id] = task.name; - if (task.group) { - actualTaskGroups.add(task.group, task); + assert.ok(!actualTasks[task.configurationProperties.name]); + actualTasks[task.configurationProperties.name] = task; + actualId2Name[task._id] = task.configurationProperties.name; + if (task.configurationProperties.group) { + actualTaskGroups.add(task.configurationProperties.group, task); } }); let expectedTasks: { [key: string]: Tasks.Task; } = Object.create(null); let expectedTaskGroup = new TaskGroupMap(); expected.forEach(task => { - assert.ok(!expectedTasks[task.name]); - expectedTasks[task.name] = task; - if (task.group) { - expectedTaskGroup.add(task.group, task); + assert.ok(!expectedTasks[task.configurationProperties.name]); + expectedTasks[task.configurationProperties.name] = task; + if (task.configurationProperties.group) { + expectedTaskGroup.add(task.configurationProperties.group, task); } }); let actualKeys = Object.keys(actualTasks); @@ -457,19 +459,19 @@ 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'); + assert.strictEqual(actual.configurationProperties.name, expected.configurationProperties.name, 'name'); if (!Tasks.InMemoryTask.is(actual) && !Tasks.InMemoryTask.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'); - assert.strictEqual(actual.group, expected.group, 'group'); - assert.strictEqual(actual.groupType, expected.groupType, 'groupType'); - if (actual.problemMatchers && expected.problemMatchers) { - assert.strictEqual(actual.problemMatchers.length, expected.problemMatchers.length); - for (let i = 0; i < actual.problemMatchers.length; i++) { - assertProblemMatcher(actual.problemMatchers[i], expected.problemMatchers[i]); + assert.strictEqual(actual.configurationProperties.isBackground, expected.configurationProperties.isBackground, 'isBackground'); + assert.strictEqual(typeof actual.configurationProperties.problemMatchers, typeof expected.configurationProperties.problemMatchers); + assert.strictEqual(actual.configurationProperties.promptOnClose, expected.configurationProperties.promptOnClose, 'promptOnClose'); + assert.strictEqual(actual.configurationProperties.group, expected.configurationProperties.group, 'group'); + assert.strictEqual(actual.configurationProperties.groupType, expected.configurationProperties.groupType, 'groupType'); + if (actual.configurationProperties.problemMatchers && expected.configurationProperties.problemMatchers) { + assert.strictEqual(actual.configurationProperties.problemMatchers.length, expected.configurationProperties.problemMatchers.length); + for (let i = 0; i < actual.configurationProperties.problemMatchers.length; i++) { + assertProblemMatcher(actual.configurationProperties.problemMatchers[i], expected.configurationProperties.problemMatchers[i]); } } }