diff --git a/src/vs/workbench/parts/tasks/browser/quickOpen.ts b/src/vs/workbench/parts/tasks/browser/quickOpen.ts index c0cbb0c12b67e74ee87547af5e6612f8c8506876..a842937eeca6f8d0e0f7c0021e36dad2822a7352 100644 --- a/src/vs/workbench/parts/tasks/browser/quickOpen.ts +++ b/src/vs/workbench/parts/tasks/browser/quickOpen.ts @@ -98,7 +98,12 @@ export abstract class QuickOpenHandler extends Quickopen.QuickOpenHandler { let configured: CustomTask[] = []; let detected: ContributedTask[] = []; let taskMap: IStringDictionary = Object.create(null); - tasks.forEach(task => taskMap[Task.getKey(task)] = task); + tasks.forEach(task => { + let key = Task.getRecentlyUsedKey(task); + if (key) { + taskMap[key] = task; + } + }); recentlyUsedTasks.keys().forEach(key => { let task = taskMap[key]; if (task) { @@ -106,7 +111,8 @@ export abstract class QuickOpenHandler extends Quickopen.QuickOpenHandler { } }); for (let task of tasks) { - if (!recentlyUsedTasks.has(Task.getKey(task))) { + let key = Task.getRecentlyUsedKey(task); + if (!key || !recentlyUsedTasks.has(key)) { if (CustomTask.is(task)) { configured.push(task); } else { diff --git a/src/vs/workbench/parts/tasks/common/tasks.ts b/src/vs/workbench/parts/tasks/common/tasks.ts index 12c20adf3a3c47b262c4fcc74df152b2852039d8..6f4def9b10b902a6a12f12cdbbffed9d9ca9de04 100644 --- a/src/vs/workbench/parts/tasks/common/tasks.ts +++ b/src/vs/workbench/parts/tasks/common/tasks.ts @@ -227,7 +227,7 @@ export enum TaskScope { export namespace TaskSourceKind { export const Workspace: 'workspace' = 'workspace'; export const Extension: 'extension' = 'extension'; - export const Composite: 'composite' = 'composite'; + export const InMemory: 'inMemory' = 'inMemory'; } export interface TaskSourceConfigElement { @@ -256,12 +256,12 @@ export interface ExtensionTaskSourceTransfer { __workspaceFolder: URI; } -export interface CompositeTaskSource { - readonly kind: 'composite'; +export interface InMemoryTaskSource { + readonly kind: 'inMemory'; readonly label: string; } -export type TaskSource = WorkspaceTaskSource | ExtensionTaskSource | CompositeTaskSource; +export type TaskSource = WorkspaceTaskSource | ExtensionTaskSource | InMemoryTaskSource; export interface TaskIdentifier { _key: string; @@ -403,33 +403,58 @@ export namespace ContributedTask { } } -export interface CompositeTask extends CommonTask, ConfigurationProperties { +export interface InMemoryTask extends CommonTask, ConfigurationProperties { /** * Indicated the source of the task (e.g tasks.json or extension) */ - _source: CompositeTaskSource; + _source: InMemoryTaskSource; - type: 'composite'; + type: 'inMemory'; 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 namespace InMemoryTask { + export function is(value: any): value is InMemoryTask { + let candidate = value as InMemoryTask; + return candidate && candidate._source && candidate._source.kind === TaskSourceKind.InMemory; } } -export type Task = CustomTask | ContributedTask | CompositeTask; +export type Task = CustomTask | ContributedTask | InMemoryTask; export namespace Task { - export function getKey(task: Task): string { - if (CustomTask.is(task) || CompositeTask.is(task)) { - return task.identifier; - } else { - return task.defines._key; + 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: 'custom', 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.defines._key }; + if (task._source.scope === TaskScope.Folder && task._source.workspaceFolder) { + key.folder = task._source.workspaceFolder.uri.toString(); + } + return JSON.stringify(key); } + return undefined; } export function getWorkspaceFolder(task: Task): IWorkspaceFolder | undefined { @@ -455,7 +480,7 @@ export namespace Task { } else { return 'workspace'; } - } else if (CompositeTask.is(task)) { + } else if (InMemoryTask.is(task)) { return 'composite'; } else { return 'unknown'; 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 de7a52799e704ad916f47fe59d6a51eeeee07643..91753e9ff9ce639ed26bc20011d6ee91d86924c1 100644 --- a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts +++ b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts @@ -73,7 +73,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, CompositeTask, TaskSet, TaskGroup, ExecutionEngine, JsonSchemaVersion, TaskSourceKind, TaskIdentifier, TaskSorter } from 'vs/workbench/parts/tasks/common/tasks'; +import { Task, CustomTask, ConfiguringTask, ContributedTask, InMemoryTask, TaskSet, TaskGroup, ExecutionEngine, JsonSchemaVersion, TaskSourceKind, TaskIdentifier, TaskSorter } 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'; @@ -849,7 +849,7 @@ class TaskService extends EventEmitter implements ITaskService { throw new TaskError(Severity.Info, nls.localize('TaskServer.noTask', 'Requested task {0} to execute not found.', task.name), TaskErrors.TaskNotFound); } else { let resolver = this.createResolver(grouped); - if (options && options.attachProblemMatcher && this.shouldAttachProblemMatcher(task) && !CompositeTask.is(task)) { + if (options && options.attachProblemMatcher && this.shouldAttachProblemMatcher(task) && !InMemoryTask.is(task)) { return this.attachProblemMatcher(task).then((toExecute) => { if (toExecute) { return this.executeTask(toExecute, resolver); @@ -1164,11 +1164,11 @@ class TaskService extends EventEmitter implements ITaskService { return { task: extensionTasks[0], resolver }; } else { let id: string = UUID.generateUuid(); - let task: CompositeTask = { + let task: InMemoryTask = { _id: id, - _source: { kind: TaskSourceKind.Composite, label: 'composite' }, + _source: { kind: TaskSourceKind.InMemory, label: 'inMemory' }, _label: id, - type: 'composite', + type: 'inMemory', name: id, identifier: id, dependsOn: extensionTasks.map((task) => { return { workspaceFolder: Task.getWorkspaceFolder(task), task: task._id }; }) @@ -1213,7 +1213,10 @@ class TaskService extends EventEmitter implements ITaskService { return ProblemMatcherRegistry.onReady().then(() => { return this.textFileService.saveAll().then((value) => { // make sure all dirty files are saved let executeResult = this.getTaskSystem().run(task, resolver); - this.getRecentlyUsedTasks().set(Task.getKey(task), Task.getKey(task), Touch.First); + let key = Task.getRecentlyUsedKey(task); + if (key) { + this.getRecentlyUsedTasks().set(key, key, Touch.First); + } if (executeResult.kind === TaskExecuteKind.Active) { let active = executeResult.active; if (active.same) { @@ -1809,7 +1812,12 @@ class TaskService extends EventEmitter implements ITaskService { let configured: Task[] = []; let detected: Task[] = []; let taskMap: IStringDictionary = Object.create(null); - tasks.forEach(task => taskMap[Task.getKey(task)] = task); + tasks.forEach(task => { + let key = Task.getRecentlyUsedKey(task); + if (key) { + taskMap[key] = task; + } + }); recentlyUsedTasks.keys().forEach(key => { let task = taskMap[key]; if (task) { @@ -1817,7 +1825,8 @@ class TaskService extends EventEmitter implements ITaskService { } }); for (let task of tasks) { - if (!recentlyUsedTasks.has(Task.getKey(task))) { + let key = Task.getRecentlyUsedKey(task); + if (!key || !recentlyUsedTasks.has(key)) { if (task._source.kind === TaskSourceKind.Workspace) { configured.push(task); } else { @@ -2216,7 +2225,7 @@ class TaskService extends EventEmitter implements ITaskService { if (task === defaultTask && CustomTask.is(task)) { this.openConfig(task); } - if (!CompositeTask.is(task)) { + if (!InMemoryTask.is(task)) { this.customize(task, { group: { kind: 'build', isDefault: true } }, true); } }); @@ -2250,7 +2259,7 @@ class TaskService extends EventEmitter implements ITaskService { if (!task) { return; } - if (!CompositeTask.is(task)) { + if (!InMemoryTask.is(task)) { this.customize(task, { group: { kind: 'test', isDefault: true } }, true); } }); 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 85d747f12c3f24c719de7f785f55613b292423e1..4d212d7fd89bf297eb2f4bf60408f80135f63ab8 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 @@ -458,7 +458,7 @@ 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'); - if (!Tasks.CompositeTask.is(actual) && !Tasks.CompositeTask.is(expected)) { + if (!Tasks.InMemoryTask.is(actual) && !Tasks.InMemoryTask.is(expected)) { assertCommandConfiguration(actual.command, expected.command); } assert.strictEqual(actual.isBackground, expected.isBackground, 'isBackground');