Skip to content

Commit

Permalink
Adopt new internal Search query shapes for new API shape (#214041)
Browse files Browse the repository at this point in the history
Creating `New` versions of all Search APIs (ie: `TextSearchProviderNew`) to support the new API shape.

Since this new shape requires a new internal query shape, this is quite a big change.
  • Loading branch information
andreamah committed Aug 16, 2024
1 parent 48bf32d commit c5ef039
Show file tree
Hide file tree
Showing 28 changed files with 1,469 additions and 771 deletions.
11 changes: 6 additions & 5 deletions src/vs/workbench/api/common/extHost.api.impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,8 @@ import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/c
import { UIKind } from 'vs/workbench/services/extensions/common/extensionHostProtocol';
import { checkProposedApiEnabled, isProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
import { ProxyIdentifier } from 'vs/workbench/services/extensions/common/proxyIdentifier';
import { ExcludeSettingOptions, TextSearchCompleteMessageType, TextSearchCompleteMessageTypeNew, TextSearchContextNew, TextSearchMatchNew, oldToNewTextSearchResult } from 'vs/workbench/services/search/common/searchExtTypes';
import { oldToNewTextSearchResult } from 'vs/workbench/services/search/common/searchExtConversionTypes';
import { ExcludeSettingOptions, TextSearchCompleteMessageType, TextSearchContextNew, TextSearchMatchNew } from 'vs/workbench/services/search/common/searchExtTypes';
import type * as vscode from 'vscode';

export interface IExtensionRegistries {
Expand Down Expand Up @@ -1186,17 +1187,17 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
},
registerFileSearchProvider: (scheme: string, provider: vscode.FileSearchProvider) => {
checkProposedApiEnabled(extension, 'fileSearchProvider');
return extHostSearch.registerFileSearchProvider(scheme, provider);
return extHostSearch.registerFileSearchProviderOld(scheme, provider);
},
registerTextSearchProvider: (scheme: string, provider: vscode.TextSearchProvider) => {
checkProposedApiEnabled(extension, 'textSearchProvider');
return extHostSearch.registerTextSearchProvider(scheme, provider);
return extHostSearch.registerTextSearchProviderOld(scheme, provider);
},
registerAITextSearchProvider: (scheme: string, provider: vscode.AITextSearchProvider) => {
// there are some dependencies on textSearchProvider, so we need to check for both
checkProposedApiEnabled(extension, 'aiTextSearchProvider');
checkProposedApiEnabled(extension, 'textSearchProvider');
return extHostSearch.registerAITextSearchProvider(scheme, provider);
return extHostSearch.registerAITextSearchProviderOld(scheme, provider);
},
registerFileSearchProviderNew: (scheme: string, provider: vscode.FileSearchProviderNew) => {
checkProposedApiEnabled(extension, 'fileSearchProviderNew');
Expand Down Expand Up @@ -1839,7 +1840,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
ExcludeSettingOptions: ExcludeSettingOptions,
TextSearchContextNew: TextSearchContextNew,
TextSearchMatchNew: TextSearchMatchNew,
TextSearchCompleteMessageTypeNew: TextSearchCompleteMessageTypeNew,
TextSearchCompleteMessageTypeNew: TextSearchCompleteMessageType,
};
};
}
78 changes: 65 additions & 13 deletions src/vs/workbench/api/common/extHostSearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,15 @@ import { URI, UriComponents } from 'vs/base/common/uri';
import { TextSearchManager } from 'vs/workbench/services/search/common/textSearchManager';
import { CancellationToken } from 'vs/base/common/cancellation';
import { revive } from 'vs/base/common/marshalling';
import { OldAITextSearchProviderConverter, OldFileSearchProviderConverter, OldTextSearchProviderConverter } from 'vs/workbench/services/search/common/searchExtConversionTypes';

export interface IExtHostSearch extends ExtHostSearchShape {
registerTextSearchProvider(scheme: string, provider: vscode.TextSearchProvider): IDisposable;
registerAITextSearchProvider(scheme: string, provider: vscode.AITextSearchProvider): IDisposable;
registerFileSearchProvider(scheme: string, provider: vscode.FileSearchProvider): IDisposable;
registerTextSearchProviderOld(scheme: string, provider: vscode.TextSearchProvider): IDisposable;
registerAITextSearchProviderOld(scheme: string, provider: vscode.AITextSearchProvider): IDisposable;
registerFileSearchProviderOld(scheme: string, provider: vscode.FileSearchProvider): IDisposable;
registerTextSearchProvider(scheme: string, provider: vscode.TextSearchProviderNew): IDisposable;
registerAITextSearchProvider(scheme: string, provider: vscode.AITextSearchProviderNew): IDisposable;
registerFileSearchProvider(scheme: string, provider: vscode.FileSearchProviderNew): IDisposable;
doInternalFileSearchWithCustomCallback(query: IFileQuery, token: CancellationToken, handleFileMatch: (data: URI[]) => void): Promise<ISearchCompleteStats>;
}

Expand All @@ -31,28 +35,44 @@ export class ExtHostSearch implements IExtHostSearch {
protected readonly _proxy: MainThreadSearchShape = this.extHostRpc.getProxy(MainContext.MainThreadSearch);
protected _handlePool: number = 0;

private readonly _textSearchProvider = new Map<number, vscode.TextSearchProvider>();
private readonly _textSearchProvider = new Map<number, vscode.TextSearchProviderNew>();
private readonly _textSearchUsedSchemes = new Set<string>();

private readonly _aiTextSearchProvider = new Map<number, vscode.AITextSearchProvider>();
private readonly _aiTextSearchProvider = new Map<number, vscode.AITextSearchProviderNew>();
private readonly _aiTextSearchUsedSchemes = new Set<string>();

private readonly _fileSearchProvider = new Map<number, vscode.FileSearchProvider>();
private readonly _fileSearchProvider = new Map<number, vscode.FileSearchProviderNew>();
private readonly _fileSearchUsedSchemes = new Set<string>();

private readonly _fileSearchManager = new FileSearchManager();

constructor(
@IExtHostRpcService private extHostRpc: IExtHostRpcService,
@IURITransformerService protected _uriTransformer: IURITransformerService,
@ILogService protected _logService: ILogService
@ILogService protected _logService: ILogService,
) { }

protected _transformScheme(scheme: string): string {
return this._uriTransformer.transformOutgoingScheme(scheme);
}

registerTextSearchProvider(scheme: string, provider: vscode.TextSearchProvider): IDisposable {
registerTextSearchProviderOld(scheme: string, provider: vscode.TextSearchProvider): IDisposable {
if (this._textSearchUsedSchemes.has(scheme)) {
throw new Error(`a text search provider for the scheme '${scheme}' is already registered`);
}

this._textSearchUsedSchemes.add(scheme);
const handle = this._handlePool++;
this._textSearchProvider.set(handle, new OldTextSearchProviderConverter(provider));
this._proxy.$registerTextSearchProvider(handle, this._transformScheme(scheme));
return toDisposable(() => {
this._textSearchUsedSchemes.delete(scheme);
this._textSearchProvider.delete(handle);
this._proxy.$unregisterProvider(handle);
});
}

registerTextSearchProvider(scheme: string, provider: vscode.TextSearchProviderNew): IDisposable {
if (this._textSearchUsedSchemes.has(scheme)) {
throw new Error(`a text search provider for the scheme '${scheme}' is already registered`);
}
Expand All @@ -68,7 +88,23 @@ export class ExtHostSearch implements IExtHostSearch {
});
}

registerAITextSearchProvider(scheme: string, provider: vscode.AITextSearchProvider): IDisposable {
registerAITextSearchProviderOld(scheme: string, provider: vscode.AITextSearchProvider): IDisposable {
if (this._aiTextSearchUsedSchemes.has(scheme)) {
throw new Error(`an AI text search provider for the scheme '${scheme}'is already registered`);
}

this._aiTextSearchUsedSchemes.add(scheme);
const handle = this._handlePool++;
this._aiTextSearchProvider.set(handle, new OldAITextSearchProviderConverter(provider));
this._proxy.$registerAITextSearchProvider(handle, this._transformScheme(scheme));
return toDisposable(() => {
this._aiTextSearchUsedSchemes.delete(scheme);
this._aiTextSearchProvider.delete(handle);
this._proxy.$unregisterProvider(handle);
});
}

registerAITextSearchProvider(scheme: string, provider: vscode.AITextSearchProviderNew): IDisposable {
if (this._aiTextSearchUsedSchemes.has(scheme)) {
throw new Error(`an AI text search provider for the scheme '${scheme}'is already registered`);
}
Expand All @@ -84,7 +120,23 @@ export class ExtHostSearch implements IExtHostSearch {
});
}

registerFileSearchProvider(scheme: string, provider: vscode.FileSearchProvider): IDisposable {
registerFileSearchProviderOld(scheme: string, provider: vscode.FileSearchProvider): IDisposable {
if (this._fileSearchUsedSchemes.has(scheme)) {
throw new Error(`a file search provider for the scheme '${scheme}' is already registered`);
}

this._fileSearchUsedSchemes.add(scheme);
const handle = this._handlePool++;
this._fileSearchProvider.set(handle, new OldFileSearchProviderConverter(provider));
this._proxy.$registerFileSearchProvider(handle, this._transformScheme(scheme));
return toDisposable(() => {
this._fileSearchUsedSchemes.delete(scheme);
this._fileSearchProvider.delete(handle);
this._proxy.$unregisterProvider(handle);
});
}

registerFileSearchProvider(scheme: string, provider: vscode.FileSearchProviderNew): IDisposable {
if (this._fileSearchUsedSchemes.has(scheme)) {
throw new Error(`a file search provider for the scheme '${scheme}' is already registered`);
}
Expand All @@ -108,7 +160,7 @@ export class ExtHostSearch implements IExtHostSearch {
this._proxy.$handleFileMatch(handle, session, batch.map(p => p.resource));
}, token);
} else {
throw new Error('3 unknown provider: ' + handle);
throw new Error('unknown provider: ' + handle);
}
}

Expand Down Expand Up @@ -146,14 +198,14 @@ export class ExtHostSearch implements IExtHostSearch {

$enableExtensionHostSearch(): void { }

protected createTextSearchManager(query: ITextQuery, provider: vscode.TextSearchProvider): TextSearchManager {
protected createTextSearchManager(query: ITextQuery, provider: vscode.TextSearchProviderNew): TextSearchManager {
return new TextSearchManager({ query, provider }, {
readdir: resource => Promise.resolve([]),
toCanonicalName: encoding => encoding
}, 'textSearchProvider');
}

protected createAITextSearchManager(query: IAITextQuery, provider: vscode.AITextSearchProvider): TextSearchManager {
protected createAITextSearchManager(query: IAITextQuery, provider: vscode.AITextSearchProviderNew): TextSearchManager {
return new TextSearchManager({ query, provider }, {
readdir: resource => Promise.resolve([]),
toCanonicalName: encoding => encoding
Expand Down
12 changes: 6 additions & 6 deletions src/vs/workbench/api/common/extHostWorkspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,7 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape, IExtHostWorkspac
fileEncoding: options.encoding,
maxResults: options.maxResults,
previewOptions,
surroundingContext: options.afterContext,
surroundingContext: options.afterContext, // TODO: remove ability to have before/after context separately

includePattern: includePattern,
excludePattern: excludePattern
Expand All @@ -567,14 +567,14 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape, IExtHostWorkspac
callback({
uri,
preview: {
text: result.preview.text,
text: result.previewText,
matches: mapArrayOrNot(
result.preview.matches,
m => new Range(m.startLineNumber, m.startColumn, m.endLineNumber, m.endColumn))
result.rangeLocations,
m => new Range(m.preview.startLineNumber, m.preview.startColumn, m.preview.endLineNumber, m.preview.endColumn))
},
ranges: mapArrayOrNot(
result.ranges,
r => new Range(r.startLineNumber, r.startColumn, r.endLineNumber, r.endColumn))
result.rangeLocations,
r => new Range(r.source.startLineNumber, r.source.startColumn, r.source.endLineNumber, r.source.endColumn))
} satisfies vscode.TextSearchMatch);
} else {
callback({
Expand Down
2 changes: 1 addition & 1 deletion src/vs/workbench/api/node/extHostSearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ export class NativeExtHostSearch extends ExtHostSearch implements IDisposable {
return super.$clearCache(cacheKey);
}

protected override createTextSearchManager(query: ITextQuery, provider: vscode.TextSearchProvider): TextSearchManager {
protected override createTextSearchManager(query: ITextQuery, provider: vscode.TextSearchProviderNew): TextSearchManager {
return new NativeTextSearchManager(query, provider, undefined, 'textSearchProvider');
}
}
12 changes: 6 additions & 6 deletions src/vs/workbench/api/test/node/extHostSearch.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,12 @@ suite('ExtHostSearch', () => {
const disposables = ensureNoDisposablesAreLeakedInTestSuite();

async function registerTestTextSearchProvider(provider: vscode.TextSearchProvider, scheme = 'file'): Promise<void> {
disposables.add(extHostSearch.registerTextSearchProvider(scheme, provider));
disposables.add(extHostSearch.registerTextSearchProviderOld(scheme, provider));
await rpcProtocol.sync();
}

async function registerTestFileSearchProvider(provider: vscode.FileSearchProvider, scheme = 'file'): Promise<void> {
disposables.add(extHostSearch.registerFileSearchProvider(scheme, provider));
disposables.add(extHostSearch.registerFileSearchProviderOld(scheme, provider));
await rpcProtocol.sync();
}

Expand Down Expand Up @@ -170,7 +170,7 @@ suite('ExtHostSearch', () => {
this._pfs = mockPFS as any;
}

protected override createTextSearchManager(query: ITextQuery, provider: vscode.TextSearchProvider): TextSearchManager {
protected override createTextSearchManager(query: ITextQuery, provider: vscode.TextSearchProviderNew): TextSearchManager {
return new NativeTextSearchManager(query, provider, this._pfs);
}
});
Expand Down Expand Up @@ -746,13 +746,13 @@ suite('ExtHostSearch', () => {
if (resultIsMatch(lineResult)) {
actualTextSearchResults.push({
preview: {
text: lineResult.preview.text,
text: lineResult.previewText,
matches: mapArrayOrNot(
lineResult.preview.matches,
lineResult.rangeLocations.map(r => r.preview),
m => new Range(m.startLineNumber, m.startColumn, m.endLineNumber, m.endColumn))
},
ranges: mapArrayOrNot(
lineResult.ranges,
lineResult.rangeLocations.map(r => r.source),
r => new Range(r.startLineNumber, r.startColumn, r.endLineNumber, r.endColumn),
),
uri: fileMatch.resource
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,5 @@ export function webviewMatchesToTextSearchMatches(webviewMatches: CellWebviewFin
new Range(0, rawMatch.searchPreviewInfo.range.start, 0, rawMatch.searchPreviewInfo.range.end),
undefined,
rawMatch.index) : undefined
).filter((e): e is ITextSearchMatch => !!e);
).filter((e): e is TextSearchMatch => !!e);
}
34 changes: 10 additions & 24 deletions src/vs/workbench/contrib/search/browser/searchModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2479,39 +2479,25 @@ export class RangeHighlightDecorations implements IDisposable {
});
}



function textSearchResultToMatches(rawMatch: ITextSearchMatch, fileMatch: FileMatch, isAiContributed: boolean): Match[] {
const previewLines = rawMatch.preview.text.split('\n');
if (Array.isArray(rawMatch.ranges)) {
return rawMatch.ranges.map((r, i) => {
const previewRange: ISearchRange = (<ISearchRange[]>rawMatch.preview.matches)[i];
return new Match(fileMatch, previewLines, previewRange, r, isAiContributed);
});
} else {
const previewRange = <ISearchRange>rawMatch.preview.matches;
const match = new Match(fileMatch, previewLines, previewRange, rawMatch.ranges, isAiContributed);
return [match];
}
const previewLines = rawMatch.previewText.split('\n');
return rawMatch.rangeLocations.map((rangeLocation) => {
const previewRange: ISearchRange = rangeLocation.preview;
return new Match(fileMatch, previewLines, previewRange, rangeLocation.source, isAiContributed);
});
}

// text search to notebook matches

export function textSearchMatchesToNotebookMatches(textSearchMatches: ITextSearchMatch[], cell: CellMatch): MatchInNotebook[] {
const notebookMatches: MatchInNotebook[] = [];
textSearchMatches.forEach((textSearchMatch) => {
const previewLines = textSearchMatch.preview.text.split('\n');
if (Array.isArray(textSearchMatch.ranges)) {
textSearchMatch.ranges.forEach((r, i) => {
const previewRange: ISearchRange = (<ISearchRange[]>textSearchMatch.preview.matches)[i];
const match = new MatchInNotebook(cell, previewLines, previewRange, r, textSearchMatch.webviewIndex);
notebookMatches.push(match);
});
} else {
const previewRange = <ISearchRange>textSearchMatch.preview.matches;
const match = new MatchInNotebook(cell, previewLines, previewRange, textSearchMatch.ranges, textSearchMatch.webviewIndex);
const previewLines = textSearchMatch.previewText.split('\n');
textSearchMatch.rangeLocations.map((rangeLocation) => {
const previewRange: ISearchRange = rangeLocation.preview;
const match = new MatchInNotebook(cell, previewLines, previewRange, rangeLocation.source, textSearchMatch.webviewIndex);
notebookMatches.push(match);
}
});
});
return notebookMatches;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,28 +149,28 @@ suite('searchNotebookHelpers', () => {
codeWebviewResults = webviewMatchesToTextSearchMatches(codeCellFindMatch.webviewMatches);

assert.strictEqual(markdownContentResults.length, 1);
assert.strictEqual(markdownContentResults[0].preview.text, '# Hello World Test\n');
assertRangesEqual(markdownContentResults[0].preview.matches, [new Range(0, 14, 0, 18)]);
assertRangesEqual(markdownContentResults[0].ranges, [new Range(0, 14, 0, 18)]);
assert.strictEqual(markdownContentResults[0].previewText, '# Hello World Test\n');
assertRangesEqual(markdownContentResults[0].rangeLocations.map(e => e.preview), [new Range(0, 14, 0, 18)]);
assertRangesEqual(markdownContentResults[0].rangeLocations.map(e => e.source), [new Range(0, 14, 0, 18)]);


assert.strictEqual(codeContentResults.length, 2);
assert.strictEqual(codeContentResults[0].preview.text, 'print("test! testing!!")\n');
assert.strictEqual(codeContentResults[1].preview.text, 'print("this is a Test")\n');
assertRangesEqual(codeContentResults[0].preview.matches, [new Range(0, 7, 0, 11), new Range(0, 13, 0, 17)]);
assertRangesEqual(codeContentResults[0].ranges, [new Range(0, 7, 0, 11), new Range(0, 13, 0, 17)]);
assert.strictEqual(codeContentResults[0].previewText, 'print("test! testing!!")\n');
assert.strictEqual(codeContentResults[1].previewText, 'print("this is a Test")\n');
assertRangesEqual(codeContentResults[0].rangeLocations.map(e => e.preview), [new Range(0, 7, 0, 11), new Range(0, 13, 0, 17)]);
assertRangesEqual(codeContentResults[0].rangeLocations.map(e => e.source), [new Range(0, 7, 0, 11), new Range(0, 13, 0, 17)]);

assert.strictEqual(codeWebviewResults.length, 3);
assert.strictEqual(codeWebviewResults[0].preview.text, 'test! testing!!');
assert.strictEqual(codeWebviewResults[1].preview.text, 'test! testing!!');
assert.strictEqual(codeWebviewResults[2].preview.text, 'this is a Test');

assertRangesEqual(codeWebviewResults[0].preview.matches, [new Range(0, 1, 0, 5)]);
assertRangesEqual(codeWebviewResults[1].preview.matches, [new Range(0, 7, 0, 11)]);
assertRangesEqual(codeWebviewResults[2].preview.matches, [new Range(0, 11, 0, 15)]);
assertRangesEqual(codeWebviewResults[0].ranges, [new Range(0, 1, 0, 5)]);
assertRangesEqual(codeWebviewResults[1].ranges, [new Range(0, 7, 0, 11)]);
assertRangesEqual(codeWebviewResults[2].ranges, [new Range(0, 11, 0, 15)]);
assert.strictEqual(codeWebviewResults[0].previewText, 'test! testing!!');
assert.strictEqual(codeWebviewResults[1].previewText, 'test! testing!!');
assert.strictEqual(codeWebviewResults[2].previewText, 'this is a Test');

assertRangesEqual(codeWebviewResults[0].rangeLocations.map(e => e.preview), [new Range(0, 1, 0, 5)]);
assertRangesEqual(codeWebviewResults[1].rangeLocations.map(e => e.preview), [new Range(0, 7, 0, 11)]);
assertRangesEqual(codeWebviewResults[2].rangeLocations.map(e => e.preview), [new Range(0, 11, 0, 15)]);
assertRangesEqual(codeWebviewResults[0].rangeLocations.map(e => e.source), [new Range(0, 1, 0, 5)]);
assertRangesEqual(codeWebviewResults[1].rangeLocations.map(e => e.source), [new Range(0, 7, 0, 11)]);
assertRangesEqual(codeWebviewResults[2].rangeLocations.map(e => e.source), [new Range(0, 11, 0, 15)]);
});

test('convert ITextSearchMatch to MatchInNotebook', () => {
Expand Down
Loading

0 comments on commit c5ef039

Please sign in to comment.