Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/microsoft/vscode.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts')
-rw-r--r--src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts150
1 files changed, 118 insertions, 32 deletions
diff --git a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts
index 93cbe879116..c123a941880 100644
--- a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts
+++ b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts
@@ -57,7 +57,7 @@ import {
TaskSettingId,
TasksSchemaProperties
} from 'vs/workbench/contrib/tasks/common/tasks';
-import { ITaskService, ITaskProvider, IProblemMatcherRunOptions, ICustomizationProperties, ITaskFilter, IWorkspaceFolderTaskResult, CustomExecutionSupportedContext, ShellExecutionSupportedContext, ProcessExecutionSupportedContext } from 'vs/workbench/contrib/tasks/common/taskService';
+import { ITaskService, ITaskProvider, IProblemMatcherRunOptions, ICustomizationProperties, ITaskFilter, IWorkspaceFolderTaskResult, CustomExecutionSupportedContext, ShellExecutionSupportedContext, ProcessExecutionSupportedContext, TaskCommandsRegistered } from 'vs/workbench/contrib/tasks/common/taskService';
import { getTemplates as getTaskTemplates } from 'vs/workbench/contrib/tasks/common/taskTemplates';
import * as TaskConfig from '../common/taskConfiguration';
@@ -78,7 +78,7 @@ import { ITextEditorSelection, TextEditorSelectionRevealType } from 'vs/platform
import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
import { IViewsService, IViewDescriptorService } from 'vs/workbench/common/views';
-import { isWorkspaceFolder, ITaskQuickPickEntry, QUICKOPEN_DETAIL_CONFIG, TaskQuickPick, QUICKOPEN_SKIP_CONFIG, configureTaskIcon } from 'vs/workbench/contrib/tasks/browser/taskQuickPick';
+import { isWorkspaceFolder, ITaskQuickPickEntry, QUICKOPEN_DETAIL_CONFIG, TaskQuickPick, QUICKOPEN_SKIP_CONFIG, configureTaskIcon, ITaskTwoLevelQuickPickEntry } from 'vs/workbench/contrib/tasks/browser/taskQuickPick';
import { ILogService } from 'vs/platform/log/common/log';
import { once } from 'vs/base/common/functional';
import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService';
@@ -200,6 +200,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
private static _nextHandle: number = 0;
+ private _tasksReconnected: boolean = false;
private _schemaVersion: JsonSchemaVersion | undefined;
private _executionEngine: ExecutionEngine | undefined;
private _workspaceFolders: IWorkspaceFolder[] | undefined;
@@ -292,7 +293,9 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
}));
this._taskRunningState = TASK_RUNNING_STATE.bindTo(_contextKeyService);
this._onDidStateChange = this._register(new Emitter());
- this._registerCommands();
+ this._registerCommands().then(() => {
+ TaskCommandsRegistered.bindTo(this._contextKeyService).set(true);
+ });
this._configurationResolverService.contributeVariable('defaultBuildTask', async (): Promise<string | undefined> => {
let tasks = await this._getTasksForGroup(TaskGroup.Build);
if (tasks.length > 0) {
@@ -337,6 +340,27 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
processContext.set(process && !isVirtual);
}
this._onDidRegisterSupportedExecutions.fire();
+ if (this._jsonTasksSupported && !this._tasksReconnected) {
+ this._reconnectTasks();
+ }
+ }
+
+ private async _reconnectTasks(): Promise<void> {
+ const recentlyUsedTasks = await this.readRecentTasks();
+ if (!recentlyUsedTasks.length) {
+ return;
+ }
+ for (const task of recentlyUsedTasks) {
+ if (ConfiguringTask.is(task)) {
+ const resolved = await this.tryResolveTask(task);
+ if (resolved) {
+ this.run(resolved, undefined, TaskRunSource.Reconnect);
+ }
+ } else {
+ this.run(task, undefined, TaskRunSource.Reconnect);
+ }
+ }
+ this._tasksReconnected = true;
}
public get onDidStateChange(): Event<ITaskEvent> {
@@ -347,7 +371,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
return this.inTerminal();
}
- private _registerCommands(): void {
+ private async _registerCommands(): Promise<void> {
CommandsRegistry.registerCommand({
id: 'workbench.action.tasks.runTask',
handler: async (accessor, arg) => {
@@ -359,8 +383,30 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
description: 'Run Task',
args: [{
name: 'args',
+ isOptional: true,
+ description: nls.localize('runTask.arg', "Filters the tasks shown in the quickpick"),
schema: {
- 'type': 'string',
+ anyOf: [
+ {
+ type: 'string',
+ description: nls.localize('runTask.label', "The task's label or a term to filter by")
+ },
+ {
+ type: 'object',
+ properties: {
+ type: {
+ type: 'string',
+ description: nls.localize('runTask.type', "The contributed task type"),
+ enum: Array.from(this._providerTypes.values()).map(provider => provider)
+ },
+ taskName: {
+ type: 'string',
+ description: nls.localize('runTask.taskName', "The task's label or a term to filter by"),
+ enum: await this.tasks().then((tasks) => tasks.map(t => t._label))
+ }
+ }
+ }
+ ]
}
}]
}
@@ -383,7 +429,6 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
this._runTerminateCommand(arg);
}
});
-
CommandsRegistry.registerCommand('workbench.action.tasks.showLog', () => {
if (!this._canRunCommand()) {
return;
@@ -639,7 +684,6 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
}
}
}
-
return result;
}
@@ -895,7 +939,6 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
map.get(folder).push(task);
}
}
-
for (const entry of recentlyUsedTasks.entries()) {
const key = entry[0];
const task = JSON.parse(entry[1]);
@@ -904,6 +947,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
}
const readTasksMap: Map<string, (Task | ConfiguringTask)> = new Map();
+
async function readTasks(that: AbstractTaskService, map: Map<string, any>, isWorkspaceFile: boolean) {
for (const key of map.keys()) {
const custom: CustomTask[] = [];
@@ -932,7 +976,6 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
}
await readTasks(this, folderToTasksMap, false);
await readTasks(this, workspaceToTaskMap, true);
-
for (const key of recentlyUsedTasks.keys()) {
if (readTasksMap.has(key)) {
tasks.push(readTasksMap.get(key)!);
@@ -1727,8 +1770,11 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
? await this.getTask(taskFolder, taskIdentifier) : task) ?? task;
}
await ProblemMatcherRegistry.onReady();
- const executeResult = this._getTaskSystem().run(taskToRun, resolver);
- return this._handleExecuteResult(executeResult, runSource);
+ const executeResult = runSource === TaskRunSource.Reconnect ? this._getTaskSystem().reconnect(taskToRun, resolver) : this._getTaskSystem().run(taskToRun, resolver);
+ if (executeResult) {
+ return this._handleExecuteResult(executeResult, runSource);
+ }
+ return { exitCode: 0 };
}
private async _handleExecuteResult(executeResult: ITaskExecuteResult, runSource?: TaskRunSource): Promise<ITaskSummary> {
@@ -1759,6 +1805,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
throw new TaskError(Severity.Warning, nls.localize('TaskSystem.active', 'There is already a task running. Terminate it first before executing another task.'), TaskErrors.RunningTask);
}
}
+ this._setRecentlyUsedTask(executeResult.task);
return executeResult.promise;
}
@@ -2127,7 +2174,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
}
private get _jsonTasksSupported(): boolean {
- return !!ShellExecutionSupportedContext.getValue(this._contextKeyService) && !!ProcessExecutionSupportedContext.getValue(this._contextKeyService);
+ return ShellExecutionSupportedContext.getValue(this._contextKeyService) === true && ProcessExecutionSupportedContext.getValue(this._contextKeyService) === true;
}
private _computeWorkspaceFolderTasks(workspaceFolder: IWorkspaceFolder, runSource: TaskRunSource = TaskRunSource.User): Promise<IWorkspaceFolderTaskResult> {
@@ -2521,11 +2568,11 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
return entries;
}
- private async _showTwoLevelQuickPick(placeHolder: string, defaultEntry?: ITaskQuickPickEntry) {
- return TaskQuickPick.show(this, this._configurationService, this._quickInputService, this._notificationService, this._dialogService, this._themeService, placeHolder, defaultEntry);
+ private async _showTwoLevelQuickPick(placeHolder: string, defaultEntry?: ITaskQuickPickEntry, filter?: string) {
+ return TaskQuickPick.show(this, this._configurationService, this._quickInputService, this._notificationService, this._dialogService, this._themeService, placeHolder, defaultEntry, filter);
}
- private async _showQuickPick(tasks: Promise<Task[]> | Task[], placeHolder: string, defaultEntry?: ITaskQuickPickEntry, group: boolean = false, sort: boolean = false, selectedEntry?: ITaskQuickPickEntry, additionalEntries?: ITaskQuickPickEntry[]): Promise<ITaskQuickPickEntry | undefined | null> {
+ private async _showQuickPick(tasks: Promise<Task[]> | Task[], placeHolder: string, defaultEntry?: ITaskQuickPickEntry, group: boolean = false, sort: boolean = false, selectedEntry?: ITaskQuickPickEntry, additionalEntries?: ITaskQuickPickEntry[], filter?: string): Promise<ITaskQuickPickEntry | undefined | null> {
const tokenSource = new CancellationTokenSource();
const cancellationToken: CancellationToken = tokenSource.token;
const createEntries = new Promise<QuickPickInput<ITaskQuickPickEntry>[]>((resolve) => {
@@ -2564,7 +2611,6 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
const picker: IQuickPick<ITaskQuickPickEntry> = this._quickInputService.createQuickPick();
picker.placeholder = placeHolder;
picker.matchOnDescription = true;
-
picker.onDidTriggerItemButton(context => {
const task = context.item.task;
this._quickInputService.cancel();
@@ -2580,7 +2626,9 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
picker.items = entries;
});
picker.show();
-
+ if (filter) {
+ picker.value = filter;
+ }
return new Promise<ITaskQuickPickEntry | undefined | null>(resolve => {
this._register(picker.onDidAccept(async () => {
let selection = picker.selectedItems ? picker.selectedItems[0] : undefined;
@@ -2654,12 +2702,20 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
})) === true;
}
- private _runTaskCommand(arg?: any): void {
+ private async _runTaskCommand(filter?: { type?: string; taskName?: string } | string): Promise<void> {
if (!this._canRunCommand()) {
return;
}
- const identifier = this._getTaskIdentifier(arg);
- if (identifier !== undefined) {
+
+ let typeFilter: boolean = false;
+ if (filter && typeof filter !== 'string') {
+ // name takes precedence
+ typeFilter = !filter?.taskName && !!filter?.type;
+ filter = filter?.taskName || filter?.type;
+ }
+
+ const taskIdentifier: KeyedTaskIdentifier | undefined | string = this._getTaskIdentifier(filter);
+ if (taskIdentifier) {
this._getGroupedTasks().then(async (grouped) => {
const resolver = this._createResolver(grouped);
const folderURIs: (URI | string)[] = this._contextService.getWorkspace().folders.map(folder => folder.uri);
@@ -2668,7 +2724,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
}
folderURIs.push(USER_TASKS_GROUP_KEY);
for (const uri of folderURIs) {
- const task = await resolver.resolve(uri, identifier);
+ const task = await resolver.resolve(uri, taskIdentifier);
if (task) {
this.run(task).then(undefined, reason => {
// eat the error, it has already been surfaced to the user and we don't care about it here
@@ -2676,7 +2732,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
return;
}
}
- this._doRunTaskCommand(grouped.all());
+ this._doRunTaskCommand(grouped.all(), typeof taskIdentifier === 'string' ? taskIdentifier : undefined, typeFilter);
}, () => {
this._doRunTaskCommand();
});
@@ -2716,7 +2772,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
return { tasks, grouped };
}
- private _doRunTaskCommand(tasks?: Task[]): void {
+ private _doRunTaskCommand(tasks?: Task[], filter?: string, typeFilter?: boolean): void {
const pickThen = (task: Task | undefined | null) => {
if (task === undefined) {
return;
@@ -2732,28 +2788,58 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
const placeholder = nls.localize('TaskService.pickRunTask', 'Select the task to run');
- this._showIgnoredFoldersMessage().then(() => {
+ this._showIgnoredFoldersMessage().then(async () => {
if (this._configurationService.getValue(USE_SLOW_PICKER)) {
let taskResult: { tasks: Promise<Task[]>; grouped: Promise<TaskMap> } | undefined = undefined;
if (!tasks) {
taskResult = this._tasksAndGroupedTasks();
}
+ if (filter && typeFilter) {
+ const picker: IQuickPick<ITaskTwoLevelQuickPickEntry> = this._quickInputService.createQuickPick();
+ picker.placeholder = nls.localize('TaskService.pickRunTask', 'Select the task to run');
+ picker.matchOnDescription = true;
+ picker.ignoreFocusOut = false;
+ const taskQuickPick = new TaskQuickPick(this, this._configurationService, this._quickInputService, this._notificationService, this._themeService, this._dialogService);
+ const result = await taskQuickPick.doPickerSecondLevel(picker, filter);
+ if (result?.task) {
+ pickThen(result.task as Task);
+ taskQuickPick.dispose();
+ }
+ return;
+ }
this._showQuickPick(tasks ? tasks : taskResult!.tasks, placeholder,
{
label: '$(plus) ' + nls.localize('TaskService.noEntryToRun', 'Configure a Task'),
task: null
},
- true).
+ true, false, undefined, undefined, typeof filter === 'string' ? filter : undefined).
then((entry) => {
return pickThen(entry ? entry.task : undefined);
});
} else {
- this._showTwoLevelQuickPick(placeholder,
- {
- label: '$(plus) ' + nls.localize('TaskService.noEntryToRun', 'Configure a Task'),
- task: null
- }).
- then(pickThen);
+ if (filter && typeFilter) {
+ const picker: IQuickPick<ITaskTwoLevelQuickPickEntry> = this._quickInputService.createQuickPick();
+ picker.placeholder = nls.localize('TaskService.pickRunTask', 'Select the task to run');
+ picker.matchOnDescription = true;
+ picker.ignoreFocusOut = false;
+ const taskQuickPick = new TaskQuickPick(this, this._configurationService, this._quickInputService, this._notificationService, this._themeService, this._dialogService);
+ const result = await taskQuickPick.doPickerSecondLevel(picker, filter);
+ if (result?.task) {
+ pickThen(result.task as Task);
+ picker.dispose();
+ taskQuickPick.dispose();
+ return;
+ } else {
+ return;
+ }
+ } else {
+ this._showTwoLevelQuickPick(placeholder,
+ {
+ label: '$(plus) ' + nls.localize('TaskService.noEntryToRun', 'Configure a Task'),
+ task: null
+ }, typeof filter === 'string' ? filter : undefined).
+ then(pickThen);
+ }
}
});
}
@@ -3055,7 +3141,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
}
}
- private _getTaskIdentifier(arg?: any): string | KeyedTaskIdentifier | undefined {
+ private _getTaskIdentifier(arg?: string | ITaskIdentifier): string | KeyedTaskIdentifier | undefined {
let result: string | KeyedTaskIdentifier | undefined = undefined;
if (Types.isString(arg)) {
result = arg;