Search Provider - implement clearCache

This commit is contained in:
Rob Lourens
2018-07-03 20:08:53 -07:00
parent 3a0ae3683b
commit 0215f30d9b
7 changed files with 83 additions and 21 deletions

View File

@@ -69,6 +69,16 @@ export class ExtHostSearch implements ExtHostSearchShape {
});
}
$clearCache(handle: number, cacheKey: string): TPromise<void> {
const provider = this._searchProvider.get(handle);
if (!provider.clearCache) {
return TPromise.as(undefined);
}
return TPromise.as(
this._fileSearchManager.clearCache(cacheKey, provider));
}
$provideTextSearchResults(handle: number, session: number, pattern: IPatternInfo, rawQuery: IRawSearchQuery): TPromise<ISearchCompleteStats> {
const provider = this._searchProvider.get(handle);
if (!provider.provideTextSearchResults) {
@@ -530,10 +540,10 @@ class FileSearchEngine {
this.activeCancellationTokens = new Set();
}
public search(): PPromise<{ isLimitHit: boolean }, IInternalFileMatch> {
public search(): PPromise<IInternalSearchComplete, IInternalFileMatch> {
const folderQueries = this.config.folderQueries;
return new PPromise<{ isLimitHit: boolean }, IInternalFileMatch>((resolve, reject, _onResult) => {
return new PPromise((resolve, reject, _onResult) => {
const onResult = (match: IInternalFileMatch) => {
this.resultCount++;
_onResult(match);
@@ -541,7 +551,7 @@ class FileSearchEngine {
// Support that the file pattern is a full path to a file that exists
if (this.isCanceled) {
return resolve({ isLimitHit: this.isLimitHit });
return resolve({ limitHit: this.isLimitHit, cacheKeys: [] });
}
// For each extra file
@@ -562,8 +572,8 @@ class FileSearchEngine {
// For each root folder
PPromise.join(folderQueries.map(fq => {
return this.searchInFolder(fq).then(null, null, onResult);
})).then(() => {
resolve({ isLimitHit: this.isLimitHit });
})).then(cacheKeys => {
resolve({ limitHit: this.isLimitHit, cacheKeys });
}, (errs: Error[]) => {
const errMsg = errs
.map(err => toErrorMessage(err))
@@ -574,7 +584,7 @@ class FileSearchEngine {
});
}
private searchInFolder(fq: IFolderQuery<URI>): PPromise<void, IInternalFileMatch> {
private searchInFolder(fq: IFolderQuery<URI>): PPromise<string, IInternalFileMatch> {
let cancellation = new CancellationTokenSource();
return new PPromise((resolve, reject, onResult) => {
const options = this.getSearchOptionsForFolder(fq);
@@ -601,13 +611,17 @@ class FileSearchEngine {
this.addDirectoryEntries(tree, fq.folder, relativePath, onResult);
};
new TPromise(resolve => process.nextTick(resolve))
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: this.config.cacheKey + '_' + fq.folder.fsPath
cacheKey: folderCacheKey
},
options,
{ report: onProviderResult },
@@ -637,7 +651,7 @@ class FileSearchEngine {
}).then(
() => {
cancellation.dispose();
resolve(undefined);
resolve(folderCacheKey);
},
err => {
cancellation.dispose();
@@ -775,19 +789,38 @@ class FileSearchEngine {
}
}
interface IInternalSearchComplete {
limitHit: boolean;
cacheKeys: string[];
}
class FileSearchManager {
private static readonly BATCH_SIZE = 512;
private readonly expandedCacheKeys = new Map<string, string[]>();
constructor(private _pfs: typeof pfs) { }
public fileSearch(config: ISearchQuery, provider: vscode.SearchProvider): PPromise<ISearchCompleteStats, IFileMatch[]> {
fileSearch(config: ISearchQuery, provider: vscode.SearchProvider): PPromise<ISearchCompleteStats, IFileMatch[]> {
let searchP: PPromise;
return new PPromise<ISearchCompleteStats, IFileMatch[]>((c, e, p) => {
const engine = new FileSearchEngine(config, provider, this._pfs);
searchP = this.doSearch(engine, provider, FileSearchManager.BATCH_SIZE).then(c, e, progress => {
p(progress.map(m => this.rawMatchToSearchItem(m)));
});
searchP = this.doSearch(engine, FileSearchManager.BATCH_SIZE).then(
result => {
if (config.cacheKey) {
this.expandedCacheKeys.set(config.cacheKey, result.cacheKeys);
}
c({
limitHit: result.limitHit
});
},
e,
progress => {
p(progress.map(m => this.rawMatchToSearchItem(m)));
});
}, () => {
if (searchP) {
searchP.cancel();
@@ -795,23 +828,30 @@ 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)
};
}
private doSearch(engine: FileSearchEngine, provider: vscode.SearchProvider, batchSize: number): PPromise<ISearchCompleteStats, IInternalFileMatch[]> {
return new PPromise<ISearchCompleteStats, IInternalFileMatch[]>((c, e, p) => {
private doSearch(engine: FileSearchEngine, batchSize: number): PPromise<IInternalSearchComplete, IInternalFileMatch[]> {
return new PPromise((c, e, p) => {
let batch: IInternalFileMatch[] = [];
engine.search().then(result => {
if (batch.length) {
p(batch);
}
c({
limitHit: result.isLimitHit
});
c(result);
}, error => {
if (batch.length) {
p(batch);