mirror of
https://github.com/Microsoft/vscode
synced 2024-08-27 21:09:43 +00:00
SearchProvider - clean up FileSearchProvider, remove cacheKey
This commit is contained in:
parent
28fd1cc007
commit
aff77d278b
19
src/vs/vscode.proposed.d.ts
vendored
19
src/vs/vscode.proposed.d.ts
vendored
|
@ -113,13 +113,6 @@ declare module 'vscode' {
|
|||
* The search pattern to match against file paths.
|
||||
*/
|
||||
pattern: string;
|
||||
|
||||
/**
|
||||
* `cacheKey` has the same value when `provideFileSearchResults` is invoked multiple times during a single quickopen session.
|
||||
* Providers can optionally use this to cache results at the beginning of a quickopen session and filter results as the user types.
|
||||
* It will have a different value for each folder searched.
|
||||
*/
|
||||
cacheKey?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -176,9 +169,9 @@ declare module 'vscode' {
|
|||
}
|
||||
|
||||
/**
|
||||
* A SearchProvider provides search results for files or text in files. It can be invoked by quickopen, the search viewlet, and other extensions.
|
||||
* A FileSearchProvider provides search results for files or text in files. It can be invoked by quickopen and other extensions.
|
||||
*/
|
||||
export interface SearchProvider {
|
||||
export interface FileSearchProvider {
|
||||
/**
|
||||
* Provide the set of files that match a certain file path pattern.
|
||||
* @param query The parameters for this query.
|
||||
|
@ -187,12 +180,6 @@ declare module 'vscode' {
|
|||
* @param token A cancellation token.
|
||||
*/
|
||||
provideFileSearchResults?(query: FileSearchQuery, options: FileSearchOptions, progress: Progress<Uri>, token: CancellationToken): Thenable<void>;
|
||||
|
||||
/**
|
||||
* Optional - if the provider makes use of `query.cacheKey`, it can implement this method which is invoked when the cache can be cleared.
|
||||
* @param cacheKey The same key that was passed as `query.cacheKey`.
|
||||
*/
|
||||
clearCache?(cacheKey: string): void;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -247,7 +234,7 @@ declare module 'vscode' {
|
|||
* @param provider The provider.
|
||||
* @return A [disposable](#Disposable) that unregisters this provider when being disposed.
|
||||
*/
|
||||
export function registerFileSearchProvider(scheme: string, provider: SearchProvider): Disposable;
|
||||
export function registerFileSearchProvider(scheme: string, provider: FileSearchProvider): Disposable;
|
||||
|
||||
/**
|
||||
* Register a text search provider.
|
||||
|
|
|
@ -138,7 +138,7 @@ class RemoteSearchProvider implements ISearchResultProvider, IDisposable {
|
|||
}
|
||||
|
||||
clearCache(cacheKey: string): TPromise<void> {
|
||||
return this._proxy.$clearCache(this._handle, cacheKey);
|
||||
return this._proxy.$clearCache(cacheKey);
|
||||
}
|
||||
|
||||
handleFindMatch(session: number, dataOrUri: (UriComponents | IRawFileMatch2)[]): void {
|
||||
|
|
|
@ -689,7 +689,7 @@ export interface ExtHostFileSystemShape {
|
|||
|
||||
export interface ExtHostSearchShape {
|
||||
$provideFileSearchResults(handle: number, session: number, query: IRawSearchQuery): TPromise<ISearchCompleteStats>;
|
||||
$clearCache(handle: number, cacheKey: string): TPromise<void>;
|
||||
$clearCache(cacheKey: string): TPromise<void>;
|
||||
$provideTextSearchResults(handle: number, session: number, pattern: IPatternInfo, query: IRawSearchQuery): TPromise<ISearchCompleteStats>;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ export interface ISchemeTransformer {
|
|||
export class ExtHostSearch implements ExtHostSearchShape {
|
||||
|
||||
private readonly _proxy: MainThreadSearchShape;
|
||||
private readonly _fileSearchProvider = new Map<number, vscode.SearchProvider>();
|
||||
private readonly _fileSearchProvider = new Map<number, vscode.FileSearchProvider>();
|
||||
private readonly _textSearchProvider = new Map<number, vscode.TextSearchProvider>();
|
||||
private readonly _fileIndexProvider = new Map<number, vscode.FileIndexProvider>();
|
||||
private _handlePool: number = 0;
|
||||
|
@ -46,7 +46,7 @@ export class ExtHostSearch implements ExtHostSearchShape {
|
|||
return scheme;
|
||||
}
|
||||
|
||||
registerFileSearchProvider(scheme: string, provider: vscode.SearchProvider) {
|
||||
registerFileSearchProvider(scheme: string, provider: vscode.FileSearchProvider) {
|
||||
const handle = this._handlePool++;
|
||||
this._fileSearchProvider.set(handle, provider);
|
||||
this._proxy.$registerFileSearchProvider(handle, this._transformScheme(scheme));
|
||||
|
@ -95,14 +95,9 @@ export class ExtHostSearch implements ExtHostSearchShape {
|
|||
}
|
||||
}
|
||||
|
||||
$clearCache(handle: number, cacheKey: string): TPromise<void> {
|
||||
const provider = this._fileSearchProvider.get(handle);
|
||||
if (!provider.clearCache) {
|
||||
return TPromise.as(undefined);
|
||||
}
|
||||
|
||||
return TPromise.as(
|
||||
this._fileSearchManager.clearCache(cacheKey, provider));
|
||||
$clearCache(cacheKey: string): TPromise<void> {
|
||||
// Only relevant to file index search
|
||||
return this._fileIndexSearchManager.clearCache(cacheKey);
|
||||
}
|
||||
|
||||
$provideTextSearchResults(handle: number, session: number, pattern: IPatternInfo, rawQuery: IRawSearchQuery): TPromise<ISearchCompleteStats> {
|
||||
|
@ -421,7 +416,7 @@ class FileSearchEngine {
|
|||
|
||||
private globalExcludePattern: glob.ParsedExpression;
|
||||
|
||||
constructor(private config: ISearchQuery, private provider: vscode.SearchProvider) {
|
||||
constructor(private config: ISearchQuery, private provider: vscode.FileSearchProvider) {
|
||||
this.filePattern = config.filePattern;
|
||||
this.includePattern = config.includePattern && glob.parse(config.includePattern);
|
||||
this.maxResults = config.maxResults || null;
|
||||
|
@ -450,7 +445,7 @@ class FileSearchEngine {
|
|||
|
||||
// Support that the file pattern is a full path to a file that exists
|
||||
if (this.isCanceled) {
|
||||
return resolve({ limitHit: this.isLimitHit, cacheKeys: [] });
|
||||
return resolve({ limitHit: this.isLimitHit });
|
||||
}
|
||||
|
||||
// For each extra file
|
||||
|
@ -471,8 +466,8 @@ class FileSearchEngine {
|
|||
// For each root folder
|
||||
TPromise.join(folderQueries.map(fq => {
|
||||
return this.searchInFolder(fq, onResult);
|
||||
})).then(cacheKeys => {
|
||||
resolve({ limitHit: this.isLimitHit, cacheKeys });
|
||||
})).then(() => {
|
||||
resolve({ limitHit: this.isLimitHit });
|
||||
}, (errs: Error[]) => {
|
||||
const errMsg = errs
|
||||
.map(err => toErrorMessage(err))
|
||||
|
@ -483,7 +478,7 @@ class FileSearchEngine {
|
|||
});
|
||||
}
|
||||
|
||||
private searchInFolder(fq: IFolderQuery<URI>, onResult: (match: IInternalFileMatch) => void): TPromise<string> {
|
||||
private searchInFolder(fq: IFolderQuery<URI>, onResult: (match: IInternalFileMatch) => void): TPromise<void> {
|
||||
let cancellation = new CancellationTokenSource();
|
||||
return new TPromise((resolve, reject) => {
|
||||
const options = this.getSearchOptionsForFolder(fq);
|
||||
|
@ -510,17 +505,13 @@ class FileSearchEngine {
|
|||
this.addDirectoryEntries(tree, fq.folder, relativePath, onResult);
|
||||
};
|
||||
|
||||
let folderCacheKey: string;
|
||||
new TPromise(_resolve => process.nextTick(_resolve))
|
||||
.then(() => {
|
||||
this.activeCancellationTokens.add(cancellation);
|
||||
|
||||
folderCacheKey = this.config.cacheKey && (this.config.cacheKey + '_' + fq.folder.fsPath);
|
||||
|
||||
return this.provider.provideFileSearchResults(
|
||||
{
|
||||
pattern: this.config.filePattern || '',
|
||||
cacheKey: folderCacheKey
|
||||
pattern: this.config.filePattern || ''
|
||||
},
|
||||
options,
|
||||
{ report: onProviderResult },
|
||||
|
@ -537,7 +528,7 @@ class FileSearchEngine {
|
|||
}).then(
|
||||
() => {
|
||||
cancellation.dispose();
|
||||
resolve(folderCacheKey);
|
||||
resolve(null);
|
||||
},
|
||||
err => {
|
||||
cancellation.dispose();
|
||||
|
@ -646,30 +637,23 @@ class FileSearchEngine {
|
|||
|
||||
interface IInternalSearchComplete {
|
||||
limitHit: boolean;
|
||||
cacheKeys: string[];
|
||||
}
|
||||
|
||||
class FileSearchManager {
|
||||
|
||||
private static readonly BATCH_SIZE = 512;
|
||||
|
||||
private readonly expandedCacheKeys = new Map<string, string[]>();
|
||||
|
||||
fileSearch(config: ISearchQuery, provider: vscode.SearchProvider, onResult: (matches: IFileMatch[]) => void): TPromise<ISearchCompleteStats> {
|
||||
fileSearch(config: ISearchQuery, provider: vscode.FileSearchProvider, onBatch: (matches: IFileMatch[]) => void): TPromise<ISearchCompleteStats> {
|
||||
let searchP: TPromise;
|
||||
return new TPromise<ISearchCompleteStats>((c, e) => {
|
||||
const engine = new FileSearchEngine(config, provider);
|
||||
|
||||
const onInternalResult = (progress: IInternalFileMatch[]) => {
|
||||
onResult(progress.map(m => this.rawMatchToSearchItem(m)));
|
||||
const onInternalResult = (batch: IInternalFileMatch[]) => {
|
||||
onBatch(batch.map(m => this.rawMatchToSearchItem(m)));
|
||||
};
|
||||
|
||||
searchP = this.doSearch(engine, FileSearchManager.BATCH_SIZE, onInternalResult).then(
|
||||
result => {
|
||||
if (config.cacheKey) {
|
||||
this.expandedCacheKeys.set(config.cacheKey, result.cacheKeys);
|
||||
}
|
||||
|
||||
c({
|
||||
limitHit: result.limitHit
|
||||
});
|
||||
|
@ -682,15 +666,6 @@ class FileSearchManager {
|
|||
});
|
||||
}
|
||||
|
||||
clearCache(cacheKey: string, provider: vscode.SearchProvider): void {
|
||||
if (!this.expandedCacheKeys.has(cacheKey)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.expandedCacheKeys.get(cacheKey).forEach(key => provider.clearCache(key));
|
||||
this.expandedCacheKeys.delete(cacheKey);
|
||||
}
|
||||
|
||||
private rawMatchToSearchItem(match: IInternalFileMatch): IFileMatch {
|
||||
return {
|
||||
resource: resources.joinPath(match.base, match.relativePath)
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
import * as arrays from 'vs/base/common/arrays';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { ResourceMap } from 'vs/base/common/map';
|
||||
import { ResourceMap, values } from 'vs/base/common/map';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import * as objects from 'vs/base/common/objects';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
|
@ -52,9 +52,6 @@ export class SearchService extends Disposable implements ISearchService {
|
|||
}
|
||||
|
||||
public registerSearchResultProvider(scheme: string, type: SearchProviderType, provider: ISearchResultProvider): IDisposable {
|
||||
// if (scheme === 'file') {
|
||||
// this.fileSearchProvider = provider;
|
||||
|
||||
let list: Map<string, ISearchResultProvider>;
|
||||
if (type === SearchProviderType.file) {
|
||||
list = this.fileSearchProviders;
|
||||
|
@ -137,11 +134,19 @@ export class SearchService extends Disposable implements ISearchService {
|
|||
}
|
||||
};
|
||||
|
||||
const provider = query.type === QueryType.File ?
|
||||
let provider = query.type === QueryType.File ?
|
||||
this.fileSearchProviders.get(fq.folder.scheme) || this.fileIndexProviders.get(fq.folder.scheme) :
|
||||
this.textSearchProviders.get(fq.folder.scheme);
|
||||
|
||||
return TPromise.as(provider.search(oneFolderQuery, onProviderProgress));
|
||||
if (!provider && fq.folder.scheme === 'file') {
|
||||
provider = this.diskSearch;
|
||||
}
|
||||
|
||||
if (!provider) {
|
||||
return TPromise.wrapError(new Error('No search provider registered for scheme: ' + fq.folder.scheme));
|
||||
}
|
||||
|
||||
return provider.search(oneFolderQuery, onProviderProgress);
|
||||
})).then(completes => {
|
||||
completes = completes.filter(c => !!c);
|
||||
if (!completes.length) {
|
||||
|
@ -268,9 +273,12 @@ export class SearchService extends Disposable implements ISearchService {
|
|||
}
|
||||
|
||||
public clearCache(cacheKey: string): TPromise<void> {
|
||||
return TPromise.join([
|
||||
this.diskSearch
|
||||
].map(provider => provider && provider.clearCache(cacheKey)))
|
||||
const clearPs = [
|
||||
this.diskSearch,
|
||||
...values(this.fileIndexProviders)
|
||||
].map(provider => provider && provider.clearCache(cacheKey));
|
||||
|
||||
return TPromise.join(clearPs)
|
||||
.then(() => { });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ suite('ExtHostSearch', () => {
|
|||
await rpcProtocol.sync();
|
||||
}
|
||||
|
||||
async function registerTestFileSearchProvider(provider: vscode.SearchProvider, scheme = 'file'): Promise<void> {
|
||||
async function registerTestFileSearchProvider(provider: vscode.FileSearchProvider, scheme = 'file'): Promise<void> {
|
||||
disposables.push(extHostSearch.registerFileSearchProvider(scheme, provider));
|
||||
await rpcProtocol.sync();
|
||||
}
|
||||
|
@ -647,34 +647,6 @@ suite('ExtHostSearch', () => {
|
|||
const { results } = await runFileSearch(query);
|
||||
compareURIs(results, reportedResults);
|
||||
});
|
||||
|
||||
test('uses different cache keys for different folders', async () => {
|
||||
const cacheKeys: string[] = [];
|
||||
await registerTestFileSearchProvider({
|
||||
provideFileSearchResults(query: vscode.FileSearchQuery, options: vscode.FileSearchOptions, progress: vscode.Progress<URI>, token: vscode.CancellationToken): Thenable<void> {
|
||||
cacheKeys.push(query.cacheKey);
|
||||
return TPromise.wrap(null);
|
||||
}
|
||||
});
|
||||
|
||||
const query: ISearchQuery = {
|
||||
type: QueryType.File,
|
||||
filePattern: '',
|
||||
cacheKey: 'cacheKey',
|
||||
folderQueries: [
|
||||
{
|
||||
folder: rootFolderA
|
||||
},
|
||||
{
|
||||
folder: rootFolderB
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
await runFileSearch(query);
|
||||
assert.equal(cacheKeys.length, 2);
|
||||
assert.notEqual(cacheKeys[0], cacheKeys[1]);
|
||||
});
|
||||
});
|
||||
|
||||
suite('Text:', () => {
|
||||
|
|
Loading…
Reference in a new issue