diff --git a/src/vs/workbench/parts/preferences/browser/settingsEditor2.ts b/src/vs/workbench/parts/preferences/browser/settingsEditor2.ts index 5dfc89b2d30f6e7cfe5e9ff4d48b0aa035623e64..74c5e53e7ec55ab60c10fb157f9ec39fa6467016 100644 --- a/src/vs/workbench/parts/preferences/browser/settingsEditor2.ts +++ b/src/vs/workbench/parts/preferences/browser/settingsEditor2.ts @@ -56,6 +56,7 @@ export class SettingsEditor2 extends BaseEditor { private delayedFilterLogging: Delayer; private localSearchDelayer: Delayer; private remoteSearchThrottle: ThrottledDelayer; + private searchInProgress: TPromise; private pendingSettingModifiedReport: { key: string, value: any }; @@ -424,14 +425,18 @@ export class SettingsEditor2 extends BaseEditor { private triggerSearch(query: string): TPromise { if (query) { - return TPromise.join([ + return this.searchInProgress = TPromise.join([ this.localSearchDelayer.trigger(() => this.localFilterPreferences(query)), this.remoteSearchThrottle.trigger(() => this.remoteSearchPreferences(query), 500) - ]) as TPromise; + ]).then(() => { + this.searchInProgress = null; + }); } else { - // When clearing the input, update immediately to clear it this.localSearchDelayer.cancel(); this.remoteSearchThrottle.cancel(); + if (this.searchInProgress && this.searchInProgress.cancel) { + this.searchInProgress.cancel(); + } this.searchResultModel = null; this.settingsTree.setInput(this.defaultSettingsEditorModel); @@ -495,15 +500,25 @@ export class SettingsEditor2 extends BaseEditor { private filterOrSearchPreferences(query: string, type: SearchResultIdx, searchProvider: ISearchProvider): TPromise { const filterPs: TPromise[] = [this._filterOrSearchPreferencesModel(query, this.defaultSettingsEditorModel, searchProvider)]; - return TPromise.join(filterPs).then(results => { - const [result] = results; - if (!this.searchResultModel) { - this.searchResultModel = new SearchResultModel(); - this.settingsTree.setInput(this.searchResultModel); - } + let isCanceled = false; + return new TPromise(resolve => { + return TPromise.join(filterPs).then(results => { + if (isCanceled) { + // Handle cancellation like this because cancellation is lost inside the search provider due to async/await + return null; + } + + const [result] = results; + if (!this.searchResultModel) { + this.searchResultModel = new SearchResultModel(); + this.settingsTree.setInput(this.searchResultModel); + } - this.searchResultModel.setResult(type, result); - return this.refreshTreeAndMaintainFocus(); + this.searchResultModel.setResult(type, result); + resolve(this.refreshTreeAndMaintainFocus()); + }); + }, () => { + isCanceled = true; }); }