Refactor markdown language features (#152402)

(sorry for the size of this PR)

This change cleans up the markdown language features by making the following changes:

- Use `registerXSupport` public functions to register these
- Expose the slugifier the `MarkdownEngine` uses. You never want to use a different one if you already have a markdown engine
- Sort of clean up names. I'd introduced a bunch of confusing names while iterating in this space. What I'm working towards:

    - `Computer` — Stateless thing that computer data
    - `Provider` — Potentially stateful thing that provides data (which may be cached)
    - `VsCodeProvider` — The actual implementation of the various vscode language features (which should only be used by VS Code and in tests, not shared with other features)
- Introduce `MdLinkProvider` to avoid recomputing links for a given document. Also use this to hide more internals of link computation
This commit is contained in:
Matt Bierner
2022-06-17 01:25:52 -07:00
committed by GitHub
parent 54f5758f81
commit 623f55f437
24 changed files with 333 additions and 181 deletions

View File

@@ -9,7 +9,7 @@ import { MarkdownEngine } from '../markdownEngine';
import { TableOfContents } from '../tableOfContents';
import { resolveUriToMarkdownFile } from '../util/openDocumentLink';
import { SkinnyTextDocument } from '../workspaceContents';
import { MdLinkComputer } from './documentLinkProvider';
import { MdLinkProvider } from './documentLinkProvider';
enum CompletionContextKind {
/** `[...](|)` */
@@ -76,19 +76,14 @@ function tryDecodeUriComponent(str: string): string {
}
}
export class MdPathCompletionProvider implements vscode.CompletionItemProvider {
public static register(
selector: vscode.DocumentSelector,
engine: MarkdownEngine,
linkComputer: MdLinkComputer,
): vscode.Disposable {
return vscode.languages.registerCompletionItemProvider(selector, new MdPathCompletionProvider(engine, linkComputer), '.', '/', '#');
}
/**
* Adds path completions in markdown files by implementing {@link vscode.CompletionItemProvider}.
*/
export class MdVsCodePathCompletionProvider implements vscode.CompletionItemProvider {
constructor(
private readonly engine: MarkdownEngine,
private readonly linkComputer: MdLinkComputer,
private readonly linkProvider: MdLinkProvider,
) { }
public async provideCompletionItems(document: SkinnyTextDocument, position: vscode.Position, _token: vscode.CancellationToken, _context: vscode.CompletionContext): Promise<vscode.CompletionItem[]> {
@@ -240,8 +235,8 @@ export class MdPathCompletionProvider implements vscode.CompletionItemProvider {
const insertionRange = new vscode.Range(context.linkTextStartPosition, position);
const replacementRange = new vscode.Range(insertionRange.start, position.translate({ characterDelta: context.linkSuffix.length }));
const definitions = await this.linkComputer.getLinkDefinitions(document);
for (const def of definitions) {
const { definitions } = await this.linkProvider.getLinks(document);
for (const [_, def] of definitions) {
yield {
kind: vscode.CompletionItemKind.Reference,
label: def.ref.text,
@@ -351,3 +346,11 @@ export class MdPathCompletionProvider implements vscode.CompletionItemProvider {
return document.uri;
}
}
export function registerPathCompletionSupport(
selector: vscode.DocumentSelector,
engine: MarkdownEngine,
linkProvider: MdLinkProvider,
): vscode.Disposable {
return vscode.languages.registerCompletionItemProvider(selector, new MdVsCodePathCompletionProvider(engine, linkProvider), '.', '/', '#');
}