Skip to content

Commit c892e65

Browse files
authored
Fix several AI settings search bugs (microsoft#250068)
1 parent c5816ba commit c892e65

File tree

5 files changed

+41
-36
lines changed

5 files changed

+41
-36
lines changed

src/vs/workbench/contrib/preferences/browser/preferencesSearch.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,8 @@ export class LocalSearchProvider implements ISearchProvider {
131131
const filteredMatches = filterMatches.filter(m => (m.matchType & topKeyMatchType) || (m.matchType & alwaysAllowedMatchTypes) || m.matchType === SettingMatchType.ExactMatch);
132132
return Promise.resolve({
133133
filterMatches: filteredMatches,
134-
exactMatch: filteredMatches.some(m => m.matchType === SettingMatchType.ExactMatch)
134+
exactMatch: filteredMatches.some(m => m.matchType === SettingMatchType.ExactMatch),
135+
providerName: 'local'
135136
});
136137
}
137138

src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -633,10 +633,11 @@ export class SettingsEditor2 extends EditorPane {
633633
const showSuggestions = this.configurationService.getValue<boolean>('workbench.settings.showAISearchToggle');
634634
if (!setupHidden && showSuggestions) {
635635
const showAiResultActionClassNames = ['action-label', ThemeIcon.asClassName(preferencesAiResultsIcon)];
636+
const searchServiceEnabled = this.aiSettingsSearchService.isEnabled();
636637
this.showAiResultsAction = this._register(new Action(SETTINGS_EDITOR_COMMAND_SHOW_AI_RESULTS,
637-
localize('showAiResultsDescription', "Search settings with AI"), showAiResultActionClassNames.join(' '), false
638+
localize('showAiResultsDescription', "Search settings with AI"), showAiResultActionClassNames.join(' '), searchServiceEnabled
638639
));
639-
this._register(this.aiSettingsSearchService.onDidEnable(() => {
640+
this._register(this.aiSettingsSearchService.onProviderRegistered(() => {
640641
this.showAiResultsAction!.enabled = true;
641642
}));
642643
this._register(this.showAiResultsAction.onDidChange(() => {

src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -919,7 +919,7 @@ export const enum SearchResultIdx {
919919

920920
export class SearchResultModel extends SettingsTreeModel {
921921
private rawSearchResults: ISearchResult[] | null = null;
922-
private cachedUniqueSearchResults: ISearchResult | null = null;
922+
private cachedUniqueSearchResults: Map<boolean, ISearchResult | null>;
923923
private newExtensionSearchResults: ISearchResult | null = null;
924924
private searchResultCount: number | null = null;
925925
private settingsOrderByTocIndex: Map<string, number> | null;
@@ -939,11 +939,13 @@ export class SearchResultModel extends SettingsTreeModel {
939939
) {
940940
super(viewState, isWorkspaceTrusted, configurationService, languageService, userDataProfileService, productService);
941941
this.settingsOrderByTocIndex = settingsOrderByTocIndex;
942+
this.cachedUniqueSearchResults = new Map();
942943
this.update({ id: 'searchResultModel', label: '' });
943944
}
944945

945946
set showAiResults(show: boolean) {
946947
this.aiFilterEnabled = show;
948+
this.updateChildren();
947949
}
948950

949951
private sortResults(filterMatches: ISettingMatch[]): ISettingMatch[] {
@@ -986,8 +988,9 @@ export class SearchResultModel extends SettingsTreeModel {
986988
}
987989

988990
getUniqueSearchResults(): ISearchResult | null {
989-
if (this.cachedUniqueSearchResults) {
990-
return this.cachedUniqueSearchResults;
991+
const cachedResults = this.cachedUniqueSearchResults.get(this.aiFilterEnabled);
992+
if (cachedResults) {
993+
return cachedResults;
991994
}
992995

993996
if (!this.rawSearchResults) {
@@ -1009,33 +1012,35 @@ export class SearchResultModel extends SettingsTreeModel {
10091012
embeddingsResult.filterMatches = embeddingsResult.filterMatches.filter(m => !aiSelectedKeys.has(m.setting.key));
10101013
combinedFilterMatches = combinedFilterMatches.concat(embeddingsResult.filterMatches);
10111014
}
1012-
this.cachedUniqueSearchResults = {
1015+
const result = {
10131016
filterMatches: combinedFilterMatches,
10141017
exactMatch: false
10151018
};
1016-
} else {
1017-
const localMatchKeys = new Set<string>();
1018-
const localResult = this.rawSearchResults[SearchResultIdx.Local];
1019-
if (localResult) {
1020-
localResult.filterMatches.forEach(m => localMatchKeys.add(m.setting.key));
1021-
combinedFilterMatches = localResult.filterMatches;
1022-
}
1023-
1024-
const remoteResult = this.rawSearchResults[SearchResultIdx.Remote];
1025-
if (remoteResult) {
1026-
remoteResult.filterMatches = remoteResult.filterMatches.filter(m => !localMatchKeys.has(m.setting.key));
1027-
combinedFilterMatches = combinedFilterMatches.concat(remoteResult.filterMatches);
1019+
this.cachedUniqueSearchResults.set(true, result);
1020+
return result;
1021+
}
10281022

1029-
this.newExtensionSearchResults = this.rawSearchResults[SearchResultIdx.NewExtensions];
1030-
}
1031-
combinedFilterMatches = this.sortResults(combinedFilterMatches);
1032-
this.cachedUniqueSearchResults = {
1033-
filterMatches: combinedFilterMatches,
1034-
exactMatch: localResult.exactMatch // remote results should never have an exact match
1035-
};
1023+
const localMatchKeys = new Set<string>();
1024+
const localResult = this.rawSearchResults[SearchResultIdx.Local];
1025+
if (localResult) {
1026+
localResult.filterMatches.forEach(m => localMatchKeys.add(m.setting.key));
1027+
combinedFilterMatches = localResult.filterMatches;
10361028
}
10371029

1038-
return this.cachedUniqueSearchResults;
1030+
const remoteResult = this.rawSearchResults[SearchResultIdx.Remote];
1031+
if (remoteResult) {
1032+
remoteResult.filterMatches = remoteResult.filterMatches.filter(m => !localMatchKeys.has(m.setting.key));
1033+
combinedFilterMatches = combinedFilterMatches.concat(remoteResult.filterMatches);
1034+
1035+
this.newExtensionSearchResults = this.rawSearchResults[SearchResultIdx.NewExtensions];
1036+
}
1037+
combinedFilterMatches = this.sortResults(combinedFilterMatches);
1038+
const result = {
1039+
filterMatches: combinedFilterMatches,
1040+
exactMatch: localResult.exactMatch // remote results should never have an exact match
1041+
};
1042+
this.cachedUniqueSearchResults.set(false, result);
1043+
return result;
10391044
}
10401045

10411046
getRawResults(): ISearchResult[] {
@@ -1089,7 +1094,7 @@ export class SearchResultModel extends SettingsTreeModel {
10891094
}
10901095

10911096
setResult(order: SearchResultIdx, result: ISearchResult | null): void {
1092-
this.cachedUniqueSearchResults = null;
1097+
this.cachedUniqueSearchResults.clear();
10931098
this.newExtensionSearchResults = null;
10941099

10951100
this.rawSearchResults ??= [];

src/vs/workbench/services/aiSettingsSearch/common/aiSettingsSearch.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export interface AiSettingsSearchProviderOptions {
2929

3030
export interface IAiSettingsSearchService {
3131
readonly _serviceBrand: undefined;
32-
readonly onDidEnable: Event<void>;
32+
readonly onProviderRegistered: Event<void>;
3333

3434
// Called from the Settings editor
3535
isEnabled(): boolean;

src/vs/workbench/services/aiSettingsSearch/common/aiSettingsSearchService.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,30 +6,28 @@
66
import { DeferredPromise, raceCancellation } from '../../../../base/common/async.js';
77
import { CancellationToken } from '../../../../base/common/cancellation.js';
88
import { Emitter, Event } from '../../../../base/common/event.js';
9-
import { IDisposable } from '../../../../base/common/lifecycle.js';
9+
import { Disposable, IDisposable } from '../../../../base/common/lifecycle.js';
1010
import { InstantiationType, registerSingleton } from '../../../../platform/instantiation/common/extensions.js';
1111
import { AiSettingsSearchResult, AiSettingsSearchResultKind, IAiSettingsSearchProvider, IAiSettingsSearchService } from './aiSettingsSearch.js';
1212

13-
export class AiSettingsSearchService implements IAiSettingsSearchService {
13+
export class AiSettingsSearchService extends Disposable implements IAiSettingsSearchService {
1414
readonly _serviceBrand: undefined;
1515
private static readonly MAX_PICKS = 5;
1616

1717
private _providers: IAiSettingsSearchProvider[] = [];
1818
private _llmRankedResultsPromises: Map<string, DeferredPromise<string[]>> = new Map();
1919
private _embeddingsResultsPromises: Map<string, DeferredPromise<string[]>> = new Map();
2020

21-
private _onDidEnable: Emitter<void> = new Emitter<void>();
22-
readonly onDidEnable: Event<void> = this._onDidEnable.event;
21+
private _onProviderRegistered: Emitter<void> = this._register(new Emitter<void>());
22+
readonly onProviderRegistered: Event<void> = this._onProviderRegistered.event;
2323

2424
isEnabled(): boolean {
2525
return this._providers.length > 0;
2626
}
2727

2828
registerSettingsSearchProvider(provider: IAiSettingsSearchProvider): IDisposable {
2929
this._providers.push(provider);
30-
if (this._providers.length === 1) {
31-
this._onDidEnable.fire();
32-
}
30+
this._onProviderRegistered.fire();
3331
return {
3432
dispose: () => {
3533
const index = this._providers.indexOf(provider);

0 commit comments

Comments
 (0)