Skip to content

Commit 4e49ab9

Browse files
authored
Restarting task should read the updated content (#251755)
* Try to fix update on restart, rerun * TODO: clean up * Re-arrange to fix import layer, create get/set method for lastTask * properly align method names * Start cleaning up * Bring back old comments * cleaner code * formatting * Fix so that restarting works properly as well. Previous was re-run last * Remove comment * Fix bug where compile tasks under configuringTask were not refreshing
1 parent 1d30210 commit 4e49ab9

File tree

3 files changed

+104
-36
lines changed

3 files changed

+104
-36
lines changed

src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ import { ITerminalProfileResolverService } from '../../terminal/common/terminal.
4949

5050
import { ConfiguringTask, ContributedTask, CustomTask, ExecutionEngine, InMemoryTask, ITaskEvent, ITaskIdentifier, ITaskSet, JsonSchemaVersion, KeyedTaskIdentifier, RuntimeType, Task, TASK_RUNNING_STATE, TaskDefinition, TaskGroup, TaskRunSource, TaskSettingId, TaskSorter, TaskSourceKind, TasksSchemaProperties, USER_TASKS_GROUP_KEY, TaskEventKind, InstancePolicy } from '../common/tasks.js';
5151
import { CustomExecutionSupportedContext, ICustomizationProperties, IProblemMatcherRunOptions, ITaskFilter, ITaskProvider, ITaskService, IWorkspaceFolderTaskResult, ProcessExecutionSupportedContext, ServerlessWebContext, ShellExecutionSupportedContext, TaskCommandsRegistered, TaskExecutionSupportedContext } from '../common/taskService.js';
52-
import { ITaskExecuteResult, ITaskResolver, ITaskSummary, ITaskSystem, ITaskSystemInfo, ITaskTerminateResponse, TaskError, TaskErrors, TaskExecuteKind } from '../common/taskSystem.js';
52+
import { ITaskExecuteResult, ITaskResolver, ITaskSummary, ITaskSystem, ITaskSystemInfo, ITaskTerminateResponse, TaskError, TaskErrors, TaskExecuteKind, Triggers, VerifiedTask } from '../common/taskSystem.js';
5353
import { getTemplates as getTaskTemplates } from '../common/taskTemplates.js';
5454

5555
import * as TaskConfig from '../common/taskConfiguration.js';
@@ -324,8 +324,26 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
324324
}
325325

326326
this._setTaskLRUCacheLimit();
327-
await this._updateWorkspaceTasks(TaskRunSource.ConfigurationChange);
327+
const mapStringToFolderTasks: Map<string, IWorkspaceFolderTaskResult> = await this._updateWorkspaceTasks(TaskRunSource.ConfigurationChange);
328328
this._onDidChangeTaskConfig.fire();
329+
330+
// Loop through all workspaceFolderTask result
331+
for (const [folderUri, folderResult] of mapStringToFolderTasks) {
332+
if (!folderResult.set?.tasks?.length) {
333+
continue;
334+
}
335+
336+
for (const task of folderResult.set.tasks) {
337+
const realUniqueId = task._id;
338+
const lastTask = this._taskSystem?.lastTask?.task._id;
339+
340+
if (lastTask && lastTask === realUniqueId && folderUri !== 'setting') {
341+
const verifiedLastTask = new VerifiedTask(task, this._taskSystem!.lastTask!.resolver, Triggers.command);
342+
this._taskSystem!.lastTask = verifiedLastTask;
343+
}
344+
}
345+
}
346+
329347
}));
330348
this._taskRunningState = TASK_RUNNING_STATE.bindTo(_contextKeyService);
331349
this._onDidStateChange = this._register(new Emitter());
@@ -2035,7 +2053,14 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
20352053
const response = await this._taskSystem.terminate(task);
20362054
if (response.success) {
20372055
try {
2038-
await this.run(task);
2056+
// Before restarting, check if the task still exists and get updated version
2057+
const updatedTask = await this._findUpdatedTask(task);
2058+
if (updatedTask) {
2059+
await this.run(updatedTask);
2060+
} else {
2061+
// Task no longer exists, show warning
2062+
this._notificationService.warn(nls.localize('TaskSystem.taskNoLongerExists', 'Task {0} no longer exists or has been modified. Cannot restart.', task.configurationProperties.name));
2063+
}
20392064
} catch {
20402065
// eat the error, we don't care about it here
20412066
}
@@ -2044,6 +2069,37 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
20442069
}
20452070
}
20462071

2072+
private async _findUpdatedTask(originalTask: Task): Promise<Task | undefined> {
2073+
const mapStringToFolderTasks = await this._updateWorkspaceTasks(TaskRunSource.System);
2074+
2075+
// Look for the task in current workspace configuration
2076+
for (const [_, folderResult] of mapStringToFolderTasks) {
2077+
if (!folderResult.set?.tasks?.length && !folderResult.configurations?.byIdentifier) {
2078+
continue;
2079+
}
2080+
// There are two ways where Task lives:
2081+
// 1. folderResult.set.tasks
2082+
if (folderResult.set?.tasks) {
2083+
for (const task of folderResult.set.tasks) {
2084+
// Check if this is the same task by ID
2085+
if (task._id === originalTask._id) {
2086+
return task;
2087+
}
2088+
}
2089+
}
2090+
// 2. folderResult.configurations.byIdentifier
2091+
if (folderResult.configurations?.byIdentifier) {
2092+
for (const [_, configuringTask] of Object.entries(folderResult.configurations.byIdentifier)) {
2093+
// Check if this is the same task by ID
2094+
if (configuringTask._id === originalTask._id) {
2095+
return this.tryResolveTask(configuringTask);
2096+
}
2097+
}
2098+
}
2099+
}
2100+
return undefined;
2101+
}
2102+
20472103
public async terminate(task: Task): Promise<ITaskTerminateResponse> {
20482104
if (!(await this._trust())) {
20492105
return { success: true, task: undefined };
@@ -2157,7 +2213,6 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
21572213
return done(taskSet);
21582214
}, error), 5000, () => {
21592215
// onTimeout
2160-
console.error('Timed out getting tasks from ', providerType);
21612216
done(undefined);
21622217
});
21632218
}

src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts

Lines changed: 9 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ import { IViewsService } from '../../../services/views/common/viewsService.js';
3939
import { TaskTerminalStatus } from './taskTerminalStatus.js';
4040
import { ProblemCollectorEventKind, ProblemHandlingStrategy, StartStopProblemCollector, WatchingProblemCollector } from '../common/problemCollectors.js';
4141
import { GroupKind } from '../common/taskConfiguration.js';
42-
import { IResolveSet, IResolvedVariables, ITaskExecuteResult, ITaskResolver, ITaskSummary, ITaskSystem, ITaskSystemInfo, ITaskSystemInfoResolver, ITaskTerminateResponse, TaskError, TaskErrors, TaskExecuteKind, Triggers } from '../common/taskSystem.js';
42+
import { IResolveSet, IResolvedVariables, ITaskExecuteResult, ITaskResolver, ITaskSummary, ITaskSystem, ITaskSystemInfo, ITaskSystemInfoResolver, ITaskTerminateResponse, TaskError, TaskErrors, TaskExecuteKind, Triggers, VerifiedTask } from '../common/taskSystem.js';
4343
import { CommandOptions, CommandString, ContributedTask, CustomTask, DependsOrder, ICommandConfiguration, IConfigurationProperties, IExtensionTaskSource, IPresentationOptions, IShellConfiguration, IShellQuotingOptions, ITaskEvent, InMemoryTask, PanelKind, RerunForActiveTerminalCommandId, RevealKind, RevealProblemKind, RuntimeType, ShellQuoting, TASK_TERMINAL_ACTIVE, Task, TaskEvent, TaskEventKind, TaskScope, TaskSourceKind, rerunTaskIcon } from '../common/tasks.js';
4444
import { ITerminalGroupService, ITerminalInstance, ITerminalService } from '../../terminal/browser/terminal.js';
4545
import { VSCodeOscProperty, VSCodeOscPt, VSCodeSequence } from '../../terminal/browser/terminalEscapeSequences.js';
@@ -107,37 +107,6 @@ class VariableResolver {
107107
}
108108
}
109109

110-
class VerifiedTask {
111-
readonly task: Task;
112-
readonly resolver: ITaskResolver;
113-
readonly trigger: string;
114-
resolvedVariables?: IResolvedVariables;
115-
systemInfo?: ITaskSystemInfo;
116-
workspaceFolder?: IWorkspaceFolder;
117-
shellLaunchConfig?: IShellLaunchConfig;
118-
119-
constructor(task: Task, resolver: ITaskResolver, trigger: string) {
120-
this.task = task;
121-
this.resolver = resolver;
122-
this.trigger = trigger;
123-
}
124-
125-
public verify(): boolean {
126-
let verified = false;
127-
if (this.trigger && this.resolvedVariables && this.workspaceFolder && (this.shellLaunchConfig !== undefined)) {
128-
verified = true;
129-
}
130-
return verified;
131-
}
132-
133-
public getVerifiedTask(): { task: Task; resolver: ITaskResolver; trigger: string; resolvedVariables: IResolvedVariables; systemInfo: ITaskSystemInfo; workspaceFolder: IWorkspaceFolder; shellLaunchConfig: IShellLaunchConfig } {
134-
if (this.verify()) {
135-
return { task: this.task, resolver: this.resolver, trigger: this.trigger, resolvedVariables: this.resolvedVariables!, systemInfo: this.systemInfo!, workspaceFolder: this.workspaceFolder!, shellLaunchConfig: this.shellLaunchConfig! };
136-
} else {
137-
throw new Error('VerifiedTask was not checked. verify must be checked before getVerifiedTask.');
138-
}
139-
}
140-
}
141110

142111
export class TerminalTaskSystem extends Disposable implements ITaskSystem {
143112

@@ -322,6 +291,14 @@ export class TerminalTaskSystem extends Disposable implements ITaskSystem {
322291
}
323292
}
324293

294+
get lastTask(): VerifiedTask | undefined {
295+
return this._lastTask;
296+
}
297+
298+
set lastTask(task: VerifiedTask | undefined) {
299+
this._lastTask = task;
300+
}
301+
325302
private _showTaskLoadErrors(task: Task) {
326303
if (task.taskLoadMessages && task.taskLoadMessages.length > 0) {
327304
task.taskLoadMessages.forEach(loadMessage => {

src/vs/workbench/contrib/tasks/common/taskSystem.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import { IWorkspaceFolder } from '../../../../platform/workspace/common/workspac
1212
import { Task, ITaskEvent, KeyedTaskIdentifier } from './tasks.js';
1313
import { ConfigurationTarget } from '../../../../platform/configuration/common/configuration.js';
1414

15+
import { IShellLaunchConfig } from '../../../../platform/terminal/common/terminal.js';
16+
1517
export const enum TaskErrors {
1618
NotConfigured,
1719
RunningTask,
@@ -23,6 +25,38 @@ export const enum TaskErrors {
2325
UnknownError
2426
}
2527

28+
export class VerifiedTask {
29+
readonly task: Task;
30+
readonly resolver: ITaskResolver;
31+
readonly trigger: string;
32+
resolvedVariables?: IResolvedVariables;
33+
systemInfo?: ITaskSystemInfo;
34+
workspaceFolder?: IWorkspaceFolder;
35+
shellLaunchConfig?: IShellLaunchConfig;
36+
37+
constructor(task: Task, resolver: ITaskResolver, trigger: string) {
38+
this.task = task;
39+
this.resolver = resolver;
40+
this.trigger = trigger;
41+
}
42+
43+
public verify(): boolean {
44+
let verified = false;
45+
if (this.trigger && this.resolvedVariables && this.workspaceFolder && (this.shellLaunchConfig !== undefined)) {
46+
verified = true;
47+
}
48+
return verified;
49+
}
50+
51+
public getVerifiedTask(): { task: Task; resolver: ITaskResolver; trigger: string; resolvedVariables: IResolvedVariables; systemInfo: ITaskSystemInfo; workspaceFolder: IWorkspaceFolder; shellLaunchConfig: IShellLaunchConfig } {
52+
if (this.verify()) {
53+
return { task: this.task, resolver: this.resolver, trigger: this.trigger, resolvedVariables: this.resolvedVariables!, systemInfo: this.systemInfo!, workspaceFolder: this.workspaceFolder!, shellLaunchConfig: this.shellLaunchConfig! };
54+
} else {
55+
throw new Error('VerifiedTask was not checked. verify must be checked before getVerifiedTask.');
56+
}
57+
}
58+
}
59+
2660
export class TaskError {
2761
public severity: Severity;
2862
public message: string;
@@ -118,4 +152,6 @@ export interface ITaskSystem {
118152
isTaskVisible(task: Task): boolean;
119153
getTaskForTerminal(instanceId: number): Task | undefined;
120154
getFirstInstance(task: Task): Task | undefined;
155+
get lastTask(): VerifiedTask | undefined;
156+
set lastTask(task: VerifiedTask);
121157
}

0 commit comments

Comments
 (0)