Merge from vscode 61d5f2b82f17bf9f99f56405204caab88a7e8747

This commit is contained in:
ADS Merger
2020-03-19 06:57:07 +00:00
parent 03ce5d1ba7
commit 84f67f61c4
137 changed files with 13234 additions and 796 deletions

View File

@@ -5,7 +5,7 @@
import { localize } from 'vs/nls';
import { IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput';
import { PickerQuickAccessProvider, IPickerQuickAccessItem } from 'vs/platform/quickinput/browser/pickerQuickAccess';
import { PickerQuickAccessProvider, IPickerQuickAccessItem, IPickerQuickAccessProviderOptions } from 'vs/platform/quickinput/browser/pickerQuickAccess';
import { distinct } from 'vs/base/common/arrays';
import { CancellationToken } from 'vs/base/common/cancellation';
import { DisposableStore, Disposable, IDisposable } from 'vs/base/common/lifecycle';
@@ -30,7 +30,7 @@ export interface ICommandQuickPick extends IPickerQuickAccessItem {
commandAlias: string | undefined;
}
export interface ICommandsQuickAccessOptions {
export interface ICommandsQuickAccessOptions extends IPickerQuickAccessProviderOptions {
showAlias: boolean;
}
@@ -43,14 +43,14 @@ export abstract class AbstractCommandsQuickAccessProvider extends PickerQuickAcc
private readonly commandsHistory = this._register(this.instantiationService.createInstance(CommandsHistory));
constructor(
private options: ICommandsQuickAccessOptions,
protected options: ICommandsQuickAccessOptions,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IKeybindingService private readonly keybindingService: IKeybindingService,
@ICommandService private readonly commandService: ICommandService,
@ITelemetryService private readonly telemetryService: ITelemetryService,
@INotificationService private readonly notificationService: INotificationService
) {
super(AbstractCommandsQuickAccessProvider.PREFIX);
super(AbstractCommandsQuickAccessProvider.PREFIX, options);
}
protected async getPicks(filter: string, disposables: DisposableStore, token: CancellationToken): Promise<Array<ICommandQuickPick | IQuickPickSeparator>> {

View File

@@ -8,6 +8,7 @@ import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cance
import { IQuickPickSeparator, IKeyMods, IQuickPickAcceptEvent } from 'vs/base/parts/quickinput/common/quickInput';
import { IQuickAccessProvider } from 'vs/platform/quickinput/common/quickAccess';
import { IDisposable, DisposableStore, Disposable } from 'vs/base/common/lifecycle';
import { timeout } from 'vs/base/common/async';
export enum TriggerAction {
@@ -53,17 +54,31 @@ export interface IPickerQuickAccessItem extends IQuickPickItem {
trigger?(buttonIndex: number, keyMods: IKeyMods): TriggerAction | Promise<TriggerAction>;
}
export interface IPickerQuickAccessProviderOptions {
canAcceptInBackground?: boolean;
}
export type FastAndSlowPicksType<T> = { picks: Array<T | IQuickPickSeparator>, additionalPicks: Promise<Array<T | IQuickPickSeparator>> };
function isFastAndSlowPicksType<T>(obj: unknown): obj is FastAndSlowPicksType<T> {
const candidate = obj as FastAndSlowPicksType<T>;
return Array.isArray(candidate.picks) && candidate.additionalPicks instanceof Promise;
}
export abstract class PickerQuickAccessProvider<T extends IPickerQuickAccessItem> extends Disposable implements IQuickAccessProvider {
constructor(private prefix: string) {
private static FAST_PICKS_RACE_DELAY = 200; // timeout before we accept fast results before slow results are present
constructor(private prefix: string, protected options?: IPickerQuickAccessProviderOptions) {
super();
}
provide(picker: IQuickPick<T>, token: CancellationToken): IDisposable {
const disposables = new DisposableStore();
// Allow subclasses to configure picker
this.configure(picker);
// Apply options if any
picker.canAcceptInBackground = !!this.options?.canAcceptInBackground;
// Disable filtering & sorting, we control the results
picker.matchOnLabel = picker.matchOnDescription = picker.matchOnDetail = picker.sortByLabel = false;
@@ -79,21 +94,77 @@ export abstract class PickerQuickAccessProvider<T extends IPickerQuickAccessItem
// Create new cancellation source for this run
picksCts = new CancellationTokenSource(token);
// Collect picks and support both long running and short
const res = this.getPicks(picker.value.substr(this.prefix.length).trim(), disposables.add(new DisposableStore()), picksCts.token);
if (Array.isArray(res)) {
// Collect picks and support both long running and short or combined
const picksToken = picksCts.token;
const res = this.getPicks(picker.value.substr(this.prefix.length).trim(), disposables.add(new DisposableStore()), picksToken);
if (isFastAndSlowPicksType(res)) {
let fastPicksHandlerDone = false;
let slowPicksHandlerDone = false;
await Promise.all([
// Fast Picks: to reduce amount of flicker, we race against
// the slow picks over 500ms and then set the fast picks.
// If the slow picks are faster, we reduce the flicker by
// only setting the items once.
(async () => {
try {
await timeout(PickerQuickAccessProvider.FAST_PICKS_RACE_DELAY);
if (picksToken.isCancellationRequested) {
return;
}
if (!slowPicksHandlerDone) {
picker.items = res.picks;
}
} finally {
fastPicksHandlerDone = true;
}
})(),
// Slow Picks: we await the slow picks and then set them at
// once together with the fast picks, but only if we actually
// have additional results.
(async () => {
picker.busy = true;
try {
const additionalPicks = await res.additionalPicks;
if (picksToken.isCancellationRequested) {
return;
}
if (additionalPicks.length > 0 || !fastPicksHandlerDone) {
picker.items = [...res.picks, ...additionalPicks];
}
} finally {
if (!picksToken.isCancellationRequested) {
picker.busy = false;
}
slowPicksHandlerDone = true;
}
})()
]);
}
// Fast Picks
else if (Array.isArray(res)) {
picker.items = res;
} else {
}
// Slow Picks
else {
picker.busy = true;
try {
const items = await res;
if (token.isCancellationRequested) {
if (picksToken.isCancellationRequested) {
return;
}
picker.items = items;
} finally {
if (!token.isCancellationRequested) {
if (!picksToken.isCancellationRequested) {
picker.busy = false;
}
}
@@ -142,13 +213,6 @@ export abstract class PickerQuickAccessProvider<T extends IPickerQuickAccessItem
return disposables;
}
/**
* Subclasses can override this method to configure the picker before showing it.
*
* @param picker the picker instance used for the quick access before it opens.
*/
protected configure(picker: IQuickPick<T>): void { }
/**
* Returns an array of picks and separators as needed. If the picks are resolved
* long running, the provided cancellation token should be used to cancel the
@@ -162,6 +226,7 @@ export abstract class PickerQuickAccessProvider<T extends IPickerQuickAccessItem
* up when the picker closes.
* @param token for long running tasks, implementors need to check on cancellation
* through this token.
* @returns the picks either directly, as promise or combined fast and slow results.
*/
protected abstract getPicks(filter: string, disposables: DisposableStore, token: CancellationToken): Array<T | IQuickPickSeparator> | Promise<Array<T | IQuickPickSeparator>>;
protected abstract getPicks(filter: string, disposables: DisposableStore, token: CancellationToken): Array<T | IQuickPickSeparator> | Promise<Array<T | IQuickPickSeparator>> | FastAndSlowPicksType<T>;
}