diff --git a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts index c322650a4dd..7da5ec04957 100644 --- a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts +++ b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts @@ -218,6 +218,8 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer protected _taskRunningState: IContextKey; + private _persistentTasks: LRUCache | undefined; + protected _outputChannel: IOutputChannel; protected readonly _onDidStateChange: Emitter; private _waitForAllSupportedExecutions: Promise; @@ -334,11 +336,14 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer this._willRestart = e.reason !== ShutdownReason.RELOAD; }); this._register(this.onDidStateChange(e => { - this._logService.debug('Task Event kind: ', e.kind); + this._log(nls.localize('taskEvent', 'Task Event kind: {0}', e.kind), true); if (e.kind === TaskEventKind.Changed) { // no-op } else if ((this._willRestart || (e.kind === TaskEventKind.Terminated && e.exitReason === TerminalExitReason.User)) && e.taskId) { - this.removePersistentTask(e.taskId); + const key = e.__task.getKey(); + if (key) { + this.removePersistentTask(key); + } } else if (e.kind === TaskEventKind.Start && e.__task && e.__task.getWorkspaceFolder()) { this._setPersistentTask(e.__task); } @@ -385,19 +390,19 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer private _attemptTaskReconnection(): void { if (this._lifecycleService.startupKind !== StartupKind.ReloadedWindow) { - this._log(nls.localize('TaskService.skippingReconnection', '#taskService startup kind not window reload, setting connected and removing persistent tasks\n'), true); + this._log(nls.localize('TaskService.skippingReconnection', 'Startup kind not window reload, setting connected and removing persistent tasks'), true); this._tasksReconnected = true; this._storageService.remove(AbstractTaskService.PersistentTasks_Key, StorageScope.WORKSPACE); } if (!this._configurationService.getValue(TaskSettingId.Reconnection) || this._tasksReconnected) { - this._log(nls.localize('TaskService.notConnecting', '#taskService Setting tasks connected configured value {0}, tasks were already reconnected {1}\n', this._configurationService.getValue(TaskSettingId.Reconnection), this._tasksReconnected), true); + this._log(nls.localize('TaskService.notConnecting', 'Setting tasks connected configured value {0}, tasks were already reconnected {1}', this._configurationService.getValue(TaskSettingId.Reconnection), this._tasksReconnected), true); this._tasksReconnected = true; return; } - this._log(nls.localize('TaskService.reconnecting', '#taskService Reconnecting to running tasks...\n'), true); + this._log(nls.localize('TaskService.reconnecting', 'Reconnecting to running tasks...'), true); this.getWorkspaceTasks(TaskRunSource.Reconnect).then(async () => { this._tasksReconnected = await this._reconnectTasks(); - this._log(nls.localize('TaskService.reconnected', '#taskService Reconnected to running tasks.\n'), true); + this._log(nls.localize('TaskService.reconnected', 'Reconnected to running tasks.'), true); this._onDidReconnectToTasks.fire(); }); } @@ -405,11 +410,11 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer private async _reconnectTasks(): Promise { const tasks = await this.getSavedTasks('persistent'); if (!tasks.length) { - this._log(nls.localize('TaskService.noTasks', '#taskService No persistent tasks to reconnect.\n'), true); + this._log(nls.localize('TaskService.noTasks', 'No persistent tasks to reconnect.'), true); return true; } const taskLabels = tasks.map(task => task._label).join(', '); - this._log(nls.localize('TaskService.reconnectingTasks', '#taskService Reconnecting to {0} tasks...\n', taskLabels), true); + this._log(nls.localize('TaskService.reconnectingTasks', 'Reconnecting to {0} tasks...', taskLabels), true); for (const task of tasks) { if (ConfiguringTask.is(task)) { const resolved = await this.tryResolveTask(task); @@ -819,7 +824,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer if (matchingProviderUnavailable) { this._log(nls.localize( 'TaskService.providerUnavailable', - 'Warning: {0} tasks are unavailable in the current environment.\n', + 'Warning: {0} tasks are unavailable in the current environment.', configuringTask.configures.type )); } @@ -969,26 +974,25 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer } private _getPersistentTasks(): LRUCache { - // if (this._persistentTasks) { - // this._log(nls.localize('taskService.gettingCachedTasks', 'Returning cached tasks {0}\n', this._persistentTasks.size)); - // return this._persistentTasks; - // } - //TODO: should this # be configurable? - const persistentTasks = new LRUCache(10); + if (this._persistentTasks) { + this._log(nls.localize('taskService.gettingCachedTasks', 'Returning cached tasks {0}', this._persistentTasks.size), true); + return this._persistentTasks; + } + this._persistentTasks = new LRUCache(10); const storageValue = this._storageService.get(AbstractTaskService.PersistentTasks_Key, StorageScope.WORKSPACE); if (storageValue) { try { const values: [string, string][] = JSON.parse(storageValue); if (Array.isArray(values)) { for (const value of values) { - persistentTasks.set(value[0], value[1]); + this._persistentTasks.set(value[0], value[1]); } } } catch (error) { // Ignore. We use the empty result } } - return persistentTasks; + return this._persistentTasks; } private _getFolderFromTaskKey(key: string): { folder: string | undefined; isWorkspaceFile: boolean | undefined } { @@ -1007,7 +1011,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer const workspaceToTaskMap: Map = new Map(); const storedTasks = this._getTasksFromStorage(type); const tasks: (Task | ConfiguringTask)[] = []; - this._log(nls.localize('taskService.getSavedTasks', '#taskService Fetching tasks from task storage.\n'), true); + this._log(nls.localize('taskService.getSavedTasks', 'Fetching tasks from task storage.'), true); function addTaskToMap(map: Map, folder: string | undefined, task: any) { if (folder && !map.has(folder)) { map.set(folder, []); @@ -1021,7 +1025,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer const key = entry[0]; const task = JSON.parse(entry[1]); const folderInfo = this._getFolderFromTaskKey(key); - this._log(nls.localize('taskService.getSavedTasks.reading', '#taskService Reading tasks from task storage, {0}, {1}, {2}\n', key, task, folderInfo.folder), true); + this._log(nls.localize('taskService.getSavedTasks.reading', 'Reading tasks from task storage, {0}, {1}, {2}', key, task, folderInfo.folder), true); addTaskToMap(folderInfo.isWorkspaceFile ? workspaceToTaskMap : folderToTasksMap, folderInfo.folder, task); } @@ -1040,13 +1044,13 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer tasks: map.get(key) }, TaskRunSource.System, custom, customized, taskConfigSource, true); custom.forEach(task => { - const taskKey = task.getRecentlyUsedKey(); + const taskKey = task.getKey(); if (taskKey) { readTasksMap.set(taskKey, task); } }); for (const configuration in customized) { - const taskKey = customized[configuration].getRecentlyUsedKey(); + const taskKey = customized[configuration].getKey(); if (taskKey) { readTasksMap.set(taskKey, customized[configuration]); } @@ -1058,9 +1062,9 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer for (const key of storedTasks.keys()) { if (readTasksMap.has(key)) { tasks.push(readTasksMap.get(key)!); - this._log(nls.localize('taskService.getSavedTasks.resolved', '#taskService Resolved task {0}\n', key, true)); + this._log(nls.localize('taskService.getSavedTasks.resolved', 'Resolved task {0}', key), true); } else { - this._log(nls.localize('taskService.getSavedTasks.unresolved', '#taskService Unable to resolve task {0} \n', key, true)); + this._log(nls.localize('taskService.getSavedTasks.unresolved', 'Unable to resolve task {0} ', key), true); } } return tasks; @@ -1074,7 +1078,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer } public removePersistentTask(key: string) { - this._log(nls.localize('taskService.removePersistentTask', '#taskService Removing persistent task {0}\n', key), true); + this._log(nls.localize('taskService.removePersistentTask', 'Removing persistent task {0}', key), true); if (this._getTasksFromStorage('persistent').has(key)) { this._getTasksFromStorage('persistent').delete(key); this._savePersistentTasks(); @@ -1089,7 +1093,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer } private async _setRecentlyUsedTask(task: Task): Promise { - let key = task.getRecentlyUsedKey(); + let key = task.getKey(); if (!InMemoryTask.is(task) && key) { const customizations = this._createCustomizableTask(task); if (ContributedTask.is(task) && customizations) { @@ -1100,7 +1104,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer tasks: [customizations] }, TaskRunSource.System, custom, customized, TaskConfig.TaskConfigSource.TasksJson, true); for (const configuration in customized) { - key = customized[configuration].getRecentlyUsedKey()!; + key = customized[configuration].getKey()!; } } this._getTasksFromStorage('historical').set(key, JSON.stringify(customizations)); @@ -1132,7 +1136,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer if (!this._configurationService.getValue(TaskSettingId.Reconnection)) { return; } - let key = task.getRecentlyUsedKey(); + let key = task.getKey(); if (!InMemoryTask.is(task) && key) { const customizations = this._createCustomizableTask(task); if (ContributedTask.is(task) && customizations) { @@ -1143,26 +1147,26 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer tasks: [customizations] }, TaskRunSource.System, custom, customized, TaskConfig.TaskConfigSource.TasksJson, true); for (const configuration in customized) { - key = customized[configuration].getRecentlyUsedKey()!; + key = customized[configuration].getKey()!; } } if (!task.configurationProperties.isBackground) { return; } - this._log(nls.localize('taskService.setPersistentTask', '#taskService Setting persistent task {0}\n', key), true); + this._log(nls.localize('taskService.setPersistentTask', 'Setting persistent task {0}', key), true); this._getTasksFromStorage('persistent').set(key, JSON.stringify(customizations)); this._savePersistentTasks(); } } private _savePersistentTasks(): void { - const persistentTasks = this._getTasksFromStorage('persistent'); - const keys = [...persistentTasks.keys()]; + this._persistentTasks = this._getTasksFromStorage('persistent'); + const keys = [...this._persistentTasks.keys()]; const keyValues: [string, string][] = []; for (const key of keys) { - keyValues.push([key, persistentTasks.get(key, Touch.None)!]); + keyValues.push([key, this._persistentTasks.get(key, Touch.None)!]); } - this._log(nls.localize('savePersistentTask', 'Saving persistent tasks: {0}\n', keys.join(', ')), true); + this._log(nls.localize('savePersistentTask', 'Saving persistent tasks: {0}', keys.join(', ')), true); this._storageService.store(AbstractTaskService.PersistentTasks_Key, JSON.stringify(keyValues), StorageScope.WORKSPACE, StorageTarget.MACHINE); } @@ -1716,7 +1720,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer }; if (workspaceTasks.length > 0) { if (workspaceTasks.length > 1) { - this._log(nls.localize('moreThanOneBuildTask', 'There are many build tasks defined in the tasks.json. Executing the first one.\n')); + this._log(nls.localize('moreThanOneBuildTask', 'There are many build tasks defined in the tasks.json. Executing the first one.')); } return { task: workspaceTasks[0], resolver }; } @@ -2010,7 +2014,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer this._log(`Error: ${error.message}\n`); this._showOutput(); } else { - this._log('Unknown error received while collecting tasks from providers.\n'); + this._log('Unknown error received while collecting tasks from providers.'); this._showOutput(); } } finally { @@ -2163,13 +2167,13 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer if (requiredTaskProviderUnavailable) { this._log(nls.localize( 'TaskService.providerUnavailable', - 'Warning: {0} tasks are unavailable in the current environment.\n', + 'Warning: {0} tasks are unavailable in the current environment.', configuringTask.configures.type )); } else { this._log(nls.localize( 'TaskService.noConfiguration', - 'Error: The {0} task detection didn\'t contribute a task for the following configuration:\n{1}\nThe task will be ignored.\n', + 'Error: The {0} task detection didn\'t contribute a task for the following configuration:\n{1}\nThe task will be ignored.', configuringTask.configures.type, JSON.stringify(configuringTask._source.config.element, undefined, 4) )); @@ -2339,7 +2343,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer } } if (isAffected) { - this._log(nls.localize({ key: 'TaskSystem.invalidTaskJsonOther', comment: ['Message notifies of an error in one of several places there is tasks related json, not necessarily in a file named tasks.json'] }, 'Error: The content of the tasks json in {0} has syntax errors. Please correct them before executing a task.\n', location)); + this._log(nls.localize({ key: 'TaskSystem.invalidTaskJsonOther', comment: ['Message notifies of an error in one of several places there is tasks related json, not necessarily in a file named tasks.json'] }, 'Error: The content of the tasks json in {0} has syntax errors. Please correct them before executing a task.', location)); this._showOutput(); return { config, hasParseErrors: true }; } @@ -2348,7 +2352,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer } private _log(value: string, verbose?: boolean): void { - if (!verbose || verbose && this._configurationService.getValue(TaskSettingId.VerboseLogging)) { + if (verbose && this._configurationService.getValue(TaskSettingId.VerboseLogging) || !verbose) { this._outputChannel.append(value); } } @@ -2466,7 +2470,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer ignoredWorkspaceFolders.push(workspaceFolder); this._log(nls.localize( 'taskService.ignoreingFolder', - 'Ignoring task configurations for workspace folder {0}. Multi folder workspace task support requires that all folders use task version 2.0.0\n', + 'Ignoring task configurations for workspace folder {0}. Multi folder workspace task support requires that all folders use task version 2.0.0', workspaceFolder.uri.fsPath)); } } @@ -2527,7 +2531,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer } } if (isAffected) { - this._log(nls.localize('TaskSystem.invalidTaskJson', 'Error: The content of the tasks.json file has syntax errors. Please correct them before executing a task.\n')); + this._log(nls.localize('TaskSystem.invalidTaskJson', 'Error: The content of the tasks.json file has syntax errors. Please correct them before executing a task.')); this._showOutput(); return { config: undefined, hasParseErrors: true }; } @@ -2739,7 +2743,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer const recentlyUsedTasks = this.getRecentlyUsedTasksV1(); const taskMap: IStringDictionary = Object.create(null); tasks.forEach(task => { - const key = task.getRecentlyUsedKey(); + const key = task.getKey(); if (key) { taskMap[key] = task; } diff --git a/src/vs/workbench/contrib/tasks/browser/taskQuickPick.ts b/src/vs/workbench/contrib/tasks/browser/taskQuickPick.ts index 3c15935f60a..6dde509a9d4 100644 --- a/src/vs/workbench/contrib/tasks/browser/taskQuickPick.ts +++ b/src/vs/workbench/contrib/tasks/browser/taskQuickPick.ts @@ -149,11 +149,11 @@ export class TaskQuickPick extends Disposable { const definition = configuredTasks[j].getDefinition()?._key; const type = configuredTasks[j].type; const label = configuredTasks[j]._label; - const recentKey = configuredTasks[j].getRecentlyUsedKey(); + const recentKey = configuredTasks[j].getKey(); const findIndex = recentTasks.findIndex((value) => { return (workspaceFolder && definition && value.getWorkspaceFolder()?.uri.toString() === workspaceFolder && ((value.getDefinition()?._key === definition) || (value.type === type && value._label === label))) - || (recentKey && value.getRecentlyUsedKey() === recentKey); + || (recentKey && value.getKey() === recentKey); }); if (findIndex === -1) { dedupedConfiguredTasks.push(configuredTasks[j]); @@ -231,7 +231,7 @@ export class TaskQuickPick extends Disposable { picker.onDidTriggerItemButton(async (context) => { const task = context.item.task; if (context.button.iconClass === ThemeIcon.asClassName(removeTaskIcon)) { - const key = (task && !Types.isString(task)) ? task.getRecentlyUsedKey() : undefined; + const key = (task && !Types.isString(task)) ? task.getKey() : undefined; if (key) { this._taskService.removeRecentlyUsedTask(key); } diff --git a/src/vs/workbench/contrib/tasks/browser/tasksQuickAccess.ts b/src/vs/workbench/contrib/tasks/browser/tasksQuickAccess.ts index dd605f15b54..51e6ae001b0 100644 --- a/src/vs/workbench/contrib/tasks/browser/tasksQuickAccess.ts +++ b/src/vs/workbench/contrib/tasks/browser/tasksQuickAccess.ts @@ -65,7 +65,7 @@ export class TasksQuickAccessProvider extends PickerQuickAccessProvider { if ((index === 1) && (quickAccessEntry.buttons?.length === 2)) { - const key = (task && !isString(task)) ? task.getRecentlyUsedKey() : undefined; + const key = (task && !isString(task)) ? task.getKey() : undefined; if (key) { this._taskService.removeRecentlyUsedTask(key); } diff --git a/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts b/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts index dd2d581c170..20b6a6c35e5 100644 --- a/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts +++ b/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts @@ -386,9 +386,9 @@ export class TerminalTaskSystem extends Disposable implements ITaskSystem { } public getLastInstance(task: Task): Task | undefined { - const recentKey = task.getRecentlyUsedKey(); + const recentKey = task.getKey(); return Object.values(this._activeTasks).reverse().find( - (value) => recentKey && recentKey === value.task.getRecentlyUsedKey())?.task; + (value) => recentKey && recentKey === value.task.getKey())?.task; } public getBusyTasks(): Task[] { @@ -408,9 +408,9 @@ export class TerminalTaskSystem extends Disposable implements ITaskSystem { } private _getInstances(task: Task): IActiveTerminalData[] { - const recentKey = task.getRecentlyUsedKey(); + const recentKey = task.getKey(); return Object.values(this._activeTasks).filter( - (value) => recentKey && recentKey === value.task.getRecentlyUsedKey()); + (value) => recentKey && recentKey === value.task.getKey()); } private _removeFromActiveTasks(task: Task | string): void { diff --git a/src/vs/workbench/contrib/tasks/common/tasks.ts b/src/vs/workbench/contrib/tasks/common/tasks.ts index 88da77f9181..b7884faa838 100644 --- a/src/vs/workbench/contrib/tasks/common/tasks.ts +++ b/src/vs/workbench/contrib/tasks/common/tasks.ts @@ -617,7 +617,7 @@ export abstract class CommonTask { return this._id; } - public getRecentlyUsedKey(): string | undefined { + public getKey(): string | undefined { return undefined; } @@ -788,10 +788,13 @@ export class CustomTask extends CommonTask { } public override getCommonTaskId(): string { - return this._source.customizes ? super.getCommonTaskId() : (this.getRecentlyUsedKey() ?? super.getCommonTaskId()); + return this._source.customizes ? super.getCommonTaskId() : (this.getKey() ?? super.getCommonTaskId()); } - public override getRecentlyUsedKey(): string | undefined { + /** + * @returns A key representing the task + */ + public override getKey(): string | undefined { interface ICustomKey { type: string; folder: string; @@ -875,7 +878,7 @@ export class ConfiguringTask extends CommonTask { return this._source.kind === TaskSourceKind.User ? USER_TASKS_GROUP_KEY : this._source.config.workspaceFolder?.uri.toString(); } - public override getRecentlyUsedKey(): string | undefined { + public override getKey(): string | undefined { interface ICustomKey { type: string; folder: string; @@ -963,7 +966,7 @@ export class ContributedTask extends CommonTask { return undefined; } - public override getRecentlyUsedKey(): string | undefined { + public override getKey(): string | undefined { interface IContributedKey { type: string; scope: number;