Reduce recomputation of state in markdown extension (#152804)

* Reduce recomputation of state in markdown extension

- Use `getForDocument` more often to avoid refetching documents
- Debounce `MdTableOfContentsWatcher`. We don't want this to trigger on every keystroke :)

* Cache LinkDefinitionSet

* Add test file change

* Fix toc watcher for tests
This commit is contained in:
Matt Bierner
2022-06-21 16:25:10 -07:00
committed by GitHub
parent f9d332c692
commit c84655d123
9 changed files with 64 additions and 31 deletions

View File

@@ -9,13 +9,13 @@ import * as nls from 'vscode-nls';
import { CommandManager } from '../commandManager';
import { ILogger } from '../logging';
import { MdTableOfContentsProvider } from '../tableOfContents';
import { MdTableOfContentsWatcher } from '../test/tableOfContentsWatcher';
import { Delayer } from '../util/async';
import { noopToken } from '../util/cancellation';
import { Disposable } from '../util/dispose';
import { isMarkdownFile, looksLikeMarkdownPath } from '../util/file';
import { Limiter } from '../util/limiter';
import { ResourceMap } from '../util/resourceMap';
import { MdTableOfContentsWatcher } from '../util/tableOfContentsWatcher';
import { MdWorkspaceContents, SkinnyTextDocument } from '../workspaceContents';
import { InternalHref, LinkDefinitionSet, MdLink, MdLinkProvider, MdLinkSource } from './documentLinks';
import { MdReferencesProvider, tryResolveLinkPath } from './references';
@@ -347,7 +347,7 @@ export class DiagnosticManager extends Disposable {
}
}));
this.tableOfContentsWatcher = this._register(new MdTableOfContentsWatcher(workspaceContents, tocProvider));
this.tableOfContentsWatcher = this._register(new MdTableOfContentsWatcher(workspaceContents, tocProvider, delay));
this._register(this.tableOfContentsWatcher.onTocChanged(async e => {
// When the toc of a document changes, revalidate every file that linked to it too
const triggered = new ResourceMap<void>();
@@ -491,7 +491,7 @@ export class DiagnosticComputer {
return [];
}
const toc = await this.tocProvider.get(doc.uri);
const toc = await this.tocProvider.getForDocument(doc);
if (token.isCancellationRequested) {
return [];
}

View File

@@ -427,12 +427,17 @@ export class MdLinkComputer {
}
}
interface MdDocumentLinks {
readonly links: readonly MdLink[];
readonly definitions: LinkDefinitionSet;
}
/**
* Stateful object which provides links for markdown files the workspace.
*/
export class MdLinkProvider extends Disposable {
private readonly _linkCache: MdDocumentInfoCache<readonly MdLink[]>;
private readonly _linkCache: MdDocumentInfoCache<MdDocumentLinks>;
private readonly linkComputer: MdLinkComputer;
@@ -443,21 +448,19 @@ export class MdLinkProvider extends Disposable {
) {
super();
this.linkComputer = new MdLinkComputer(tokenizer);
this._linkCache = this._register(new MdDocumentInfoCache(workspaceContents, doc => {
this._linkCache = this._register(new MdDocumentInfoCache(workspaceContents, async doc => {
logger.verbose('LinkProvider', `compute - ${doc.uri}`);
return this.linkComputer.getAllLinks(doc, noopToken);
const links = await this.linkComputer.getAllLinks(doc, noopToken);
return {
links,
definitions: new LinkDefinitionSet(links),
};
}));
}
public async getLinks(document: SkinnyTextDocument): Promise<{
readonly links: readonly MdLink[];
readonly definitions: LinkDefinitionSet;
}> {
const links = (await this._linkCache.get(document.uri)) ?? [];
return {
links,
definitions: new LinkDefinitionSet(links),
};
public async getLinks(document: SkinnyTextDocument): Promise<MdDocumentLinks> {
return this._linkCache.getForDocument(document);
}
}

View File

@@ -56,7 +56,7 @@ export class MdFoldingProvider implements vscode.FoldingRangeProvider {
}
private async getHeaderFoldingRanges(document: SkinnyTextDocument): Promise<vscode.FoldingRange[]> {
const toc = await this.tocProvide.get(document.uri);
const toc = await this.tocProvide.getForDocument(document);
return toc.entries.map(entry => {
let endLine = entry.sectionLocation.range.end.line;
if (document.lineAt(endLine).isEmptyOrWhitespace && endLine >= entry.line + 1) {

View File

@@ -83,7 +83,7 @@ export class MdReferencesProvider extends Disposable {
public async getReferencesAtPosition(document: SkinnyTextDocument, position: vscode.Position, token: vscode.CancellationToken): Promise<MdReference[]> {
this.logger.verbose('ReferencesProvider', `getReferencesAtPosition: ${document.uri}`);
const toc = await this.tocProvider.get(document.uri);
const toc = await this.tocProvider.getForDocument(document);
if (token.isCancellationRequested) {
return [];
}

View File

@@ -53,7 +53,7 @@ export class MdSmartSelect implements vscode.SelectionRangeProvider {
}
private async getHeaderSelectionRange(document: SkinnyTextDocument, position: vscode.Position): Promise<vscode.SelectionRange | undefined> {
const toc = await this.tocProvider.get(document.uri);
const toc = await this.tocProvider.getForDocument(document);
const headerInfo = getHeadersForPosition(toc.entries, position);