Extract MdWorkspaceCache

This lets us reuse this logic in other places
This commit is contained in:
Matt Bierner
2022-03-29 15:21:44 -07:00
parent 407b66a6d4
commit 9b6435af76

View File

@@ -12,49 +12,68 @@ import { MdDocumentSymbolProvider } from './documentSymbolProvider';
export class MdWorkspaceSymbolProvider extends Disposable implements vscode.WorkspaceSymbolProvider {
private readonly _symbolCache = new Map<string, Lazy<Thenable<vscode.SymbolInformation[]>>>();
private _symbolCachePopulated: boolean = false;
private readonly _cache: MdWorkspaceCache<Promise<vscode.SymbolInformation[]>>;
public constructor(
private _symbolProvider: MdDocumentSymbolProvider,
private _workspaceMarkdownDocumentProvider: MdWorkspaceContents,
symbolProvider: MdDocumentSymbolProvider,
workspaceContents: MdWorkspaceContents,
) {
super();
this._cache = this._register(new MdWorkspaceCache(workspaceContents, doc => symbolProvider.provideDocumentSymbolInformation(doc)));
}
public async provideWorkspaceSymbols(query: string): Promise<vscode.SymbolInformation[]> {
const allSymbolSets = await this._cache.getAll();
const allSymbols = (await Promise.all(allSymbolSets)).flat();
return allSymbols.filter(symbolInformation => symbolInformation.name.toLowerCase().indexOf(query.toLowerCase()) !== -1);
}
}
/**
* Cache of information for markdown files in the workspace.
*/
class MdWorkspaceCache<T> extends Disposable {
private readonly _cache = new Map<string, Lazy<T>>();
private _hasPopulatedCache = false;
public constructor(
private readonly workspaceContents: MdWorkspaceContents,
private readonly getValue: (document: SkinnyTextDocument) => T,
) {
super();
}
public async provideWorkspaceSymbols(query: string): Promise<vscode.SymbolInformation[]> {
if (!this._symbolCachePopulated) {
public async getAll(): Promise<T[]> {
if (!this._hasPopulatedCache) {
await this.populateSymbolCache();
this._symbolCachePopulated = true;
this._hasPopulatedCache = true;
this._workspaceMarkdownDocumentProvider.onDidChangeMarkdownDocument(this.onDidChangeDocument, this, this._disposables);
this._workspaceMarkdownDocumentProvider.onDidCreateMarkdownDocument(this.onDidChangeDocument, this, this._disposables);
this._workspaceMarkdownDocumentProvider.onDidDeleteMarkdownDocument(this.onDidDeleteDocument, this, this._disposables);
this.workspaceContents.onDidChangeMarkdownDocument(this.onDidChangeDocument, this, this._disposables);
this.workspaceContents.onDidCreateMarkdownDocument(this.onDidChangeDocument, this, this._disposables);
this.workspaceContents.onDidDeleteMarkdownDocument(this.onDidDeleteDocument, this, this._disposables);
}
const allSymbolsSets = await Promise.all(Array.from(this._symbolCache.values(), x => x.value));
const allSymbols = allSymbolsSets.flat();
return allSymbols.filter(symbolInformation => symbolInformation.name.toLowerCase().indexOf(query.toLowerCase()) !== -1);
return Array.from(this._cache.values(), x => x.value);
}
public async populateSymbolCache(): Promise<void> {
const markdownDocumentUris = await this._workspaceMarkdownDocumentProvider.getAllMarkdownDocuments();
private async populateSymbolCache(): Promise<void> {
const markdownDocumentUris = await this.workspaceContents.getAllMarkdownDocuments();
for (const document of markdownDocumentUris) {
this._symbolCache.set(document.uri.toString(), this.getSymbols(document));
this._cache.set(document.uri.toString(), this.update(document));
}
}
private getSymbols(document: SkinnyTextDocument): Lazy<Thenable<vscode.SymbolInformation[]>> {
return lazy(() => {
return this._symbolProvider.provideDocumentSymbolInformation(document);
});
private update(document: SkinnyTextDocument): Lazy<T> {
return lazy(() => this.getValue(document));
}
private onDidChangeDocument(document: SkinnyTextDocument) {
this._symbolCache.set(document.uri.toString(), this.getSymbols(document));
this._cache.set(document.uri.toString(), this.update(document));
}
private onDidDeleteDocument(resource: vscode.Uri) {
this._symbolCache.delete(resource.toString());
this._cache.delete(resource.toString());
}
}