diff --git a/src/vs/base/parts/quickinput/browser/quickInput.ts b/src/vs/base/parts/quickinput/browser/quickInput.ts index 059eb29406d3eb997ccceb82cf1756297c7f6294..afb94d703957e298de53875f83f06eeb233c70f7 100644 --- a/src/vs/base/parts/quickinput/browser/quickInput.ts +++ b/src/vs/base/parts/quickinput/browser/quickInput.ts @@ -575,10 +575,6 @@ class QuickPick extends QuickInput implements IQuickPi return this.visible ? this.ui.inputBox.hasFocus() : false; } - public focusOnInput() { - this.ui.inputBox.setFocus(); - } - onDidChangeSelection = this.onDidChangeSelectionEmitter.event; onDidTriggerItemButton = this.onDidTriggerItemButtonEmitter.event; diff --git a/src/vs/base/parts/quickinput/common/quickInput.ts b/src/vs/base/parts/quickinput/common/quickInput.ts index 5640fecc09bc49ec3644d0af3fdc6bf71b508590..8cbf10553e75891a0372bdf1563ec94379e78244 100644 --- a/src/vs/base/parts/quickinput/common/quickInput.ts +++ b/src/vs/base/parts/quickinput/common/quickInput.ts @@ -209,8 +209,6 @@ export interface IQuickPick extends IQuickInput { validationMessage: string | undefined; inputHasFocus(): boolean; - - focusOnInput(): void; } export interface IInputBox extends IQuickInput { diff --git a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts index 9fef6bbe46ee0febc145e9ffa5f7aef33f92133d..d5321cc69450ad5c5f1823cc2804b0554c461851 100644 --- a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts +++ b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts @@ -34,7 +34,7 @@ import { IProgressService, IProgressOptions, ProgressLocation } from 'vs/platfor import { IOpenerService } from 'vs/platform/opener/common/opener'; import { IHostService } from 'vs/workbench/services/host/browser/host'; -import { INotificationService } from 'vs/platform/notification/common/notification'; +import { INotificationService, IPromptChoice } from 'vs/platform/notification/common/notification'; import { IDialogService, IConfirmationResult } from 'vs/platform/dialogs/common/dialogs'; import { IModelService } from 'vs/editor/common/services/modelService'; @@ -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, IQuickPick } from 'vs/platform/quickinput/common/quickInput'; +import { IQuickInputService, IQuickPickItem, QuickPickInput } 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,7 +80,6 @@ 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'; @@ -221,7 +220,6 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer private _providers: Map; private _providerTypes: Map; protected _taskSystemInfos: Map; - private _providerProgressManager: ProviderProgressMananger | undefined; protected _workspaceTasksPromise?: Promise>; protected _areJsonTasksSupportedPromise: Promise = Promise.resolve(false); @@ -1349,26 +1347,36 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer protected abstract getTaskSystem(): ITaskSystem; - private async provideTasksWithWarning(provider: ITaskProvider, type: string, validTypes: IStringDictionary): Promise { + private async provideTasksWithWarning(provider: ITaskProvider, type: string, validTypes: IStringDictionary): Promise { return new Promise(async (resolve, reject) => { 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) => { + provider.provideTasks(validTypes).then((value) => { isDone = true; - disposable?.dispose(); resolve(value); }, (e) => { isDone = true; - disposable?.dispose(); reject(e); }); + let settingValue: boolean | string[] = this.configurationService.getValue('task.slowProviderWarning'); + if ((settingValue === true) || (Types.isStringArray(settingValue) && (settingValue.indexOf(type) < 0))) { + setTimeout(() => { + if (!isDone) { + const settings: IPromptChoice = { label: nls.localize('TaskSystem.slowProvider.settings', "Settings"), run: () => this.preferencesService.openSettings(false, undefined) }; + const disableAll: IPromptChoice = { label: nls.localize('TaskSystem.slowProvider.disableAll', "Disable All"), run: () => this.configurationService.updateValue('task.autoDetect', 'off') }; + const dontShow: IPromptChoice = { + label: nls.localize('TaskSystem.slowProvider.dontShow', "Don't warn again for {0} tasks", type), run: () => { + if (!Types.isStringArray(settingValue)) { + settingValue = []; + } + settingValue.push(type); + return this.configurationService.updateValue('task.slowProviderWarning', settingValue); + } + }; + this.notificationService.prompt(Severity.Warning, nls.localize('TaskSystem.slowProvider', "The {0} task provider is slow. The extension that provides {0} tasks may provide a setting to disable it, or you can disable all tasks providers", type), + [settings, disableAll, dontShow]); + } + }, 4000); + } }); } @@ -1378,11 +1386,10 @@ 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(resolve => { let result: TaskSet[] = []; let counter: number = 0; - let done = (value: TaskSet | undefined) => { + let done = (value: TaskSet) => { if (value) { result.push(value); } @@ -2078,69 +2085,30 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer } return entries; }); - - const picker: IQuickPick = 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; - } + 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); + } + } + }, cancellationToken).then(async (selection) => { + if (cancellationToken.isCancellationRequested) { + // canceled when there's only one task + const task = (await pickEntries)[0]; + if ((task).task) { + selection = task; + } + } + if (!selection) { + return; } - }, 1000); - pickEntries.then(entries => { - clearTimeout(progressTimeout); - progressManager?.dispose(); - picker.busy = false; - picker.items = entries; - }); - picker.show(); - - return new Promise(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 ((task).task) { - selection = task; - } - } - picker.dispose(); - if (!selection) { - resolve(); - } - resolve(selection); - })); + return selection; }); } diff --git a/src/vs/workbench/contrib/tasks/browser/providerProgressManager.ts b/src/vs/workbench/contrib/tasks/browser/providerProgressManager.ts deleted file mode 100644 index 7c48da7f73cc7801967950f5c31aab27a1566b4d..0000000000000000000000000000000000000000 --- a/src/vs/workbench/contrib/tasks/browser/providerProgressManager.ts +++ /dev/null @@ -1,61 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { TaskSet } from 'vs/workbench/contrib/tasks/common/tasks'; -import { Emitter } from 'vs/base/common/event'; -import { Disposable } from 'vs/base/common/lifecycle'; -import { CancellationTokenSource } from 'vs/base/common/cancellation'; - -export class ProviderProgressMananger extends Disposable { - private _onProviderComplete: Emitter = new Emitter(); - private _stillProviding: Set = new Set(); - private _totalProviders: number = 0; - private _onDone: Emitter = new Emitter(); - private _isDone: boolean = false; - private _showProgress: ((remaining: string[], total: number) => void) | undefined; - public canceled: CancellationTokenSource = new CancellationTokenSource(); - - constructor() { - super(); - this._register(this._onProviderComplete.event(taskType => { - this._stillProviding.delete(taskType); - if (this._stillProviding.size === 0) { - this._isDone = true; - this._onDone.fire(); - } - if (this._showProgress) { - this._showProgress(Array.from(this._stillProviding), this._totalProviders); - } - })); - } - - public addProvider(taskType: string, provider: Promise) { - this._totalProviders++; - this._stillProviding.add(taskType); - provider.then(() => this._onProviderComplete.fire(taskType)); - } - - public addOnDoneListener(onDoneListener: () => void) { - this._register(this._onDone.event(onDoneListener)); - } - - set showProgress(progressDisplayFunction: (remaining: string[], total: number) => void) { - this._showProgress = progressDisplayFunction; - this._showProgress(Array.from(this._stillProviding), this._totalProviders); - } - - get isDone(): boolean { - return this._isDone; - } - - public cancel() { - this._isDone = true; - if (this._showProgress) { - this._showProgress([], 0); - } - this._onDone.fire(); - this.canceled.cancel(); - } -}