Merge from vscode e5834d3280fcd04898efeac32b9cf1b893f9b127 (#9385)

* Merge from vscode e5834d3280fcd04898efeac32b9cf1b893f9b127

* distro
This commit is contained in:
Anthony Dresser
2020-02-28 00:37:06 -08:00
committed by GitHub
parent 70851716f7
commit 5d13ebf0d2
143 changed files with 1711 additions and 934 deletions

View File

@@ -63,7 +63,7 @@ import { getTemplates as getTaskTemplates } from 'vs/workbench/contrib/tasks/com
import * as TaskConfig from '../common/taskConfiguration';
import { TerminalTaskSystem } from './terminalTaskSystem';
import { IQuickInputService, IQuickPickItem, QuickPickInput } from 'vs/platform/quickinput/common/quickInput';
import { IQuickInputService, IQuickPickItem, QuickPickInput, IQuickPick } from 'vs/platform/quickinput/common/quickInput';
import { TaskDefinitionRegistry } from 'vs/workbench/contrib/tasks/common/taskDefinitionRegistry';
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
@@ -80,6 +80,7 @@ import { IPreferencesService } from 'vs/workbench/services/preferences/common/pr
import { find } from 'vs/base/common/arrays';
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
import { IViewsService } from 'vs/workbench/common/views';
import { ProviderProgressMananger } from 'vs/workbench/contrib/tasks/browser/providerProgressManager';
const QUICKOPEN_HISTORY_LIMIT_CONFIG = 'task.quickOpen.history';
const QUICKOPEN_DETAIL_CONFIG = 'task.quickOpen.detail';
@@ -218,6 +219,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
private _providers: Map<number, ITaskProvider>;
private _providerTypes: Map<number, string>;
protected _taskSystemInfos: Map<string, TaskSystemInfo>;
private _providerProgressManager: ProviderProgressMananger | undefined;
protected _workspaceTasksPromise?: Promise<Map<string, WorkspaceFolderTaskResult>>;
protected _areJsonTasksSupportedPromise: Promise<boolean> = Promise.resolve(false);
@@ -560,6 +562,37 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
protected abstract versionAndEngineCompatible(filter?: TaskFilter): boolean;
private tasksAndGroupedTasks(filter?: TaskFilter): { tasks: Promise<Task[]>, grouped: Promise<TaskMap> } {
if (!this.versionAndEngineCompatible(filter)) {
return { tasks: Promise.resolve<Task[]>([]), grouped: Promise.resolve(new TaskMap()) };
}
const grouped = this.getGroupedTasks(filter ? filter.type : undefined);
const tasks = grouped.then((map) => {
if (!filter || !filter.type) {
return map.all();
}
let result: Task[] = [];
map.forEach((tasks) => {
for (let task of tasks) {
if (ContributedTask.is(task) && task.defines.type === filter.type) {
result.push(task);
} else if (CustomTask.is(task)) {
if (task.type === filter.type) {
result.push(task);
} else {
let customizes = task.customizes();
if (customizes && customizes.type === filter.type) {
result.push(task);
}
}
}
}
});
return result;
});
return { tasks, grouped };
}
public tasks(filter?: TaskFilter): Promise<Task[]> {
if (!this.versionAndEngineCompatible(filter)) {
return Promise.resolve<Task[]>([]);
@@ -703,11 +736,11 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
});
}
public run(task: Task | undefined, options?: ProblemMatcherRunOptions, runSource: TaskRunSource = TaskRunSource.System): Promise<ITaskSummary | undefined> {
public run(task: Task | undefined, options?: ProblemMatcherRunOptions, runSource: TaskRunSource = TaskRunSource.System, grouped?: Promise<TaskMap>): Promise<ITaskSummary | undefined> {
if (!task) {
throw new TaskError(Severity.Info, nls.localize('TaskServer.noTask', 'Task to execute is undefined'), TaskErrors.TaskNotFound);
}
return this.getGroupedTasks().then((grouped) => {
return (grouped ?? this.getGroupedTasks()).then((grouped) => {
let resolver = this.createResolver(grouped);
if (options && options.attachProblemMatcher && this.shouldAttachProblemMatcher(task) && !InMemoryTask.is(task)) {
return this.attachProblemMatcher(task).then((toExecute) => {
@@ -1345,11 +1378,24 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
protected abstract getTaskSystem(): ITaskSystem;
private async provideTasksWithWarning(provider: ITaskProvider, type: string, validTypes: IStringDictionary<boolean>): Promise<TaskSet> {
private async provideTasksWithWarning(provider: ITaskProvider, type: string, validTypes: IStringDictionary<boolean>): Promise<TaskSet | undefined> {
return new Promise<TaskSet>(async (resolve, reject) => {
provider.provideTasks(validTypes).then((value) => {
let isDone = false;
let disposable: IDisposable | undefined;
const providePromise = provider.provideTasks(validTypes);
this._providerProgressManager?.addProvider(type, providePromise);
disposable = this._providerProgressManager?.canceled.token.onCancellationRequested(() => {
if (!isDone) {
resolve();
}
});
providePromise.then((value) => {
isDone = true;
disposable?.dispose();
resolve(value);
}, (e) => {
isDone = true;
disposable?.dispose();
reject(e);
});
});
@@ -1361,10 +1407,11 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
TaskDefinitionRegistry.all().forEach(definition => validTypes[definition.taskType] = true);
validTypes['shell'] = true;
validTypes['process'] = true;
this._providerProgressManager = new ProviderProgressMananger();
return new Promise<TaskSet[]>(resolve => {
let result: TaskSet[] = [];
let counter: number = 0;
let done = (value: TaskSet) => {
let done = (value: TaskSet | undefined) => {
if (value) {
result.push(value);
}
@@ -2060,30 +2107,69 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
}
return entries;
});
return this.quickInputService.pick(pickEntries, {
placeHolder,
matchOnDescription: true,
onDidTriggerItemButton: context => {
let task = context.item.task;
this.quickInputService.cancel();
if (ContributedTask.is(task)) {
this.customize(task, undefined, true);
} else if (CustomTask.is(task)) {
this.openConfig(task);
const picker: IQuickPick<TaskQuickPickEntry> = this.quickInputService.createQuickPick();
picker.placeholder = placeHolder;
picker.matchOnDescription = true;
picker.ignoreFocusOut = true;
picker.onDidTriggerItemButton(context => {
let task = context.item.task;
this.quickInputService.cancel();
if (ContributedTask.is(task)) {
this.customize(task, undefined, true);
} else if (CustomTask.is(task)) {
this.openConfig(task);
}
});
picker.busy = true;
const progressManager = this._providerProgressManager;
const progressTimeout = setTimeout(() => {
if (progressManager) {
progressManager.showProgress = (stillProviding, total) => {
let message = undefined;
if (stillProviding.length > 0) {
message = nls.localize('pickProgressManager.description', 'Detecting tasks ({0} of {1}): {2} in progress', total - stillProviding.length, total, stillProviding.join(', '));
}
picker.description = message;
};
progressManager.addOnDoneListener(() => {
picker.focusOnInput();
picker.customButton = false;
});
if (!progressManager.isDone) {
picker.customLabel = nls.localize('taskQuickPick.cancel', "Stop detecting");
picker.onDidCustom(() => {
this._providerProgressManager?.cancel();
});
picker.customButton = true;
}
}
}, cancellationToken).then(async (selection) => {
if (cancellationToken.isCancellationRequested) {
// canceled when there's only one task
const task = (await pickEntries)[0];
if ((<any>task).task) {
selection = <TaskQuickPickEntry>task;
}, 1000);
pickEntries.then(entries => {
clearTimeout(progressTimeout);
progressManager?.dispose();
picker.busy = false;
picker.items = entries;
});
picker.show();
return new Promise<TaskQuickPickEntry | undefined | null>(resolve => {
this._register(picker.onDidAccept(async () => {
let selection = picker.selectedItems ? picker.selectedItems[0] : undefined;
if (cancellationToken.isCancellationRequested) {
// canceled when there's only one task
const task = (await pickEntries)[0];
if ((<any>task).task) {
selection = <TaskQuickPickEntry>task;
}
}
}
if (!selection) {
return undefined; // {{SQL CARBON EDIT}} strict-null-checks
}
return selection;
picker.dispose();
if (!selection) {
resolve();
}
resolve(selection);
}));
});
}
@@ -2138,7 +2224,11 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
private doRunTaskCommand(tasks?: Task[]): void {
this.showIgnoredFoldersMessage().then(() => {
this.showQuickPick(tasks ? tasks : this.tasks(),
let taskResult: { tasks: Promise<Task[]>, grouped: Promise<TaskMap> } | undefined = undefined;
if (!tasks) {
taskResult = this.tasksAndGroupedTasks();
}
this.showQuickPick(tasks ? tasks : taskResult!.tasks,
nls.localize('TaskService.pickRunTask', 'Select the task to run'),
{
label: nls.localize('TaskService.noEntryToRun', 'No task to run found. Configure Tasks...'),
@@ -2153,7 +2243,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
if (task === null) {
this.runConfigureTasks();
} else {
this.run(task, { attachProblemMatcher: true }, TaskRunSource.User).then(undefined, reason => {
this.run(task, { attachProblemMatcher: true }, TaskRunSource.User, taskResult?.grouped).then(undefined, reason => {
// eat the error, it has already been surfaced to the user and we don't care about it here
});
}