Rename types in the markdown extension (#152905)

Renames in the markdown extension

This renames some types and splits up some files as part of an exploration towards a proper LSP. Changes:

- `SkinnyTextDocument` -> `ITextDocument`
- Moved `ITextDocument` to own file
- `MdWorkspaceContents` -> `IMdWorkspace`
This commit is contained in:
Matt Bierner 2022-06-22 14:12:48 -07:00 committed by GitHub
parent 5f0a3888b4
commit 07144d22c4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
35 changed files with 353 additions and 336 deletions

View file

@ -5,7 +5,7 @@
import { Command } from '../commandManager';
import { MarkdownItEngine } from '../markdownEngine';
import { SkinnyTextDocument } from '../workspaceContents';
import { ITextDocument } from '../types/textDocument';
export class RenderDocument implements Command {
public readonly id = 'markdown.api.render';
@ -14,7 +14,7 @@ export class RenderDocument implements Command {
private readonly engine: MarkdownItEngine
) { }
public async execute(document: SkinnyTextDocument | string): Promise<string> {
public async execute(document: ITextDocument | string): Promise<string> {
return (await (this.engine.render(document))).html;
}
}

View file

@ -28,7 +28,7 @@ import { ContentSecurityPolicyArbiter, ExtensionContentSecurityPolicyArbiter, Pr
import { githubSlugifier } from './slugify';
import { MdTableOfContentsProvider } from './tableOfContents';
import { loadDefaultTelemetryReporter, TelemetryReporter } from './telemetryReporter';
import { MdWorkspaceContents, VsCodeMdWorkspaceContents } from './workspaceContents';
import { IMdWorkspace, VsCodeMdWorkspace } from './workspace';
export function activate(context: vscode.ExtensionContext) {
@ -45,16 +45,16 @@ export function activate(context: vscode.ExtensionContext) {
const commandManager = new CommandManager();
const engine = new MarkdownItEngine(contributions, githubSlugifier, logger);
const workspaceContents = new VsCodeMdWorkspaceContents();
const parser = new MdParsingProvider(engine, workspaceContents);
const tocProvider = new MdTableOfContentsProvider(parser, workspaceContents, logger);
context.subscriptions.push(workspaceContents, parser, tocProvider);
const workspace = new VsCodeMdWorkspace();
const parser = new MdParsingProvider(engine, workspace);
const tocProvider = new MdTableOfContentsProvider(parser, workspace, logger);
context.subscriptions.push(workspace, parser, tocProvider);
const contentProvider = new MdDocumentRenderer(engine, context, cspArbiter, contributions, logger);
const previewManager = new MarkdownPreviewManager(contentProvider, logger, contributions, tocProvider);
context.subscriptions.push(previewManager);
context.subscriptions.push(registerMarkdownLanguageFeatures(parser, workspaceContents, commandManager, tocProvider, logger));
context.subscriptions.push(registerMarkdownLanguageFeatures(parser, workspace, commandManager, tocProvider, logger));
context.subscriptions.push(registerMarkdownCommands(commandManager, previewManager, telemetryReporter, cspArbiter, engine, tocProvider));
context.subscriptions.push(vscode.workspace.onDidChangeConfiguration(() => {
@ -64,15 +64,15 @@ export function activate(context: vscode.ExtensionContext) {
function registerMarkdownLanguageFeatures(
parser: IMdParser,
workspaceContents: MdWorkspaceContents,
workspace: IMdWorkspace,
commandManager: CommandManager,
tocProvider: MdTableOfContentsProvider,
logger: ILogger,
): vscode.Disposable {
const selector: vscode.DocumentSelector = { language: 'markdown', scheme: '*' };
const linkProvider = new MdLinkProvider(parser, workspaceContents, logger);
const referencesProvider = new MdReferencesProvider(parser, workspaceContents, tocProvider, logger);
const linkProvider = new MdLinkProvider(parser, workspace, logger);
const referencesProvider = new MdReferencesProvider(parser, workspace, tocProvider, logger);
const symbolProvider = new MdDocumentSymbolProvider(tocProvider, logger);
return vscode.Disposable.from(
@ -81,7 +81,7 @@ function registerMarkdownLanguageFeatures(
// Language features
registerDefinitionSupport(selector, referencesProvider),
registerDiagnosticSupport(selector, workspaceContents, linkProvider, commandManager, referencesProvider, tocProvider, logger),
registerDiagnosticSupport(selector, workspace, linkProvider, commandManager, referencesProvider, tocProvider, logger),
registerDocumentLinkSupport(selector, linkProvider),
registerDocumentSymbolSupport(selector, tocProvider, logger),
registerDropIntoEditorSupport(selector),
@ -90,9 +90,9 @@ function registerMarkdownLanguageFeatures(
registerPasteSupport(selector),
registerPathCompletionSupport(selector, parser, linkProvider),
registerReferencesSupport(selector, referencesProvider),
registerRenameSupport(selector, workspaceContents, referencesProvider, parser.slugifier),
registerRenameSupport(selector, workspace, referencesProvider, parser.slugifier),
registerSmartSelectSupport(selector, parser, tocProvider),
registerWorkspaceSymbolSupport(workspaceContents, symbolProvider),
registerWorkspaceSymbolSupport(workspace, symbolProvider),
);
}

View file

@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import { SkinnyTextDocument } from '../workspaceContents';
import { ITextDocument } from '../types/textDocument';
import { MdReferencesProvider } from './references';
export class MdVsCodeDefinitionProvider implements vscode.DefinitionProvider {
@ -12,7 +12,7 @@ export class MdVsCodeDefinitionProvider implements vscode.DefinitionProvider {
private readonly referencesProvider: MdReferencesProvider,
) { }
async provideDefinition(document: SkinnyTextDocument, position: vscode.Position, token: vscode.CancellationToken): Promise<vscode.Definition | undefined> {
async provideDefinition(document: ITextDocument, position: vscode.Position, token: vscode.CancellationToken): Promise<vscode.Definition | undefined> {
const allRefs = await this.referencesProvider.getReferencesAtPosition(document, position, token);
return allRefs.find(ref => ref.kind === 'link' && ref.isDefinition)?.location;

View file

@ -9,6 +9,7 @@ import * as nls from 'vscode-nls';
import { CommandManager } from '../commandManager';
import { ILogger } from '../logging';
import { MdTableOfContentsProvider } from '../tableOfContents';
import { ITextDocument } from '../types/textDocument';
import { Delayer } from '../util/async';
import { noopToken } from '../util/cancellation';
import { Disposable } from '../util/dispose';
@ -16,7 +17,7 @@ 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 { IMdWorkspace } from '../workspace';
import { InternalHref, LinkDefinitionSet, MdLink, MdLinkProvider, MdLinkSource } from './documentLinks';
import { MdReferencesProvider, tryResolveLinkPath } from './references';
@ -305,7 +306,7 @@ export class DiagnosticManager extends Disposable {
public readonly ready: Promise<void>;
constructor(
private readonly workspaceContents: MdWorkspaceContents,
private readonly workspace: IMdWorkspace,
private readonly computer: DiagnosticComputer,
private readonly configuration: DiagnosticConfiguration,
private readonly reporter: DiagnosticReporter,
@ -322,17 +323,17 @@ export class DiagnosticManager extends Disposable {
this.rebuild();
}));
this._register(workspaceContents.onDidCreateMarkdownDocument(doc => {
this._register(workspace.onDidCreateMarkdownDocument(doc => {
this.triggerDiagnostics(doc.uri);
// Links in other files may have become valid
this.triggerForReferencingFiles(doc.uri);
}));
this._register(workspaceContents.onDidChangeMarkdownDocument(doc => {
this._register(workspace.onDidChangeMarkdownDocument(doc => {
this.triggerDiagnostics(doc.uri);
}));
this._register(workspaceContents.onDidDeleteMarkdownDocument(uri => {
this._register(workspace.onDidDeleteMarkdownDocument(uri => {
this.triggerForReferencingFiles(uri);
}));
@ -352,7 +353,7 @@ export class DiagnosticManager extends Disposable {
}
}));
this.tableOfContentsWatcher = this._register(new MdTableOfContentsWatcher(workspaceContents, tocProvider, delay / 2));
this.tableOfContentsWatcher = this._register(new MdTableOfContentsWatcher(workspace, tocProvider, delay / 2));
this._register(this.tableOfContentsWatcher.onTocChanged(e => {
return this.triggerForReferencingFiles(e.uri);
}));
@ -379,7 +380,7 @@ export class DiagnosticManager extends Disposable {
this.pendingDiagnostics.clear();
}
private async recomputeDiagnosticState(doc: SkinnyTextDocument, token: vscode.CancellationToken): Promise<{ diagnostics: readonly vscode.Diagnostic[]; links: readonly MdLink[]; config: DiagnosticOptions }> {
private async recomputeDiagnosticState(doc: ITextDocument, token: vscode.CancellationToken): Promise<{ diagnostics: readonly vscode.Diagnostic[]; links: readonly MdLink[]; config: DiagnosticOptions }> {
this.logger.verbose('DiagnosticManager', `recomputeDiagnosticState - ${doc.uri}`);
const config = this.configuration.getOptions(doc.uri);
@ -394,7 +395,7 @@ export class DiagnosticManager extends Disposable {
this.pendingDiagnostics.clear();
await Promise.all(pending.map(async resource => {
const doc = await this.workspaceContents.getOrLoadMarkdownDocument(resource);
const doc = await this.workspace.getOrLoadMarkdownDocument(resource);
if (doc) {
await this.inFlightDiagnostics.trigger(doc.uri, async (token) => {
if (this.reporter.areDiagnosticsEnabled(doc.uri)) {
@ -419,7 +420,7 @@ export class DiagnosticManager extends Disposable {
(async () => {
// TODO: This pulls in all md files in the workspace. Instead we only care about opened text documents.
// Need a new way to handle that.
const allDocs = await this.workspaceContents.getAllMarkdownDocuments();
const allDocs = await this.workspace.getAllMarkdownDocuments();
await Promise.all(Array.from(allDocs, doc => this.triggerDiagnostics(doc.uri)));
})()
);
@ -475,12 +476,12 @@ class FileLinkMap {
export class DiagnosticComputer {
constructor(
private readonly workspaceContents: MdWorkspaceContents,
private readonly workspace: IMdWorkspace,
private readonly linkProvider: MdLinkProvider,
private readonly tocProvider: MdTableOfContentsProvider,
) { }
public async getDiagnostics(doc: SkinnyTextDocument, options: DiagnosticOptions, token: vscode.CancellationToken): Promise<{ readonly diagnostics: vscode.Diagnostic[]; readonly links: readonly MdLink[] }> {
public async getDiagnostics(doc: ITextDocument, options: DiagnosticOptions, token: vscode.CancellationToken): Promise<{ readonly diagnostics: vscode.Diagnostic[]; readonly links: readonly MdLink[] }> {
const { links, definitions } = await this.linkProvider.getLinks(doc);
if (token.isCancellationRequested || !options.enabled) {
return { links, diagnostics: [] };
@ -496,7 +497,7 @@ export class DiagnosticComputer {
};
}
private async validateFragmentLinks(doc: SkinnyTextDocument, options: DiagnosticOptions, links: readonly MdLink[], token: vscode.CancellationToken): Promise<vscode.Diagnostic[]> {
private async validateFragmentLinks(doc: ITextDocument, options: DiagnosticOptions, links: readonly MdLink[], token: vscode.CancellationToken): Promise<vscode.Diagnostic[]> {
const severity = toSeverity(options.validateFragmentLinks);
if (typeof severity === 'undefined') {
return [];
@ -567,7 +568,7 @@ export class DiagnosticComputer {
return;
}
const resolvedHrefPath = await tryResolveLinkPath(path, this.workspaceContents);
const resolvedHrefPath = await tryResolveLinkPath(path, this.workspace);
if (!resolvedHrefPath) {
const msg = localize('invalidPathLink', 'File does not exist at path: {0}', path.fsPath);
for (const link of links) {
@ -595,7 +596,7 @@ export class DiagnosticComputer {
}
private isMarkdownPath(resolvedHrefPath: vscode.Uri) {
return this.workspaceContents.hasMarkdownDocument(resolvedHrefPath) || looksLikeMarkdownPath(resolvedHrefPath);
return this.workspace.hasMarkdownDocument(resolvedHrefPath) || looksLikeMarkdownPath(resolvedHrefPath);
}
private isIgnoredLink(options: DiagnosticOptions, link: string): boolean {
@ -652,7 +653,7 @@ class AddToIgnoreLinksQuickFixProvider implements vscode.CodeActionProvider {
export function registerDiagnosticSupport(
selector: vscode.DocumentSelector,
workspaceContents: MdWorkspaceContents,
workspace: IMdWorkspace,
linkProvider: MdLinkProvider,
commandManager: CommandManager,
referenceProvider: MdReferencesProvider,
@ -661,8 +662,8 @@ export function registerDiagnosticSupport(
): vscode.Disposable {
const configuration = new VSCodeDiagnosticConfiguration();
const manager = new DiagnosticManager(
workspaceContents,
new DiagnosticComputer(workspaceContents, linkProvider, tocProvider),
workspace,
new DiagnosticComputer(workspace, linkProvider, tocProvider),
configuration,
new DiagnosticCollectionReporter(),
referenceProvider,

View file

@ -7,14 +7,15 @@ import * as vscode from 'vscode';
import * as nls from 'vscode-nls';
import * as uri from 'vscode-uri';
import { OpenDocumentLinkCommand } from '../commands/openDocumentLink';
import { ILogger } from '../logging';
import { IMdParser } from '../markdownEngine';
import { ITextDocument } from '../types/textDocument';
import { coalesce } from '../util/arrays';
import { noopToken } from '../util/cancellation';
import { Disposable } from '../util/dispose';
import { getUriForLinkWithKnownExternalScheme, isOfScheme, Schemes } from '../util/schemes';
import { MdWorkspaceContents, SkinnyTextDocument } from '../workspaceContents';
import { MdDocumentInfoCache } from '../util/workspaceCache';
import { ILogger } from '../logging';
import { IMdWorkspace } from '../workspace';
const localize = nls.loadMessageBundle();
@ -38,7 +39,7 @@ export type LinkHref = ExternalHref | InternalHref | ReferenceHref;
function parseLink(
document: SkinnyTextDocument,
document: ITextDocument,
link: string,
): ExternalHref | InternalHref | undefined {
const cleanLink = stripAngleBrackets(link);
@ -91,7 +92,7 @@ function parseLink(
};
}
function getWorkspaceFolder(document: SkinnyTextDocument) {
function getWorkspaceFolder(document: ITextDocument) {
return vscode.workspace.getWorkspaceFolder(document.uri)?.uri
|| vscode.workspace.workspaceFolders?.[0]?.uri;
}
@ -131,7 +132,7 @@ export interface MdLinkDefinition {
export type MdLink = MdInlineLink | MdLinkDefinition;
function extractDocumentLink(
document: SkinnyTextDocument,
document: ITextDocument,
pre: string,
rawLink: string,
matchIndex: number | undefined
@ -170,7 +171,7 @@ function getFragmentRange(text: string, start: vscode.Position, end: vscode.Posi
return new vscode.Range(start.translate({ characterDelta: index + 1 }), end);
}
function getLinkSourceFragmentInfo(document: SkinnyTextDocument, link: string, linkStart: vscode.Position, linkEnd: vscode.Position): { fragmentRange: vscode.Range | undefined; pathText: string } {
function getLinkSourceFragmentInfo(document: ITextDocument, link: string, linkStart: vscode.Position, linkEnd: vscode.Position): { fragmentRange: vscode.Range | undefined; pathText: string } {
const fragmentRange = getFragmentRange(link, linkStart, linkEnd);
return {
pathText: document.getText(new vscode.Range(linkStart, fragmentRange ? fragmentRange.start.translate(0, -1) : linkEnd)),
@ -234,7 +235,7 @@ const definitionPattern = /^([\t ]*\[(?!\^)((?:\\\]|[^\]])+)\]:\s*)([^<]\S*|<[^>
const inlineCodePattern = /(?:^|[^`])(`+)(?:.+?|.*?(?:(?:\r?\n).+?)*?)(?:\r?\n)?\1(?:$|[^`])/gm;
class NoLinkRanges {
public static async compute(tokenizer: IMdParser, document: SkinnyTextDocument): Promise<NoLinkRanges> {
public static async compute(tokenizer: IMdParser, document: ITextDocument): Promise<NoLinkRanges> {
const tokens = await tokenizer.tokenize(document);
const multiline = tokens.filter(t => (t.type === 'code_block' || t.type === 'fence' || t.type === 'html_block') && !!t.map).map(t => t.map) as [number, number][];
@ -274,7 +275,7 @@ export class MdLinkComputer {
private readonly tokenizer: IMdParser,
) { }
public async getAllLinks(document: SkinnyTextDocument, token: vscode.CancellationToken): Promise<MdLink[]> {
public async getAllLinks(document: ITextDocument, token: vscode.CancellationToken): Promise<MdLink[]> {
const noLinkRanges = await NoLinkRanges.compute(this.tokenizer, document);
if (token.isCancellationRequested) {
return [];
@ -288,7 +289,7 @@ export class MdLinkComputer {
]);
}
private *getInlineLinks(document: SkinnyTextDocument, noLinkRanges: NoLinkRanges): Iterable<MdLink> {
private *getInlineLinks(document: ITextDocument, noLinkRanges: NoLinkRanges): Iterable<MdLink> {
const text = document.getText();
for (const match of text.matchAll(linkPattern)) {
const matchLinkData = extractDocumentLink(document, match[1], match[2], match.index);
@ -306,7 +307,7 @@ export class MdLinkComputer {
}
}
private * getAutoLinks(document: SkinnyTextDocument, noLinkRanges: NoLinkRanges): Iterable<MdLink> {
private * getAutoLinks(document: ITextDocument, noLinkRanges: NoLinkRanges): Iterable<MdLink> {
const text = document.getText();
for (const match of text.matchAll(autoLinkPattern)) {
@ -334,7 +335,7 @@ export class MdLinkComputer {
}
}
private *getReferenceLinks(document: SkinnyTextDocument, noLinkRanges: NoLinkRanges): Iterable<MdLink> {
private *getReferenceLinks(document: ITextDocument, noLinkRanges: NoLinkRanges): Iterable<MdLink> {
const text = document.getText();
for (const match of text.matchAll(referenceLinkPattern)) {
let linkStart: vscode.Position;
@ -382,7 +383,7 @@ export class MdLinkComputer {
}
}
private *getLinkDefinitions(document: SkinnyTextDocument, noLinkRanges: NoLinkRanges): Iterable<MdLinkDefinition> {
private *getLinkDefinitions(document: ITextDocument, noLinkRanges: NoLinkRanges): Iterable<MdLinkDefinition> {
const text = document.getText();
for (const match of text.matchAll(definitionPattern)) {
const pre = match[1];
@ -443,12 +444,12 @@ export class MdLinkProvider extends Disposable {
constructor(
tokenizer: IMdParser,
workspaceContents: MdWorkspaceContents,
workspace: IMdWorkspace,
logger: ILogger,
) {
super();
this.linkComputer = new MdLinkComputer(tokenizer);
this._linkCache = this._register(new MdDocumentInfoCache(workspaceContents, async doc => {
this._linkCache = this._register(new MdDocumentInfoCache(workspace, async doc => {
logger.verbose('LinkProvider', `compute - ${doc.uri}`);
const links = await this.linkComputer.getAllLinks(doc, noopToken);
@ -459,7 +460,7 @@ export class MdLinkProvider extends Disposable {
}));
}
public async getLinks(document: SkinnyTextDocument): Promise<MdDocumentLinks> {
public async getLinks(document: ITextDocument): Promise<MdDocumentLinks> {
return this._linkCache.getForDocument(document);
}
}
@ -491,7 +492,7 @@ export class MdVsCodeLinkProvider implements vscode.DocumentLinkProvider {
) { }
public async provideDocumentLinks(
document: SkinnyTextDocument,
document: ITextDocument,
token: vscode.CancellationToken
): Promise<vscode.DocumentLink[]> {
const { links, definitions } = await this._linkProvider.getLinks(document);

View file

@ -6,7 +6,7 @@
import * as vscode from 'vscode';
import { ILogger } from '../logging';
import { MdTableOfContentsProvider, TocEntry } from '../tableOfContents';
import { SkinnyTextDocument } from '../workspaceContents';
import { ITextDocument } from '../types/textDocument';
interface MarkdownSymbol {
readonly level: number;
@ -21,13 +21,13 @@ export class MdDocumentSymbolProvider implements vscode.DocumentSymbolProvider {
private readonly logger: ILogger,
) { }
public async provideDocumentSymbolInformation(document: SkinnyTextDocument): Promise<vscode.SymbolInformation[]> {
public async provideDocumentSymbolInformation(document: ITextDocument): Promise<vscode.SymbolInformation[]> {
this.logger.verbose('DocumentSymbolProvider', `provideDocumentSymbolInformation - ${document.uri}`);
const toc = await this.tocProvider.getForDocument(document);
return toc.entries.map(entry => this.toSymbolInformation(entry));
}
public async provideDocumentSymbols(document: SkinnyTextDocument): Promise<vscode.DocumentSymbol[]> {
public async provideDocumentSymbols(document: ITextDocument): Promise<vscode.DocumentSymbol[]> {
const toc = await this.tocProvider.getForDocument(document);
const root: MarkdownSymbol = {
level: -Infinity,

View file

@ -7,7 +7,7 @@ import type Token = require('markdown-it/lib/token');
import * as vscode from 'vscode';
import { IMdParser } from '../markdownEngine';
import { MdTableOfContentsProvider } from '../tableOfContents';
import { SkinnyTextDocument } from '../workspaceContents';
import { ITextDocument } from '../types/textDocument';
const rangeLimit = 5000;
@ -23,7 +23,7 @@ export class MdFoldingProvider implements vscode.FoldingRangeProvider {
) { }
public async provideFoldingRanges(
document: SkinnyTextDocument,
document: ITextDocument,
_: vscode.FoldingContext,
_token: vscode.CancellationToken
): Promise<vscode.FoldingRange[]> {
@ -35,7 +35,7 @@ export class MdFoldingProvider implements vscode.FoldingRangeProvider {
return foldables.flat().slice(0, rangeLimit);
}
private async getRegions(document: SkinnyTextDocument): Promise<vscode.FoldingRange[]> {
private async getRegions(document: ITextDocument): Promise<vscode.FoldingRange[]> {
const tokens = await this.parser.tokenize(document);
const regionMarkers = tokens.filter(isRegionMarker)
.map(token => ({ line: token.map[0], isStart: isStartRegion(token.content) }));
@ -55,7 +55,7 @@ export class MdFoldingProvider implements vscode.FoldingRangeProvider {
.filter((region: vscode.FoldingRange | null): region is vscode.FoldingRange => !!region);
}
private async getHeaderFoldingRanges(document: SkinnyTextDocument): Promise<vscode.FoldingRange[]> {
private async getHeaderFoldingRanges(document: ITextDocument): Promise<vscode.FoldingRange[]> {
const toc = await this.tocProvide.getForDocument(document);
return toc.entries.map(entry => {
let endLine = entry.sectionLocation.range.end.line;
@ -66,7 +66,7 @@ export class MdFoldingProvider implements vscode.FoldingRangeProvider {
});
}
private async getBlockFoldingRanges(document: SkinnyTextDocument): Promise<vscode.FoldingRange[]> {
private async getBlockFoldingRanges(document: ITextDocument): Promise<vscode.FoldingRange[]> {
const tokens = await this.parser.tokenize(document);
const multiLineListItems = tokens.filter(isFoldableToken);
return multiLineListItems.map(listItem => {

View file

@ -7,8 +7,8 @@ import { dirname, resolve } from 'path';
import * as vscode from 'vscode';
import { IMdParser } from '../markdownEngine';
import { TableOfContents } from '../tableOfContents';
import { ITextDocument } from '../types/textDocument';
import { resolveUriToMarkdownFile } from '../util/openDocumentLink';
import { SkinnyTextDocument } from '../workspaceContents';
import { MdLinkProvider } from './documentLinks';
enum CompletionContextKind {
@ -86,7 +86,7 @@ export class MdVsCodePathCompletionProvider implements vscode.CompletionItemProv
private readonly linkProvider: MdLinkProvider,
) { }
public async provideCompletionItems(document: SkinnyTextDocument, position: vscode.Position, _token: vscode.CancellationToken, _context: vscode.CompletionContext): Promise<vscode.CompletionItem[]> {
public async provideCompletionItems(document: ITextDocument, position: vscode.Position, _token: vscode.CancellationToken, _context: vscode.CompletionContext): Promise<vscode.CompletionItem[]> {
if (!this.arePathSuggestionEnabled(document)) {
return [];
}
@ -144,7 +144,7 @@ export class MdVsCodePathCompletionProvider implements vscode.CompletionItemProv
}
}
private arePathSuggestionEnabled(document: SkinnyTextDocument): boolean {
private arePathSuggestionEnabled(document: ITextDocument): boolean {
const config = vscode.workspace.getConfiguration('markdown', document.uri);
return config.get('suggest.paths.enabled', true);
}
@ -158,7 +158,7 @@ export class MdVsCodePathCompletionProvider implements vscode.CompletionItemProv
/// [id]: |
private readonly definitionPattern = /^\s*\[[\w\-]+\]:\s*([^\s]*)$/m;
private getPathCompletionContext(document: SkinnyTextDocument, position: vscode.Position): CompletionContext | undefined {
private getPathCompletionContext(document: ITextDocument, position: vscode.Position): CompletionContext | undefined {
const line = document.lineAt(position.line).text;
const linePrefixText = line.slice(0, position.character);
@ -231,7 +231,7 @@ export class MdVsCodePathCompletionProvider implements vscode.CompletionItemProv
};
}
private async *provideReferenceSuggestions(document: SkinnyTextDocument, position: vscode.Position, context: CompletionContext): AsyncIterable<vscode.CompletionItem> {
private async *provideReferenceSuggestions(document: ITextDocument, position: vscode.Position, context: CompletionContext): AsyncIterable<vscode.CompletionItem> {
const insertionRange = new vscode.Range(context.linkTextStartPosition, position);
const replacementRange = new vscode.Range(insertionRange.start, position.translate({ characterDelta: context.linkSuffix.length }));
@ -248,7 +248,7 @@ export class MdVsCodePathCompletionProvider implements vscode.CompletionItemProv
}
}
private async *provideHeaderSuggestions(document: SkinnyTextDocument, position: vscode.Position, context: CompletionContext, insertionRange: vscode.Range): AsyncIterable<vscode.CompletionItem> {
private async *provideHeaderSuggestions(document: ITextDocument, position: vscode.Position, context: CompletionContext, insertionRange: vscode.Range): AsyncIterable<vscode.CompletionItem> {
const toc = await TableOfContents.createForDocumentOrNotebook(this.parser, document);
for (const entry of toc.entries) {
const replacementRange = new vscode.Range(insertionRange.start, position.translate({ characterDelta: context.linkSuffix.length }));
@ -263,7 +263,7 @@ export class MdVsCodePathCompletionProvider implements vscode.CompletionItemProv
}
}
private async *providePathSuggestions(document: SkinnyTextDocument, position: vscode.Position, context: CompletionContext): AsyncIterable<vscode.CompletionItem> {
private async *providePathSuggestions(document: ITextDocument, position: vscode.Position, context: CompletionContext): AsyncIterable<vscode.CompletionItem> {
const valueBeforeLastSlash = context.linkPrefix.substring(0, context.linkPrefix.lastIndexOf('/') + 1); // keep the last slash
const parentDir = this.resolveReference(document, valueBeforeLastSlash || '.');
@ -304,7 +304,7 @@ export class MdVsCodePathCompletionProvider implements vscode.CompletionItemProv
}
}
private resolveReference(document: SkinnyTextDocument, ref: string): vscode.Uri | undefined {
private resolveReference(document: ITextDocument, ref: string): vscode.Uri | undefined {
const docUri = this.getFileUriOfTextDocument(document);
if (ref.startsWith('/')) {
@ -333,7 +333,7 @@ export class MdVsCodePathCompletionProvider implements vscode.CompletionItemProv
}
}
private getFileUriOfTextDocument(document: SkinnyTextDocument) {
private getFileUriOfTextDocument(document: ITextDocument) {
if (document.uri.scheme === 'vscode-notebook-cell') {
const notebook = vscode.workspace.notebookDocuments
.find(notebook => notebook.getCells().some(cell => cell.document === document));

View file

@ -7,11 +7,12 @@ import * as uri from 'vscode-uri';
import { ILogger } from '../logging';
import { IMdParser } from '../markdownEngine';
import { MdTableOfContentsProvider, TocEntry } from '../tableOfContents';
import { ITextDocument } from '../types/textDocument';
import { noopToken } from '../util/cancellation';
import { Disposable } from '../util/dispose';
import { looksLikeMarkdownPath } from '../util/file';
import { MdWorkspaceInfoCache } from '../util/workspaceCache';
import { MdWorkspaceContents, SkinnyTextDocument } from '../workspaceContents';
import { IMdWorkspace } from '../workspace';
import { InternalHref, MdLink, MdLinkComputer } from './documentLinks';
@ -70,17 +71,17 @@ export class MdReferencesProvider extends Disposable {
public constructor(
private readonly parser: IMdParser,
private readonly workspaceContents: MdWorkspaceContents,
private readonly workspace: IMdWorkspace,
private readonly tocProvider: MdTableOfContentsProvider,
private readonly logger: ILogger,
) {
super();
this._linkComputer = new MdLinkComputer(parser);
this._linkCache = this._register(new MdWorkspaceInfoCache(workspaceContents, doc => this._linkComputer.getAllLinks(doc, noopToken)));
this._linkCache = this._register(new MdWorkspaceInfoCache(workspace, doc => this._linkComputer.getAllLinks(doc, noopToken)));
}
public async getReferencesAtPosition(document: SkinnyTextDocument, position: vscode.Position, token: vscode.CancellationToken): Promise<MdReference[]> {
public async getReferencesAtPosition(document: ITextDocument, position: vscode.Position, token: vscode.CancellationToken): Promise<MdReference[]> {
this.logger.verbose('ReferencesProvider', `getReferencesAtPosition: ${document.uri}`);
const toc = await this.tocProvider.getForDocument(document);
@ -103,7 +104,7 @@ export class MdReferencesProvider extends Disposable {
return Array.from(this.findAllLinksToFile(resource, allLinksInWorkspace, undefined));
}
private async getReferencesToHeader(document: SkinnyTextDocument, header: TocEntry): Promise<MdReference[]> {
private async getReferencesToHeader(document: ITextDocument, header: TocEntry): Promise<MdReference[]> {
const links = (await this._linkCache.values()).flat();
const references: MdReference[] = [];
@ -135,7 +136,7 @@ export class MdReferencesProvider extends Disposable {
return references;
}
private async getReferencesToLinkAtPosition(document: SkinnyTextDocument, position: vscode.Position, token: vscode.CancellationToken): Promise<MdReference[]> {
private async getReferencesToLinkAtPosition(document: ITextDocument, position: vscode.Position, token: vscode.CancellationToken): Promise<MdReference[]> {
const docLinks = await this._linkComputer.getAllLinks(document, token);
for (const link of docLinks) {
@ -184,7 +185,7 @@ export class MdReferencesProvider extends Disposable {
return references;
}
const resolvedResource = await tryResolveLinkPath(sourceLink.href.path, this.workspaceContents);
const resolvedResource = await tryResolveLinkPath(sourceLink.href.path, this.workspace);
if (token.isCancellationRequested) {
return [];
}
@ -229,7 +230,7 @@ export class MdReferencesProvider extends Disposable {
}
private isMarkdownPath(resolvedHrefPath: vscode.Uri) {
return this.workspaceContents.hasMarkdownDocument(resolvedHrefPath) || looksLikeMarkdownPath(resolvedHrefPath);
return this.workspace.hasMarkdownDocument(resolvedHrefPath) || looksLikeMarkdownPath(resolvedHrefPath);
}
private looksLikeLinkToDoc(href: InternalHref, targetDoc: vscode.Uri) {
@ -306,7 +307,7 @@ export class MdVsCodeReferencesProvider implements vscode.ReferenceProvider {
private readonly referencesProvider: MdReferencesProvider
) { }
async provideReferences(document: SkinnyTextDocument, position: vscode.Position, context: vscode.ReferenceContext, token: vscode.CancellationToken): Promise<vscode.Location[]> {
async provideReferences(document: ITextDocument, position: vscode.Position, context: vscode.ReferenceContext, token: vscode.CancellationToken): Promise<vscode.Location[]> {
const allRefs = await this.referencesProvider.getReferencesAtPosition(document, position, token);
return allRefs
.filter(ref => context.includeDeclaration || !ref.isDefinition)
@ -321,15 +322,15 @@ export function registerReferencesSupport(
return vscode.languages.registerReferenceProvider(selector, new MdVsCodeReferencesProvider(referencesProvider));
}
export async function tryResolveLinkPath(originalUri: vscode.Uri, workspaceContents: MdWorkspaceContents): Promise<vscode.Uri | undefined> {
if (await workspaceContents.pathExists(originalUri)) {
export async function tryResolveLinkPath(originalUri: vscode.Uri, workspace: IMdWorkspace): Promise<vscode.Uri | undefined> {
if (await workspace.pathExists(originalUri)) {
return originalUri;
}
// We don't think the file exists. If it doesn't already have an extension, try tacking on a `.md` and using that instead
if (uri.Utils.extname(originalUri) === '') {
const dotMdResource = originalUri.with({ path: originalUri.path + '.md' });
if (await workspaceContents.pathExists(dotMdResource)) {
if (await workspace.pathExists(dotMdResource)) {
return dotMdResource;
}
}

View file

@ -7,9 +7,10 @@ import * as vscode from 'vscode';
import * as nls from 'vscode-nls';
import * as URI from 'vscode-uri';
import { Slugifier } from '../slugify';
import { ITextDocument } from '../types/textDocument';
import { Disposable } from '../util/dispose';
import { resolveDocumentLink } from '../util/openDocumentLink';
import { MdWorkspaceContents, SkinnyTextDocument } from '../workspaceContents';
import { IMdWorkspace } from '../workspace';
import { InternalHref } from './documentLinks';
import { MdHeaderReference, MdLinkReference, MdReference, MdReferencesProvider, tryResolveLinkPath } from './references';
@ -58,14 +59,14 @@ export class MdVsCodeRenameProvider extends Disposable implements vscode.RenameP
private readonly renameNotSupportedText = localize('invalidRenameLocation', "Rename not supported at location");
public constructor(
private readonly workspaceContents: MdWorkspaceContents,
private readonly workspace: IMdWorkspace,
private readonly referencesProvider: MdReferencesProvider,
private readonly slugifier: Slugifier,
) {
super();
}
public async prepareRename(document: SkinnyTextDocument, position: vscode.Position, token: vscode.CancellationToken): Promise<undefined | { readonly range: vscode.Range; readonly placeholder: string }> {
public async prepareRename(document: ITextDocument, position: vscode.Position, token: vscode.CancellationToken): Promise<undefined | { readonly range: vscode.Range; readonly placeholder: string }> {
const allRefsInfo = await this.getAllReferences(document, position, token);
if (token.isCancellationRequested) {
return undefined;
@ -122,11 +123,11 @@ export class MdVsCodeRenameProvider extends Disposable implements vscode.RenameP
return references.find(ref => ref.isDefinition && ref.kind === 'header') as MdHeaderReference | undefined;
}
public async provideRenameEdits(document: SkinnyTextDocument, position: vscode.Position, newName: string, token: vscode.CancellationToken): Promise<vscode.WorkspaceEdit | undefined> {
public async provideRenameEdits(document: ITextDocument, position: vscode.Position, newName: string, token: vscode.CancellationToken): Promise<vscode.WorkspaceEdit | undefined> {
return (await this.provideRenameEditsImpl(document, position, newName, token))?.edit;
}
public async provideRenameEditsImpl(document: SkinnyTextDocument, position: vscode.Position, newName: string, token: vscode.CancellationToken): Promise<MdWorkspaceEdit | undefined> {
public async provideRenameEditsImpl(document: ITextDocument, position: vscode.Position, newName: string, token: vscode.CancellationToken): Promise<MdWorkspaceEdit | undefined> {
const allRefsInfo = await this.getAllReferences(document, position, token);
if (token.isCancellationRequested || !allRefsInfo || !allRefsInfo.references.length) {
return undefined;
@ -153,7 +154,7 @@ export class MdVsCodeRenameProvider extends Disposable implements vscode.RenameP
const edit = new vscode.WorkspaceEdit();
const fileRenames: MdFileRenameEdit[] = [];
const targetUri = await tryResolveLinkPath(triggerHref.path, this.workspaceContents) ?? triggerHref.path;
const targetUri = await tryResolveLinkPath(triggerHref.path, this.workspace) ?? triggerHref.path;
const rawNewFilePath = resolveDocumentLink(newName, triggerDocument);
let resolvedNewFilePath = rawNewFilePath;
@ -168,7 +169,7 @@ export class MdVsCodeRenameProvider extends Disposable implements vscode.RenameP
}
// First rename the file
if (await this.workspaceContents.pathExists(targetUri)) {
if (await this.workspace.pathExists(targetUri)) {
fileRenames.push({ from: targetUri, to: resolvedNewFilePath });
edit.renameFile(targetUri, resolvedNewFilePath);
}
@ -241,7 +242,7 @@ export class MdVsCodeRenameProvider extends Disposable implements vscode.RenameP
return { edit };
}
private async getAllReferences(document: SkinnyTextDocument, position: vscode.Position, token: vscode.CancellationToken): Promise<MdReferencesResponse | undefined> {
private async getAllReferences(document: ITextDocument, position: vscode.Position, token: vscode.CancellationToken): Promise<MdReferencesResponse | undefined> {
const version = document.version;
if (this.cachedRefs
@ -272,9 +273,9 @@ export class MdVsCodeRenameProvider extends Disposable implements vscode.RenameP
export function registerRenameSupport(
selector: vscode.DocumentSelector,
workspaceContents: MdWorkspaceContents,
workspace: IMdWorkspace,
referencesProvider: MdReferencesProvider,
slugifier: Slugifier,
): vscode.Disposable {
return vscode.languages.registerRenameProvider(selector, new MdVsCodeRenameProvider(workspaceContents, referencesProvider, slugifier));
return vscode.languages.registerRenameProvider(selector, new MdVsCodeRenameProvider(workspace, referencesProvider, slugifier));
}

View file

@ -6,7 +6,7 @@ import Token = require('markdown-it/lib/token');
import * as vscode from 'vscode';
import { IMdParser } from '../markdownEngine';
import { MdTableOfContentsProvider, TocEntry } from '../tableOfContents';
import { SkinnyTextDocument } from '../workspaceContents';
import { ITextDocument } from '../types/textDocument';
interface MarkdownItTokenWithMap extends Token {
map: [number, number];
@ -19,24 +19,24 @@ export class MdSmartSelect implements vscode.SelectionRangeProvider {
private readonly tocProvider: MdTableOfContentsProvider,
) { }
public async provideSelectionRanges(document: SkinnyTextDocument, positions: vscode.Position[], _token: vscode.CancellationToken): Promise<vscode.SelectionRange[] | undefined> {
public async provideSelectionRanges(document: ITextDocument, positions: vscode.Position[], _token: vscode.CancellationToken): Promise<vscode.SelectionRange[] | undefined> {
const promises = await Promise.all(positions.map((position) => {
return this.provideSelectionRange(document, position, _token);
}));
return promises.filter(item => item !== undefined) as vscode.SelectionRange[];
}
private async provideSelectionRange(document: SkinnyTextDocument, position: vscode.Position, _token: vscode.CancellationToken): Promise<vscode.SelectionRange | undefined> {
private async provideSelectionRange(document: ITextDocument, position: vscode.Position, _token: vscode.CancellationToken): Promise<vscode.SelectionRange | undefined> {
const headerRange = await this.getHeaderSelectionRange(document, position);
const blockRange = await this.getBlockSelectionRange(document, position, headerRange);
const inlineRange = await this.getInlineSelectionRange(document, position, blockRange);
return inlineRange || blockRange || headerRange;
}
private async getInlineSelectionRange(document: SkinnyTextDocument, position: vscode.Position, blockRange?: vscode.SelectionRange): Promise<vscode.SelectionRange | undefined> {
private async getInlineSelectionRange(document: ITextDocument, position: vscode.Position, blockRange?: vscode.SelectionRange): Promise<vscode.SelectionRange | undefined> {
return createInlineRange(document, position, blockRange);
}
private async getBlockSelectionRange(document: SkinnyTextDocument, position: vscode.Position, headerRange?: vscode.SelectionRange): Promise<vscode.SelectionRange | undefined> {
private async getBlockSelectionRange(document: ITextDocument, position: vscode.Position, headerRange?: vscode.SelectionRange): Promise<vscode.SelectionRange | undefined> {
const tokens = await this.parser.tokenize(document);
const blockTokens = getBlockTokensForPosition(tokens, position, headerRange);
@ -52,7 +52,7 @@ export class MdSmartSelect implements vscode.SelectionRangeProvider {
return currentRange;
}
private async getHeaderSelectionRange(document: SkinnyTextDocument, position: vscode.Position): Promise<vscode.SelectionRange | undefined> {
private async getHeaderSelectionRange(document: ITextDocument, position: vscode.Position): Promise<vscode.SelectionRange | undefined> {
const toc = await this.tocProvider.getForDocument(document);
const headerInfo = getHeadersForPosition(toc.entries, position);
@ -107,7 +107,7 @@ function getBlockTokensForPosition(tokens: Token[], position: vscode.Position, p
return sortedTokens;
}
function createBlockRange(block: MarkdownItTokenWithMap, document: SkinnyTextDocument, cursorLine: number, parent?: vscode.SelectionRange): vscode.SelectionRange | undefined {
function createBlockRange(block: MarkdownItTokenWithMap, document: ITextDocument, cursorLine: number, parent?: vscode.SelectionRange): vscode.SelectionRange | undefined {
if (block.type === 'fence') {
return createFencedRange(block, cursorLine, document, parent);
} else {
@ -129,7 +129,7 @@ function createBlockRange(block: MarkdownItTokenWithMap, document: SkinnyTextDoc
}
}
function createInlineRange(document: SkinnyTextDocument, cursorPosition: vscode.Position, parent?: vscode.SelectionRange): vscode.SelectionRange | undefined {
function createInlineRange(document: ITextDocument, cursorPosition: vscode.Position, parent?: vscode.SelectionRange): vscode.SelectionRange | undefined {
const lineText = document.lineAt(cursorPosition.line).text;
const boldSelection = createBoldRange(lineText, cursorPosition.character, cursorPosition.line, parent);
const italicSelection = createOtherInlineRange(lineText, cursorPosition.character, cursorPosition.line, true, parent);
@ -146,7 +146,7 @@ function createInlineRange(document: SkinnyTextDocument, cursorPosition: vscode.
return inlineCodeBlockSelection || linkSelection || comboSelection || boldSelection || italicSelection;
}
function createFencedRange(token: MarkdownItTokenWithMap, cursorLine: number, document: SkinnyTextDocument, parent?: vscode.SelectionRange): vscode.SelectionRange {
function createFencedRange(token: MarkdownItTokenWithMap, cursorLine: number, document: ITextDocument, parent?: vscode.SelectionRange): vscode.SelectionRange {
const startLine = token.map[0];
const endLine = token.map[1] - 1;
const onFenceLine = cursorLine === startLine || cursorLine === endLine;
@ -236,7 +236,7 @@ function isBlockElement(token: Token): boolean {
return !['list_item_close', 'paragraph_close', 'bullet_list_close', 'inline', 'heading_close', 'heading_open'].includes(token.type);
}
function getFirstChildHeader(document: SkinnyTextDocument, header?: TocEntry, toc?: readonly TocEntry[]): vscode.Position | undefined {
function getFirstChildHeader(document: ITextDocument, header?: TocEntry, toc?: readonly TocEntry[]): vscode.Position | undefined {
let childRange: vscode.Position | undefined;
if (header && toc) {
const children = toc.filter(t => header.sectionLocation.range.contains(t.sectionLocation.range) && t.sectionLocation.range.start.line > header.sectionLocation.range.start.line).sort((t1, t2) => t1.line - t2.line);

View file

@ -5,9 +5,9 @@
import * as vscode from 'vscode';
import { Disposable } from '../util/dispose';
import { MdWorkspaceContents } from '../workspaceContents';
import { MdDocumentSymbolProvider } from './documentSymbols';
import { MdWorkspaceInfoCache } from '../util/workspaceCache';
import { IMdWorkspace } from '../workspace';
import { MdDocumentSymbolProvider } from './documentSymbols';
export class MdWorkspaceSymbolProvider extends Disposable implements vscode.WorkspaceSymbolProvider {
@ -15,11 +15,11 @@ export class MdWorkspaceSymbolProvider extends Disposable implements vscode.Work
public constructor(
symbolProvider: MdDocumentSymbolProvider,
workspaceContents: MdWorkspaceContents,
workspace: IMdWorkspace,
) {
super();
this._cache = this._register(new MdWorkspaceInfoCache(workspaceContents, doc => symbolProvider.provideDocumentSymbolInformation(doc)));
this._cache = this._register(new MdWorkspaceInfoCache(workspace, doc => symbolProvider.provideDocumentSymbolInformation(doc)));
}
public async provideWorkspaceSymbols(query: string): Promise<vscode.SymbolInformation[]> {
@ -29,8 +29,8 @@ export class MdWorkspaceSymbolProvider extends Disposable implements vscode.Work
}
export function registerWorkspaceSymbolSupport(
workspaceContents: MdWorkspaceContents,
workspace: IMdWorkspace,
symbolProvider: MdDocumentSymbolProvider,
): vscode.Disposable {
return vscode.languages.registerWorkspaceSymbolProvider(new MdWorkspaceSymbolProvider(symbolProvider, workspaceContents));
return vscode.languages.registerWorkspaceSymbolProvider(new MdWorkspaceSymbolProvider(symbolProvider, workspace));
}

View file

@ -9,12 +9,13 @@ import * as vscode from 'vscode';
import { ILogger } from './logging';
import { MarkdownContributionProvider } from './markdownExtensions';
import { Slugifier } from './slugify';
import { ITextDocument } from './types/textDocument';
import { Disposable } from './util/dispose';
import { stringHash } from './util/hash';
import { WebviewResourceProvider } from './util/resources';
import { isOfScheme, Schemes } from './util/schemes';
import { MdDocumentInfoCache } from './util/workspaceCache';
import { MdWorkspaceContents, SkinnyTextDocument } from './workspaceContents';
import { IMdWorkspace } from './workspace';
const UNICODE_NEWLINE_REGEX = /\u2028|\u2029/g;
@ -56,7 +57,7 @@ class TokenCache {
};
private tokens?: Token[];
public tryGetCached(document: SkinnyTextDocument, config: MarkdownItConfig): Token[] | undefined {
public tryGetCached(document: ITextDocument, config: MarkdownItConfig): Token[] | undefined {
if (this.cachedDocument
&& this.cachedDocument.uri.toString() === document.uri.toString()
&& this.cachedDocument.version === document.version
@ -68,7 +69,7 @@ class TokenCache {
return undefined;
}
public update(document: SkinnyTextDocument, config: MarkdownItConfig, tokens: Token[]) {
public update(document: ITextDocument, config: MarkdownItConfig, tokens: Token[]) {
this.cachedDocument = {
uri: document.uri,
version: document.version,
@ -97,7 +98,7 @@ interface RenderEnv {
export interface IMdParser {
readonly slugifier: Slugifier;
tokenize(document: SkinnyTextDocument): Promise<Token[]>;
tokenize(document: ITextDocument): Promise<Token[]>;
}
export class MarkdownItEngine implements IMdParser {
@ -173,7 +174,7 @@ export class MarkdownItEngine implements IMdParser {
}
private tokenizeDocument(
document: SkinnyTextDocument,
document: ITextDocument,
config: MarkdownItConfig,
engine: MarkdownIt
): Token[] {
@ -199,7 +200,7 @@ export class MarkdownItEngine implements IMdParser {
this._slugCount = new Map<string, number>();
}
public async render(input: SkinnyTextDocument | string, resourceProvider?: WebviewResourceProvider): Promise<RenderOutput> {
public async render(input: ITextDocument | string, resourceProvider?: WebviewResourceProvider): Promise<RenderOutput> {
const config = this.getConfig(typeof input === 'string' ? undefined : input.uri);
const engine = await this.getEngine(config);
@ -224,7 +225,7 @@ export class MarkdownItEngine implements IMdParser {
};
}
public async tokenize(document: SkinnyTextDocument): Promise<Token[]> {
public async tokenize(document: ITextDocument): Promise<Token[]> {
const config = this.getConfig(document.uri);
const engine = await this.getEngine(config);
return this.tokenizeDocument(document, config, engine);
@ -447,18 +448,18 @@ export class MdParsingProvider extends Disposable implements IMdParser {
constructor(
engine: MarkdownItEngine,
workspaceContents: MdWorkspaceContents,
workspace: IMdWorkspace,
) {
super();
this.slugifier = engine.slugifier;
this._cache = this._register(new MdDocumentInfoCache<Token[]>(workspaceContents, doc => {
this._cache = this._register(new MdDocumentInfoCache<Token[]>(workspace, doc => {
return engine.tokenize(doc);
}));
}
public tokenize(document: SkinnyTextDocument): Promise<Token[]> {
public tokenize(document: ITextDocument): Promise<Token[]> {
return this._cache.getForDocument(document);
}
}

View file

@ -9,9 +9,9 @@ import { MarkdownContributionProvider } from '../markdownExtensions';
import { MdTableOfContentsProvider } from '../tableOfContents';
import { Disposable, disposeAll } from '../util/dispose';
import { isMarkdownFile } from '../util/file';
import { MdDocumentRenderer } from './documentRenderer';
import { DynamicMarkdownPreview, IManagedMarkdownPreview, StaticMarkdownPreview } from './preview';
import { MarkdownPreviewConfigurationManager } from './previewConfig';
import { MdDocumentRenderer } from './documentRenderer';
import { scrollEditorToLine, StartingScrollFragment } from './scrolling';
import { TopmostLineMonitor } from './topmostLineMonitor';

View file

@ -7,10 +7,11 @@ import * as vscode from 'vscode';
import { ILogger } from './logging';
import { IMdParser } from './markdownEngine';
import { githubSlugifier, Slug, Slugifier } from './slugify';
import { ITextDocument } from './types/textDocument';
import { Disposable } from './util/dispose';
import { isMarkdownFile } from './util/file';
import { MdDocumentInfoCache } from './util/workspaceCache';
import { MdWorkspaceContents, SkinnyTextDocument } from './workspaceContents';
import { IMdWorkspace } from './workspace';
export interface TocEntry {
readonly slug: Slug;
@ -64,12 +65,12 @@ export interface TocEntry {
export class TableOfContents {
public static async create(parser: IMdParser, document: SkinnyTextDocument,): Promise<TableOfContents> {
public static async create(parser: IMdParser, document: ITextDocument,): Promise<TableOfContents> {
const entries = await this.buildToc(parser, document);
return new TableOfContents(entries, parser.slugifier);
}
public static async createForDocumentOrNotebook(parser: IMdParser, document: SkinnyTextDocument): Promise<TableOfContents> {
public static async createForDocumentOrNotebook(parser: IMdParser, document: ITextDocument): Promise<TableOfContents> {
if (document.uri.scheme === 'vscode-notebook-cell') {
const notebook = vscode.workspace.notebookDocuments
.find(notebook => notebook.getCells().some(cell => cell.document === document));
@ -90,7 +91,7 @@ export class TableOfContents {
return this.create(parser, document);
}
private static async buildToc(parser: IMdParser, document: SkinnyTextDocument): Promise<TocEntry[]> {
private static async buildToc(parser: IMdParser, document: ITextDocument): Promise<TocEntry[]> {
const toc: TocEntry[] = [];
const tokens = await parser.tokenize(document);
@ -183,11 +184,11 @@ export class MdTableOfContentsProvider extends Disposable {
constructor(
parser: IMdParser,
workspaceContents: MdWorkspaceContents,
workspace: IMdWorkspace,
private readonly logger: ILogger,
) {
super();
this._cache = this._register(new MdDocumentInfoCache<TableOfContents>(workspaceContents, doc => {
this._cache = this._register(new MdDocumentInfoCache<TableOfContents>(workspace, doc => {
this.logger.verbose('TableOfContentsProvider', `create - ${doc.uri}`);
return TableOfContents.create(parser, doc);
}));
@ -197,7 +198,7 @@ export class MdTableOfContentsProvider extends Disposable {
return await this._cache.get(resource) ?? TableOfContents.empty;
}
public getForDocument(doc: SkinnyTextDocument): Promise<TableOfContents> {
public getForDocument(doc: ITextDocument): Promise<TableOfContents> {
return this._cache.getForDocument(doc);
}
}

View file

@ -11,14 +11,14 @@ import { MdReferencesProvider } from '../languageFeatures/references';
import { MdTableOfContentsProvider } from '../tableOfContents';
import { noopToken } from '../util/cancellation';
import { InMemoryDocument } from '../util/inMemoryDocument';
import { MdWorkspaceContents } from '../workspaceContents';
import { IMdWorkspace } from '../workspace';
import { createNewMarkdownEngine } from './engine';
import { InMemoryWorkspaceMarkdownDocuments } from './inMemoryWorkspace';
import { InMemoryMdWorkspace } from './inMemoryWorkspace';
import { nulLogger } from './nulLogging';
import { joinLines, workspacePath } from './util';
function getDefinition(doc: InMemoryDocument, pos: vscode.Position, workspace: MdWorkspaceContents) {
function getDefinition(doc: InMemoryDocument, pos: vscode.Position, workspace: IMdWorkspace) {
const engine = createNewMarkdownEngine();
const referencesProvider = new MdReferencesProvider(engine, workspace, new MdTableOfContentsProvider(engine, workspace, nulLogger), nulLogger);
const provider = new MdVsCodeDefinitionProvider(referencesProvider);
@ -52,7 +52,7 @@ suite('markdown: Go to definition', () => {
`[ref]: http://example.com`,
));
const defs = await getDefinition(doc, new vscode.Position(0, 1), new InMemoryWorkspaceMarkdownDocuments([doc]));
const defs = await getDefinition(doc, new vscode.Position(0, 1), new InMemoryMdWorkspace([doc]));
assert.deepStrictEqual(defs, undefined);
});
@ -64,7 +64,7 @@ suite('markdown: Go to definition', () => {
`[abc]: https://example.com`,
));
const defs = await getDefinition(doc, new vscode.Position(0, 12), new InMemoryWorkspaceMarkdownDocuments([doc]));
const defs = await getDefinition(doc, new vscode.Position(0, 12), new InMemoryMdWorkspace([doc]));
assertDefinitionsEqual(defs!,
{ uri: docUri, line: 2 },
);
@ -81,19 +81,19 @@ suite('markdown: Go to definition', () => {
));
{
const defs = await getDefinition(doc, new vscode.Position(0, 2), new InMemoryWorkspaceMarkdownDocuments([doc]));
const defs = await getDefinition(doc, new vscode.Position(0, 2), new InMemoryMdWorkspace([doc]));
assertDefinitionsEqual(defs!,
{ uri: docUri, line: 4 },
);
}
{
const defs = await getDefinition(doc, new vscode.Position(2, 7), new InMemoryWorkspaceMarkdownDocuments([doc]));
const defs = await getDefinition(doc, new vscode.Position(2, 7), new InMemoryMdWorkspace([doc]));
assertDefinitionsEqual(defs!,
{ uri: docUri, line: 4 },
);
}
{
const defs = await getDefinition(doc, new vscode.Position(4, 2), new InMemoryWorkspaceMarkdownDocuments([doc]));
const defs = await getDefinition(doc, new vscode.Position(4, 2), new InMemoryMdWorkspace([doc]));
assertDefinitionsEqual(defs!,
{ uri: docUri, line: 4 },
);
@ -108,7 +108,7 @@ suite('markdown: Go to definition', () => {
`[abc]: https://example.com`, // trigger here
));
const defs = await getDefinition(doc, new vscode.Position(2, 3), new InMemoryWorkspaceMarkdownDocuments([doc]));
const defs = await getDefinition(doc, new vscode.Position(2, 3), new InMemoryMdWorkspace([doc]));
assertDefinitionsEqual(defs!,
{ uri: docUri, line: 2 },
);
@ -122,7 +122,7 @@ suite('markdown: Go to definition', () => {
`[abc]: https://example.com`,
));
const defs = await getDefinition(doc, new vscode.Position(0, 12), new InMemoryWorkspaceMarkdownDocuments([
const defs = await getDefinition(doc, new vscode.Position(0, 12), new InMemoryMdWorkspace([
doc,
new InMemoryDocument(workspacePath('other.md'), joinLines(
`[link 1][abc]`,

View file

@ -14,9 +14,9 @@ import { noopToken } from '../util/cancellation';
import { disposeAll } from '../util/dispose';
import { InMemoryDocument } from '../util/inMemoryDocument';
import { ResourceMap } from '../util/resourceMap';
import { MdWorkspaceContents } from '../workspaceContents';
import { IMdWorkspace } from '../workspace';
import { createNewMarkdownEngine } from './engine';
import { InMemoryWorkspaceMarkdownDocuments } from './inMemoryWorkspace';
import { InMemoryMdWorkspace } from './inMemoryWorkspace';
import { nulLogger } from './nulLogging';
import { assertRangeEqual, joinLines, workspacePath } from './util';
@ -29,7 +29,7 @@ const defaultDiagnosticsOptions = Object.freeze<DiagnosticOptions>({
ignoreLinks: [],
});
async function getComputedDiagnostics(doc: InMemoryDocument, workspace: MdWorkspaceContents, options: Partial<DiagnosticOptions> = {}): Promise<vscode.Diagnostic[]> {
async function getComputedDiagnostics(doc: InMemoryDocument, workspace: IMdWorkspace, options: Partial<DiagnosticOptions> = {}): Promise<vscode.Diagnostic[]> {
const engine = createNewMarkdownEngine();
const linkProvider = new MdLinkProvider(engine, workspace, nulLogger);
const tocProvider = new MdTableOfContentsProvider(engine, workspace, nulLogger);
@ -113,7 +113,7 @@ suite('markdown: Diagnostic Computer', () => {
`text`,
));
const diagnostics = await getComputedDiagnostics(doc, new InMemoryWorkspaceMarkdownDocuments([doc]));
const diagnostics = await getComputedDiagnostics(doc, new InMemoryMdWorkspace([doc]));
assert.deepStrictEqual(diagnostics, []);
});
@ -125,7 +125,7 @@ suite('markdown: Diagnostic Computer', () => {
`[bad-ref]: /no/such/file.md`,
));
const diagnostics = await getComputedDiagnostics(doc, new InMemoryWorkspaceMarkdownDocuments([doc]));
const diagnostics = await getComputedDiagnostics(doc, new InMemoryMdWorkspace([doc]));
assertDiagnosticsEqual(diagnostics, [
new vscode.Range(0, 6, 0, 22),
new vscode.Range(3, 11, 3, 27),
@ -142,7 +142,7 @@ suite('markdown: Diagnostic Computer', () => {
`[bad-ref]: #no-such-header`,
));
const diagnostics = await getComputedDiagnostics(doc, new InMemoryWorkspaceMarkdownDocuments([doc]));
const diagnostics = await getComputedDiagnostics(doc, new InMemoryMdWorkspace([doc]));
assertDiagnosticsEqual(diagnostics, [
new vscode.Range(2, 6, 2, 21),
new vscode.Range(5, 11, 5, 26),
@ -163,7 +163,7 @@ suite('markdown: Diagnostic Computer', () => {
`# Other header`,
));
const diagnostics = await getComputedDiagnostics(doc1, new InMemoryWorkspaceMarkdownDocuments([doc1, doc2]));
const diagnostics = await getComputedDiagnostics(doc1, new InMemoryMdWorkspace([doc1, doc2]));
assertDiagnosticsEqual(diagnostics, [
new vscode.Range(5, 14, 5, 35),
]);
@ -179,7 +179,7 @@ suite('markdown: Diagnostic Computer', () => {
`[good](doc#my-header)`,
));
const diagnostics = await getComputedDiagnostics(doc, new InMemoryWorkspaceMarkdownDocuments([doc]));
const diagnostics = await getComputedDiagnostics(doc, new InMemoryMdWorkspace([doc]));
assertDiagnosticsEqual(diagnostics, []);
});
@ -191,7 +191,7 @@ suite('markdown: Diagnostic Computer', () => {
`[good]: http://example.com`,
));
const diagnostics = await getComputedDiagnostics(doc, new InMemoryWorkspaceMarkdownDocuments([doc]));
const diagnostics = await getComputedDiagnostics(doc, new InMemoryMdWorkspace([doc]));
assertDiagnosticsEqual(diagnostics, [
new vscode.Range(1, 11, 1, 18),
]);
@ -203,7 +203,7 @@ suite('markdown: Diagnostic Computer', () => {
`[text][no-such-ref]`,
));
const workspace = new InMemoryWorkspaceMarkdownDocuments([doc1]);
const workspace = new InMemoryMdWorkspace([doc1]);
const diagnostics = await getComputedDiagnostics(doc1, workspace, new MemoryDiagnosticConfiguration({ enabled: false }).getOptions(doc1.uri));
assertDiagnosticsEqual(diagnostics, []);
});
@ -213,7 +213,7 @@ suite('markdown: Diagnostic Computer', () => {
`a <user@example.com> c`,
));
const diagnostics = await getComputedDiagnostics(doc1, new InMemoryWorkspaceMarkdownDocuments([doc1]));
const diagnostics = await getComputedDiagnostics(doc1, new InMemoryMdWorkspace([doc1]));
assertDiagnosticsEqual(diagnostics, []);
});
@ -223,7 +223,7 @@ suite('markdown: Diagnostic Computer', () => {
`a <scope:tag>b</scope:tag> c`,
));
const diagnostics = await getComputedDiagnostics(doc1, new InMemoryWorkspaceMarkdownDocuments([doc1]));
const diagnostics = await getComputedDiagnostics(doc1, new InMemoryMdWorkspace([doc1]));
assertDiagnosticsEqual(diagnostics, []);
});
@ -234,7 +234,7 @@ suite('markdown: Diagnostic Computer', () => {
`[text]: /no-such-file`,
));
const workspace = new InMemoryWorkspaceMarkdownDocuments([doc1]);
const workspace = new InMemoryMdWorkspace([doc1]);
const diagnostics = await getComputedDiagnostics(doc1, workspace, { ignoreLinks: ['/no-such-file'] });
assertDiagnosticsEqual(diagnostics, []);
});
@ -245,7 +245,7 @@ suite('markdown: Diagnostic Computer', () => {
));
const doc2 = new InMemoryDocument(workspacePath('doc2.md'), joinLines(''));
const workspace = new InMemoryWorkspaceMarkdownDocuments([doc1, doc2]);
const workspace = new InMemoryMdWorkspace([doc1, doc2]);
const diagnostics = await getComputedDiagnostics(doc1, workspace, { validateMarkdownFileLinkFragments: DiagnosticLevel.ignore });
assertDiagnosticsEqual(diagnostics, []);
@ -258,7 +258,7 @@ suite('markdown: Diagnostic Computer', () => {
));
const doc2 = new InMemoryDocument(workspacePath('doc2.md'), joinLines(''));
const workspace = new InMemoryWorkspaceMarkdownDocuments([doc1, doc2]);
const workspace = new InMemoryMdWorkspace([doc1, doc2]);
{
const diagnostics = await getComputedDiagnostics(doc1, workspace, { validateFragmentLinks: DiagnosticLevel.ignore });
@ -278,7 +278,7 @@ suite('markdown: Diagnostic Computer', () => {
`[text](/no-such-file#header)`,
));
const workspace = new InMemoryWorkspaceMarkdownDocuments([doc1]);
const workspace = new InMemoryMdWorkspace([doc1]);
const diagnostics = await getComputedDiagnostics(doc1, workspace, { ignoreLinks: ['/no-such-file'] });
assertDiagnosticsEqual(diagnostics, []);
@ -289,7 +289,7 @@ suite('markdown: Diagnostic Computer', () => {
`[text](/no-such-file#header)`,
));
const workspace = new InMemoryWorkspaceMarkdownDocuments([doc1]);
const workspace = new InMemoryMdWorkspace([doc1]);
const diagnostics = await getComputedDiagnostics(doc1, workspace, { ignoreLinks: ['/no-such-file'] });
assertDiagnosticsEqual(diagnostics, []);
@ -302,7 +302,7 @@ suite('markdown: Diagnostic Computer', () => {
`![i](/images/sub/sub2/ccc.png)`,
));
const workspace = new InMemoryWorkspaceMarkdownDocuments([doc1]);
const workspace = new InMemoryMdWorkspace([doc1]);
const diagnostics = await getComputedDiagnostics(doc1, workspace, { ignoreLinks: ['/images/**/*.png'] });
assertDiagnosticsEqual(diagnostics, []);
});
@ -311,7 +311,7 @@ suite('markdown: Diagnostic Computer', () => {
const doc1 = new InMemoryDocument(workspacePath('doc1.md'), joinLines(
`![i](#no-such)`,
));
const workspace = new InMemoryWorkspaceMarkdownDocuments([doc1]);
const workspace = new InMemoryMdWorkspace([doc1]);
const diagnostics = await getComputedDiagnostics(doc1, workspace, { ignoreLinks: ['#no-such'] });
assertDiagnosticsEqual(diagnostics, []);
@ -323,7 +323,7 @@ suite('markdown: Diagnostic Computer', () => {
));
const doc2 = new InMemoryDocument(workspacePath('doc2.md'), joinLines(''));
const workspace = new InMemoryWorkspaceMarkdownDocuments([doc1, doc2]);
const workspace = new InMemoryMdWorkspace([doc1, doc2]);
{
const diagnostics = await getComputedDiagnostics(doc1, workspace, { ignoreLinks: ['/doc2.md#no-such'] });
assertDiagnosticsEqual(diagnostics, []);
@ -340,7 +340,7 @@ suite('markdown: Diagnostic Computer', () => {
));
const doc2 = new InMemoryDocument(workspacePath('doc2.md'), joinLines(''));
const workspace = new InMemoryWorkspaceMarkdownDocuments([doc1, doc2]);
const workspace = new InMemoryMdWorkspace([doc1, doc2]);
const diagnostics = await getComputedDiagnostics(doc1, workspace, { ignoreLinks: ['/doc2.md'] });
assertDiagnosticsEqual(diagnostics, []);
@ -353,7 +353,7 @@ suite('markdown: Diagnostic Computer', () => {
`- [ ]`,
));
const workspace = new InMemoryWorkspaceMarkdownDocuments([doc1]);
const workspace = new InMemoryMdWorkspace([doc1]);
const diagnostics = await getComputedDiagnostics(doc1, workspace, { ignoreLinks: ['/doc2.md'] });
assertDiagnosticsEqual(diagnostics, []);
@ -368,7 +368,7 @@ suite('markdown: Diagnostic Computer', () => {
`[link](no-such.md 'text')`,
`[link](no-such.md (text))`,
));
const diagnostics = await getComputedDiagnostics(doc, new InMemoryWorkspaceMarkdownDocuments([doc]));
const diagnostics = await getComputedDiagnostics(doc, new InMemoryMdWorkspace([doc]));
assertDiagnosticsEqual(diagnostics, [
new vscode.Range(0, 8, 0, 18),
new vscode.Range(1, 8, 1, 18),
@ -387,7 +387,7 @@ suite('markdown: Diagnostic Computer', () => {
`[bad](/sub/doc#no-such)`,
));
const diagnostics = await getComputedDiagnostics(doc, new InMemoryWorkspaceMarkdownDocuments([doc]));
const diagnostics = await getComputedDiagnostics(doc, new InMemoryMdWorkspace([doc]));
assertDiagnosticsEqual(orderDiagnosticsByRange(diagnostics), [
new vscode.Range(0, 12, 0, 20),
new vscode.Range(1, 9, 1, 17),
@ -404,7 +404,7 @@ suite('markdown: Diagnostic Computer', () => {
`[bad](/sub/doc#no-such)`,
));
const workspace = new InMemoryWorkspaceMarkdownDocuments([doc1]);
const workspace = new InMemoryMdWorkspace([doc1]);
const diagnostics = await getComputedDiagnostics(doc1, workspace, {
validateFragmentLinks: DiagnosticLevel.ignore,
@ -432,7 +432,7 @@ suite('Markdown: Diagnostics manager', () => {
});
function createDiagnosticsManager(
workspace: MdWorkspaceContents,
workspace: IMdWorkspace,
configuration = new MemoryDiagnosticConfiguration({}),
reporter: DiagnosticReporter = new DiagnosticCollectionReporter(),
) {
@ -456,7 +456,7 @@ suite('Markdown: Diagnostics manager', () => {
test('Changing enable/disable should recompute diagnostics', async () => {
const doc1Uri = workspacePath('doc1.md');
const doc2Uri = workspacePath('doc2.md');
const workspace = new InMemoryWorkspaceMarkdownDocuments([
const workspace = new InMemoryMdWorkspace([
new InMemoryDocument(doc1Uri, joinLines(
`[text](#no-such-1)`,
)),
@ -510,7 +510,7 @@ suite('Markdown: Diagnostics manager', () => {
`[text](#no-such-2)`,
));
const workspace = new InMemoryWorkspaceMarkdownDocuments([doc1, doc2]);
const workspace = new InMemoryMdWorkspace([doc1, doc2]);
const reporter = new MemoryDiagnosticReporter();
const manager = createDiagnosticsManager(workspace, new MemoryDiagnosticConfiguration({}), reporter);
@ -566,7 +566,7 @@ suite('Markdown: Diagnostics manager', () => {
`# Header`
));
const workspace = new InMemoryWorkspaceMarkdownDocuments([doc1, doc2]);
const workspace = new InMemoryMdWorkspace([doc1, doc2]);
const reporter = new MemoryDiagnosticReporter();
const manager = createDiagnosticsManager(workspace, new MemoryDiagnosticConfiguration({}), reporter);

View file

@ -7,13 +7,13 @@ import * as assert from 'assert';
import 'mocha';
import { InMemoryDocument } from '../util/inMemoryDocument';
import { MdDocumentInfoCache } from '../util/workspaceCache';
import { InMemoryWorkspaceMarkdownDocuments } from './inMemoryWorkspace';
import { InMemoryMdWorkspace } from './inMemoryWorkspace';
import { workspacePath } from './util';
suite('DocumentInfoCache', () => {
test('Repeated calls should only compute value once', async () => {
const doc = workspacePath('doc.md');
const workspace = new InMemoryWorkspaceMarkdownDocuments([
const workspace = new InMemoryMdWorkspace([
new InMemoryDocument(doc, '')
]);

View file

@ -10,14 +10,14 @@ import { MdLinkProvider, MdVsCodeLinkProvider } from '../languageFeatures/docume
import { noopToken } from '../util/cancellation';
import { InMemoryDocument } from '../util/inMemoryDocument';
import { createNewMarkdownEngine } from './engine';
import { InMemoryWorkspaceMarkdownDocuments } from './inMemoryWorkspace';
import { InMemoryMdWorkspace } from './inMemoryWorkspace';
import { nulLogger } from './nulLogging';
import { assertRangeEqual, joinLines, workspacePath } from './util';
function getLinksForFile(fileContents: string) {
const doc = new InMemoryDocument(workspacePath('x.md'), fileContents);
const workspace = new InMemoryWorkspaceMarkdownDocuments([doc]);
const workspace = new InMemoryMdWorkspace([doc]);
const engine = createNewMarkdownEngine();
const linkProvider = new MdLinkProvider(engine, workspace, nulLogger);

View file

@ -9,14 +9,14 @@ import { MdDocumentSymbolProvider } from '../languageFeatures/documentSymbols';
import { MdTableOfContentsProvider } from '../tableOfContents';
import { InMemoryDocument } from '../util/inMemoryDocument';
import { createNewMarkdownEngine } from './engine';
import { InMemoryWorkspaceMarkdownDocuments } from './inMemoryWorkspace';
import { InMemoryMdWorkspace } from './inMemoryWorkspace';
import { nulLogger } from './nulLogging';
import { workspacePath } from './util';
function getSymbolsForFile(fileContents: string) {
const doc = new InMemoryDocument(workspacePath('test.md'), fileContents);
const workspace = new InMemoryWorkspaceMarkdownDocuments([doc]);
const workspace = new InMemoryMdWorkspace([doc]);
const engine = createNewMarkdownEngine();
const provider = new MdDocumentSymbolProvider(new MdTableOfContentsProvider(engine, workspace, nulLogger), nulLogger);
return provider.provideDocumentSymbols(doc);

View file

@ -6,8 +6,8 @@
import * as assert from 'assert';
import 'mocha';
import * as vscode from 'vscode';
import { createNewMarkdownEngine } from './engine';
import { InMemoryDocument } from '../util/inMemoryDocument';
import { createNewMarkdownEngine } from './engine';
const testFileName = vscode.Uri.file('test.md');

View file

@ -10,14 +10,14 @@ import { MdReference, MdReferencesProvider } from '../languageFeatures/reference
import { MdTableOfContentsProvider } from '../tableOfContents';
import { noopToken } from '../util/cancellation';
import { InMemoryDocument } from '../util/inMemoryDocument';
import { MdWorkspaceContents } from '../workspaceContents';
import { IMdWorkspace } from '../workspace';
import { createNewMarkdownEngine } from './engine';
import { InMemoryWorkspaceMarkdownDocuments } from './inMemoryWorkspace';
import { InMemoryMdWorkspace } from './inMemoryWorkspace';
import { nulLogger } from './nulLogging';
import { joinLines, workspacePath } from './util';
function getFileReferences(resource: vscode.Uri, workspace: MdWorkspaceContents) {
function getFileReferences(resource: vscode.Uri, workspace: IMdWorkspace) {
const engine = createNewMarkdownEngine();
const computer = new MdReferencesProvider(engine, workspace, new MdTableOfContentsProvider(engine, workspace, nulLogger), nulLogger);
return computer.getAllReferencesToFile(resource, noopToken);
@ -41,7 +41,7 @@ suite('markdown: find file references', () => {
const docUri = workspacePath('doc.md');
const otherUri = workspacePath('other.md');
const refs = await getFileReferences(otherUri, new InMemoryWorkspaceMarkdownDocuments([
const refs = await getFileReferences(otherUri, new InMemoryMdWorkspace([
new InMemoryDocument(docUri, joinLines(
`# header`,
`[link 1](./other.md)`,
@ -66,7 +66,7 @@ suite('markdown: find file references', () => {
const docUri = workspacePath('doc.md');
const otherUri = workspacePath('other.md');
const refs = await getFileReferences(otherUri, new InMemoryWorkspaceMarkdownDocuments([
const refs = await getFileReferences(otherUri, new InMemoryMdWorkspace([
new InMemoryDocument(docUri, joinLines(
`# header`,
`[link 1](./other.md)`,
@ -93,7 +93,7 @@ suite('markdown: find file references', () => {
const docUri = workspacePath('doc.md');
const otherUri = workspacePath('other.md');
const refs = await getFileReferences(otherUri, new InMemoryWorkspaceMarkdownDocuments([
const refs = await getFileReferences(otherUri, new InMemoryMdWorkspace([
new InMemoryDocument(docUri, joinLines(
`# header`,
`[link 1](./other.md#sub-bla)`,

View file

@ -10,7 +10,7 @@ import { MdFoldingProvider } from '../languageFeatures/folding';
import { MdTableOfContentsProvider } from '../tableOfContents';
import { InMemoryDocument } from '../util/inMemoryDocument';
import { createNewMarkdownEngine } from './engine';
import { InMemoryWorkspaceMarkdownDocuments } from './inMemoryWorkspace';
import { InMemoryMdWorkspace } from './inMemoryWorkspace';
import { nulLogger } from './nulLogging';
import { joinLines } from './util';
@ -221,7 +221,7 @@ suite('markdown.FoldingProvider', () => {
async function getFoldsForDocument(contents: string) {
const doc = new InMemoryDocument(testFileName, contents);
const workspace = new InMemoryWorkspaceMarkdownDocuments([doc]);
const workspace = new InMemoryMdWorkspace([doc]);
const engine = createNewMarkdownEngine();
const provider = new MdFoldingProvider(engine, new MdTableOfContentsProvider(engine, workspace, nulLogger));
return await provider.provideFoldingRanges(doc, {}, new vscode.CancellationTokenSource().token);

View file

@ -5,14 +5,15 @@
import * as assert from 'assert';
import * as vscode from 'vscode';
import { ITextDocument } from '../types/textDocument';
import { ResourceMap } from '../util/resourceMap';
import { MdWorkspaceContents, SkinnyTextDocument } from '../workspaceContents';
import { IMdWorkspace } from '../workspace';
export class InMemoryWorkspaceMarkdownDocuments implements MdWorkspaceContents {
private readonly _documents = new ResourceMap<SkinnyTextDocument>(uri => uri.fsPath);
export class InMemoryMdWorkspace implements IMdWorkspace {
private readonly _documents = new ResourceMap<ITextDocument>(uri => uri.fsPath);
constructor(documents: SkinnyTextDocument[]) {
constructor(documents: ITextDocument[]) {
for (const doc of documents) {
this._documents.set(doc.uri, doc);
}
@ -22,7 +23,7 @@ export class InMemoryWorkspaceMarkdownDocuments implements MdWorkspaceContents {
return Array.from(this._documents.values());
}
public async getOrLoadMarkdownDocument(resource: vscode.Uri): Promise<SkinnyTextDocument | undefined> {
public async getOrLoadMarkdownDocument(resource: vscode.Uri): Promise<ITextDocument | undefined> {
return this._documents.get(resource);
}
@ -34,21 +35,21 @@ export class InMemoryWorkspaceMarkdownDocuments implements MdWorkspaceContents {
return this._documents.has(resource);
}
private readonly _onDidChangeMarkdownDocumentEmitter = new vscode.EventEmitter<SkinnyTextDocument>();
private readonly _onDidChangeMarkdownDocumentEmitter = new vscode.EventEmitter<ITextDocument>();
public onDidChangeMarkdownDocument = this._onDidChangeMarkdownDocumentEmitter.event;
private readonly _onDidCreateMarkdownDocumentEmitter = new vscode.EventEmitter<SkinnyTextDocument>();
private readonly _onDidCreateMarkdownDocumentEmitter = new vscode.EventEmitter<ITextDocument>();
public onDidCreateMarkdownDocument = this._onDidCreateMarkdownDocumentEmitter.event;
private readonly _onDidDeleteMarkdownDocumentEmitter = new vscode.EventEmitter<vscode.Uri>();
public onDidDeleteMarkdownDocument = this._onDidDeleteMarkdownDocumentEmitter.event;
public updateDocument(document: SkinnyTextDocument) {
public updateDocument(document: ITextDocument) {
this._documents.set(document.uri, document);
this._onDidChangeMarkdownDocumentEmitter.fire(document);
}
public createDocument(document: SkinnyTextDocument) {
public createDocument(document: ITextDocument) {
assert.ok(!this._documents.has(document.uri));
this._documents.set(document.uri, document);

View file

@ -11,14 +11,14 @@ import { MdVsCodePathCompletionProvider } from '../languageFeatures/pathCompleti
import { noopToken } from '../util/cancellation';
import { InMemoryDocument } from '../util/inMemoryDocument';
import { createNewMarkdownEngine } from './engine';
import { InMemoryWorkspaceMarkdownDocuments } from './inMemoryWorkspace';
import { InMemoryMdWorkspace } from './inMemoryWorkspace';
import { nulLogger } from './nulLogging';
import { CURSOR, getCursorPositions, joinLines, workspacePath } from './util';
function getCompletionsAtCursor(resource: vscode.Uri, fileContents: string) {
const doc = new InMemoryDocument(resource, fileContents);
const workspace = new InMemoryWorkspaceMarkdownDocuments([doc]);
const workspace = new InMemoryMdWorkspace([doc]);
const engine = createNewMarkdownEngine();
const linkProvider = new MdLinkProvider(engine, workspace, nulLogger);

View file

@ -10,14 +10,14 @@ import { MdReferencesProvider, MdVsCodeReferencesProvider } from '../languageFea
import { MdTableOfContentsProvider } from '../tableOfContents';
import { noopToken } from '../util/cancellation';
import { InMemoryDocument } from '../util/inMemoryDocument';
import { MdWorkspaceContents } from '../workspaceContents';
import { IMdWorkspace } from '../workspace';
import { createNewMarkdownEngine } from './engine';
import { InMemoryWorkspaceMarkdownDocuments } from './inMemoryWorkspace';
import { InMemoryMdWorkspace } from './inMemoryWorkspace';
import { nulLogger } from './nulLogging';
import { joinLines, workspacePath } from './util';
function getReferences(doc: InMemoryDocument, pos: vscode.Position, workspace: MdWorkspaceContents) {
function getReferences(doc: InMemoryDocument, pos: vscode.Position, workspace: IMdWorkspace) {
const engine = createNewMarkdownEngine();
const computer = new MdReferencesProvider(engine, workspace, new MdTableOfContentsProvider(engine, workspace, nulLogger), nulLogger);
const provider = new MdVsCodeReferencesProvider(computer);
@ -52,11 +52,11 @@ suite('markdown: find all references', () => {
));
{
const refs = await getReferences(doc, new vscode.Position(1, 0), new InMemoryWorkspaceMarkdownDocuments([doc]));
const refs = await getReferences(doc, new vscode.Position(1, 0), new InMemoryMdWorkspace([doc]));
assert.deepStrictEqual(refs, []);
}
{
const refs = await getReferences(doc, new vscode.Position(3, 2), new InMemoryWorkspaceMarkdownDocuments([doc]));
const refs = await getReferences(doc, new vscode.Position(3, 2), new InMemoryMdWorkspace([doc]));
assert.deepStrictEqual(refs, []);
}
});
@ -70,7 +70,7 @@ suite('markdown: find all references', () => {
`[not link](#noabc)`,
`[link 2](#abc)`,
));
const refs = await getReferences(doc, new vscode.Position(0, 3), new InMemoryWorkspaceMarkdownDocuments([doc]));
const refs = await getReferences(doc, new vscode.Position(0, 3), new InMemoryMdWorkspace([doc]));
assertReferencesEqual(refs!,
{ uri, line: 0 },
{ uri, line: 2 },
@ -84,7 +84,7 @@ suite('markdown: find all references', () => {
`[ref]: http://example.com`,
));
const refs = await getReferences(doc, new vscode.Position(0, 1), new InMemoryWorkspaceMarkdownDocuments([doc]));
const refs = await getReferences(doc, new vscode.Position(0, 1), new InMemoryMdWorkspace([doc]));
assert.deepStrictEqual(refs, []);
});
@ -98,22 +98,22 @@ suite('markdown: find all references', () => {
{
// Trigger header
const refs = await getReferences(doc, new vscode.Position(0, 0), new InMemoryWorkspaceMarkdownDocuments([doc]));
const refs = await getReferences(doc, new vscode.Position(0, 0), new InMemoryMdWorkspace([doc]));
assert.deepStrictEqual(refs!.length, 4);
}
{
// Trigger on line 1
const refs = await getReferences(doc, new vscode.Position(1, 12), new InMemoryWorkspaceMarkdownDocuments([doc]));
const refs = await getReferences(doc, new vscode.Position(1, 12), new InMemoryMdWorkspace([doc]));
assert.deepStrictEqual(refs!.length, 4);
}
{
// Trigger on line 2
const refs = await getReferences(doc, new vscode.Position(2, 24), new InMemoryWorkspaceMarkdownDocuments([doc]));
const refs = await getReferences(doc, new vscode.Position(2, 24), new InMemoryMdWorkspace([doc]));
assert.deepStrictEqual(refs!.length, 4);
}
{
// Trigger on line 3
const refs = await getReferences(doc, new vscode.Position(3, 20), new InMemoryWorkspaceMarkdownDocuments([doc]));
const refs = await getReferences(doc, new vscode.Position(3, 20), new InMemoryMdWorkspace([doc]));
assert.deepStrictEqual(refs!.length, 4);
}
});
@ -128,7 +128,7 @@ suite('markdown: find all references', () => {
``,
`[link 1](#abc)`,
));
const refs = await getReferences(doc, new vscode.Position(0, 3), new InMemoryWorkspaceMarkdownDocuments([
const refs = await getReferences(doc, new vscode.Position(0, 3), new InMemoryMdWorkspace([
doc,
new InMemoryDocument(other1Uri, joinLines(
`[not link](#abc)`,
@ -158,7 +158,7 @@ suite('markdown: find all references', () => {
`[bla]: #abc`
));
const refs = await getReferences(doc, new vscode.Position(0, 3), new InMemoryWorkspaceMarkdownDocuments([doc]));
const refs = await getReferences(doc, new vscode.Position(0, 3), new InMemoryMdWorkspace([doc]));
assertReferencesEqual(refs!,
{ uri, line: 0 }, // Header definition
{ uri, line: 2 },
@ -173,7 +173,7 @@ suite('markdown: find all references', () => {
`[bla]: #a-b-c`, // trigger here
));
const refs = await getReferences(doc, new vscode.Position(2, 9), new InMemoryWorkspaceMarkdownDocuments([doc]));
const refs = await getReferences(doc, new vscode.Position(2, 9), new InMemoryMdWorkspace([doc]));
assertReferencesEqual(refs!,
{ uri, line: 0 }, // Header definition
{ uri, line: 2 },
@ -190,7 +190,7 @@ suite('markdown: find all references', () => {
`[link 2](#abc)`,
));
const refs = await getReferences(doc, new vscode.Position(2, 10), new InMemoryWorkspaceMarkdownDocuments([doc]));
const refs = await getReferences(doc, new vscode.Position(2, 10), new InMemoryMdWorkspace([doc]));
assertReferencesEqual(refs!,
{ uri, line: 0 }, // Header definition
{ uri, line: 2 },
@ -208,7 +208,7 @@ suite('markdown: find all references', () => {
``,
`[link 1](#abc)`,
));
const refs = await getReferences(doc, new vscode.Position(2, 10), new InMemoryWorkspaceMarkdownDocuments([
const refs = await getReferences(doc, new vscode.Position(2, 10), new InMemoryMdWorkspace([
doc,
new InMemoryDocument(other1Uri, joinLines(
`[not link](#abc)`,
@ -241,7 +241,7 @@ suite('markdown: find all references', () => {
``,
`[link 1](#a-b-c)`,
));
const refs = await getReferences(doc, new vscode.Position(2, 10), new InMemoryWorkspaceMarkdownDocuments([
const refs = await getReferences(doc, new vscode.Position(2, 10), new InMemoryMdWorkspace([
doc,
new InMemoryDocument(other1Uri, joinLines(
`[not link](#a-b-c)`,
@ -272,7 +272,7 @@ suite('markdown: find all references', () => {
`[without ext](./sub/other.md#header)`,
));
const refs = await getReferences(doc, new vscode.Position(0, 23), new InMemoryWorkspaceMarkdownDocuments([
const refs = await getReferences(doc, new vscode.Position(0, 23), new InMemoryMdWorkspace([
doc,
new InMemoryDocument(other1Uri, joinLines(
`pre`,
@ -298,7 +298,7 @@ suite('markdown: find all references', () => {
`[without ext](./sub/other.md#no-such-header)`,
));
const refs = await getReferences(doc, new vscode.Position(0, 15), new InMemoryWorkspaceMarkdownDocuments([
const refs = await getReferences(doc, new vscode.Position(0, 15), new InMemoryMdWorkspace([
doc,
new InMemoryDocument(otherUri, joinLines(
`pre`,
@ -322,7 +322,7 @@ suite('markdown: find all references', () => {
`[other](./sub/other)`, // trigger here
));
const refs = await getReferences(doc, new vscode.Position(0, 15), new InMemoryWorkspaceMarkdownDocuments([
const refs = await getReferences(doc, new vscode.Position(0, 15), new InMemoryMdWorkspace([
doc,
new InMemoryDocument(otherUri, joinLines(
`# header`, // Definition should not be included since we triggered on a file link
@ -343,7 +343,7 @@ suite('markdown: find all references', () => {
`[abs](/doc.md)`,
));
const refs = await getReferences(doc, new vscode.Position(0, 12), new InMemoryWorkspaceMarkdownDocuments([doc]));
const refs = await getReferences(doc, new vscode.Position(0, 12), new InMemoryMdWorkspace([doc]));
assertReferencesEqual(refs!,
{ uri, line: 0 },
{ uri, line: 1 },
@ -360,7 +360,7 @@ suite('markdown: find all references', () => {
`[3]: http://example.com`,
));
const refs = await getReferences(doc, new vscode.Position(0, 13), new InMemoryWorkspaceMarkdownDocuments([doc]));
const refs = await getReferences(doc, new vscode.Position(0, 13), new InMemoryMdWorkspace([doc]));
assertReferencesEqual(refs!,
{ uri, line: 0 },
{ uri, line: 2 },
@ -380,7 +380,7 @@ suite('markdown: find all references', () => {
`[7](https://example.com/cat)`,
));
const refs = await getReferences(doc, new vscode.Position(0, 13), new InMemoryWorkspaceMarkdownDocuments([doc]));
const refs = await getReferences(doc, new vscode.Position(0, 13), new InMemoryMdWorkspace([doc]));
assertReferencesEqual(refs!,
{ uri, line: 0 },
{ uri, line: 4 },
@ -395,7 +395,7 @@ suite('markdown: find all references', () => {
`[3]: http://example.com`,
));
const refs = await getReferences(doc, new vscode.Position(0, 13), new InMemoryWorkspaceMarkdownDocuments([
const refs = await getReferences(doc, new vscode.Position(0, 13), new InMemoryMdWorkspace([
doc,
new InMemoryDocument(uri2, joinLines(
`[other](http://example.com)`,
@ -415,7 +415,7 @@ suite('markdown: find all references', () => {
`<http://example.com>`,
));
const refs = await getReferences(doc, new vscode.Position(0, 13), new InMemoryWorkspaceMarkdownDocuments([doc]));
const refs = await getReferences(doc, new vscode.Position(0, 13), new InMemoryMdWorkspace([doc]));
assertReferencesEqual(refs!,
{ uri, line: 0 },
{ uri, line: 1 },
@ -435,13 +435,13 @@ suite('markdown: find all references', () => {
`[link](/doc.md#abc)`,
`[link no text](/doc#abc)`,
));
const workspaceContents = new InMemoryWorkspaceMarkdownDocuments([
const workspace = new InMemoryMdWorkspace([
doc,
otherDoc,
]);
{
// Check refs to header fragment
const headerRefs = await getReferences(otherDoc, new vscode.Position(0, 16), workspaceContents);
const headerRefs = await getReferences(otherDoc, new vscode.Position(0, 16), workspace);
assertReferencesEqual(headerRefs!,
{ uri: docUri, line: 0 }, // Header definition
{ uri: docUri, line: 2 },
@ -451,7 +451,7 @@ suite('markdown: find all references', () => {
}
{
// Check refs to file itself from link with ext
const fileRefs = await getReferences(otherDoc, new vscode.Position(0, 9), workspaceContents);
const fileRefs = await getReferences(otherDoc, new vscode.Position(0, 9), workspace);
assertReferencesEqual(fileRefs!,
{ uri: other1Uri, line: 0, endCharacter: 14 },
{ uri: other1Uri, line: 1, endCharacter: 19 },
@ -459,7 +459,7 @@ suite('markdown: find all references', () => {
}
{
// Check refs to file itself from link without ext
const fileRefs = await getReferences(otherDoc, new vscode.Position(1, 17), workspaceContents);
const fileRefs = await getReferences(otherDoc, new vscode.Position(1, 17), workspace);
assertReferencesEqual(fileRefs!,
{ uri: other1Uri, line: 0 },
{ uri: other1Uri, line: 1 },
@ -481,7 +481,7 @@ suite('markdown: find all references', () => {
));
const refs = await getReferences(doc1, new vscode.Position(0, 10), new InMemoryWorkspaceMarkdownDocuments([doc1, doc2]));
const refs = await getReferences(doc1, new vscode.Position(0, 10), new InMemoryMdWorkspace([doc1, doc2]));
assertReferencesEqual(refs!,
{ uri: uri1, line: 0 },
{ uri: uri1, line: 2 },
@ -498,7 +498,7 @@ suite('markdown: find all references', () => {
`[abc]: https://example.com`,
));
const refs = await getReferences(doc, new vscode.Position(0, 12), new InMemoryWorkspaceMarkdownDocuments([doc]));
const refs = await getReferences(doc, new vscode.Position(0, 12), new InMemoryMdWorkspace([doc]));
assertReferencesEqual(refs!,
{ uri: docUri, line: 0 },
{ uri: docUri, line: 2 },
@ -516,7 +516,7 @@ suite('markdown: find all references', () => {
));
{
const refs = await getReferences(doc, new vscode.Position(0, 2), new InMemoryWorkspaceMarkdownDocuments([doc]));
const refs = await getReferences(doc, new vscode.Position(0, 2), new InMemoryMdWorkspace([doc]));
assertReferencesEqual(refs!,
{ uri: docUri, line: 0 },
{ uri: docUri, line: 2 },
@ -524,7 +524,7 @@ suite('markdown: find all references', () => {
);
}
{
const refs = await getReferences(doc, new vscode.Position(2, 7), new InMemoryWorkspaceMarkdownDocuments([doc]));
const refs = await getReferences(doc, new vscode.Position(2, 7), new InMemoryMdWorkspace([doc]));
assertReferencesEqual(refs!,
{ uri: docUri, line: 0 },
{ uri: docUri, line: 2 },
@ -532,7 +532,7 @@ suite('markdown: find all references', () => {
);
}
{
const refs = await getReferences(doc, new vscode.Position(4, 2), new InMemoryWorkspaceMarkdownDocuments([doc]));
const refs = await getReferences(doc, new vscode.Position(4, 2), new InMemoryMdWorkspace([doc]));
assertReferencesEqual(refs!,
{ uri: docUri, line: 0 },
{ uri: docUri, line: 2 },
@ -549,7 +549,7 @@ suite('markdown: find all references', () => {
`[abc]: https://example.com`, // trigger here
));
const refs = await getReferences(doc, new vscode.Position(2, 3), new InMemoryWorkspaceMarkdownDocuments([doc]));
const refs = await getReferences(doc, new vscode.Position(2, 3), new InMemoryMdWorkspace([doc]));
assertReferencesEqual(refs!,
{ uri: docUri, line: 0 },
{ uri: docUri, line: 2 },
@ -564,7 +564,7 @@ suite('markdown: find all references', () => {
`[abc]: https://example.com`,
));
const refs = await getReferences(doc, new vscode.Position(0, 12), new InMemoryWorkspaceMarkdownDocuments([
const refs = await getReferences(doc, new vscode.Position(0, 12), new InMemoryMdWorkspace([
doc,
new InMemoryDocument(workspacePath('other.md'), joinLines(
`[link 1][abc]`,
@ -588,7 +588,7 @@ suite('markdown: find all references', () => {
`[x]: https://example.com`
));
const refs = await getReferences(doc, new vscode.Position(0, 4), new InMemoryWorkspaceMarkdownDocuments([doc]));
const refs = await getReferences(doc, new vscode.Position(0, 4), new InMemoryMdWorkspace([doc]));
assert.strictEqual(refs?.length!, 0);
});
});

View file

@ -12,9 +12,9 @@ import { githubSlugifier } from '../slugify';
import { MdTableOfContentsProvider } from '../tableOfContents';
import { noopToken } from '../util/cancellation';
import { InMemoryDocument } from '../util/inMemoryDocument';
import { MdWorkspaceContents } from '../workspaceContents';
import { IMdWorkspace } from '../workspace';
import { createNewMarkdownEngine } from './engine';
import { InMemoryWorkspaceMarkdownDocuments } from './inMemoryWorkspace';
import { InMemoryMdWorkspace } from './inMemoryWorkspace';
import { nulLogger } from './nulLogging';
import { assertRangeEqual, joinLines, workspacePath } from './util';
@ -22,7 +22,7 @@ import { assertRangeEqual, joinLines, workspacePath } from './util';
/**
* Get prepare rename info.
*/
function prepareRename(doc: InMemoryDocument, pos: vscode.Position, workspace: MdWorkspaceContents): Promise<undefined | { readonly range: vscode.Range; readonly placeholder: string }> {
function prepareRename(doc: InMemoryDocument, pos: vscode.Position, workspace: IMdWorkspace): Promise<undefined | { readonly range: vscode.Range; readonly placeholder: string }> {
const engine = createNewMarkdownEngine();
const referenceComputer = new MdReferencesProvider(engine, workspace, new MdTableOfContentsProvider(engine, workspace, nulLogger), nulLogger);
const renameProvider = new MdVsCodeRenameProvider(workspace, referenceComputer, githubSlugifier);
@ -32,7 +32,7 @@ function prepareRename(doc: InMemoryDocument, pos: vscode.Position, workspace: M
/**
* Get all the edits for the rename.
*/
function getRenameEdits(doc: InMemoryDocument, pos: vscode.Position, newName: string, workspace: MdWorkspaceContents): Promise<MdWorkspaceEdit | undefined> {
function getRenameEdits(doc: InMemoryDocument, pos: vscode.Position, newName: string, workspace: IMdWorkspace): Promise<MdWorkspaceEdit | undefined> {
const engine = createNewMarkdownEngine();
const referencesProvider = new MdReferencesProvider(engine, workspace, new MdTableOfContentsProvider(engine, workspace, nulLogger), nulLogger);
const renameProvider = new MdVsCodeRenameProvider(workspace, referencesProvider, githubSlugifier);
@ -97,10 +97,10 @@ suite('markdown: rename', () => {
`# abc`
));
const info = await prepareRename(doc, new vscode.Position(0, 0), new InMemoryWorkspaceMarkdownDocuments([doc]));
const info = await prepareRename(doc, new vscode.Position(0, 0), new InMemoryMdWorkspace([doc]));
assertRangeEqual(info!.range, new vscode.Range(0, 2, 0, 5));
const edit = await getRenameEdits(doc, new vscode.Position(0, 0), "New Header", new InMemoryWorkspaceMarkdownDocuments([doc]));
const edit = await getRenameEdits(doc, new vscode.Position(0, 0), "New Header", new InMemoryMdWorkspace([doc]));
assertEditsEqual(edit!, {
uri, edits: [
new vscode.TextEdit(new vscode.Range(0, 2, 0, 5), 'New Header')
@ -114,10 +114,10 @@ suite('markdown: rename', () => {
`### abc ###`
));
const info = await prepareRename(doc, new vscode.Position(0, 0), new InMemoryWorkspaceMarkdownDocuments([doc]));
const info = await prepareRename(doc, new vscode.Position(0, 0), new InMemoryMdWorkspace([doc]));
assertRangeEqual(info!.range, new vscode.Range(0, 4, 0, 7));
const edit = await getRenameEdits(doc, new vscode.Position(0, 0), "New Header", new InMemoryWorkspaceMarkdownDocuments([doc]));
const edit = await getRenameEdits(doc, new vscode.Position(0, 0), "New Header", new InMemoryMdWorkspace([doc]));
assertEditsEqual(edit!, {
uri, edits: [
new vscode.TextEdit(new vscode.Range(0, 4, 0, 7), 'New Header')
@ -132,7 +132,7 @@ suite('markdown: rename', () => {
`[text](#a-b-c)`,
));
const edit = await getRenameEdits(doc, new vscode.Position(0, 0), "New Header", new InMemoryWorkspaceMarkdownDocuments([doc]));
const edit = await getRenameEdits(doc, new vscode.Position(0, 0), "New Header", new InMemoryMdWorkspace([doc]));
assertEditsEqual(edit!, {
uri, edits: [
new vscode.TextEdit(new vscode.Range(0, 4, 0, 9), 'New Header'),
@ -148,7 +148,7 @@ suite('markdown: rename', () => {
`[text](#a-b-c)`, // rename here
));
const edit = await getRenameEdits(doc, new vscode.Position(1, 10), "New Header", new InMemoryWorkspaceMarkdownDocuments([doc]));
const edit = await getRenameEdits(doc, new vscode.Position(1, 10), "New Header", new InMemoryMdWorkspace([doc]));
assertEditsEqual(edit!, {
uri, edits: [
new vscode.TextEdit(new vscode.Range(0, 4, 0, 9), 'New Header'),
@ -165,7 +165,7 @@ suite('markdown: rename', () => {
`[ref]: #a-b-c`// rename here
));
const edit = await getRenameEdits(doc, new vscode.Position(2, 10), "New Header", new InMemoryWorkspaceMarkdownDocuments([doc]));
const edit = await getRenameEdits(doc, new vscode.Position(2, 10), "New Header", new InMemoryMdWorkspace([doc]));
assertEditsEqual(edit!, {
uri, edits: [
new vscode.TextEdit(new vscode.Range(0, 4, 0, 9), 'New Header'),
@ -183,7 +183,7 @@ suite('markdown: rename', () => {
`[text](#a-b-c)`,
));
const edit = await getRenameEdits(doc, new vscode.Position(0, 0), "New Header", new InMemoryWorkspaceMarkdownDocuments([
const edit = await getRenameEdits(doc, new vscode.Position(0, 0), "New Header", new InMemoryMdWorkspace([
doc,
new InMemoryDocument(otherUri, joinLines(
`[text](#a-b-c)`, // Should not find this
@ -212,7 +212,7 @@ suite('markdown: rename', () => {
`[text](#a-b-c)`, // rename here
));
const edit = await getRenameEdits(doc, new vscode.Position(1, 10), "New Header", new InMemoryWorkspaceMarkdownDocuments([
const edit = await getRenameEdits(doc, new vscode.Position(1, 10), "New Header", new InMemoryMdWorkspace([
doc,
new InMemoryDocument(otherUri, joinLines(
`[text](#a-b-c)`, // Should not find this
@ -263,7 +263,7 @@ suite('markdown: rename', () => {
{
// Rename on header with file extension
const edit = await getRenameEdits(otherDoc, new vscode.Position(1, 17), "New Header", new InMemoryWorkspaceMarkdownDocuments([
const edit = await getRenameEdits(otherDoc, new vscode.Position(1, 17), "New Header", new InMemoryMdWorkspace([
doc,
otherDoc
]));
@ -271,7 +271,7 @@ suite('markdown: rename', () => {
}
{
// Rename on header without extension
const edit = await getRenameEdits(otherDoc, new vscode.Position(2, 15), "New Header", new InMemoryWorkspaceMarkdownDocuments([
const edit = await getRenameEdits(otherDoc, new vscode.Position(2, 15), "New Header", new InMemoryMdWorkspace([
doc,
otherDoc
]));
@ -288,7 +288,7 @@ suite('markdown: rename', () => {
`[ref]: https://example.com`,
));
const edit = await getRenameEdits(doc, new vscode.Position(0, 8), "new ref", new InMemoryWorkspaceMarkdownDocuments([doc]));
const edit = await getRenameEdits(doc, new vscode.Position(0, 8), "new ref", new InMemoryMdWorkspace([doc]));
assertEditsEqual(edit!, {
uri, edits: [
new vscode.TextEdit(new vscode.Range(0, 7, 0, 10), 'new ref'),
@ -307,7 +307,7 @@ suite('markdown: rename', () => {
`[ref]: https://example.com`, // rename here
));
const edit = await getRenameEdits(doc, new vscode.Position(3, 3), "new ref", new InMemoryWorkspaceMarkdownDocuments([doc]));
const edit = await getRenameEdits(doc, new vscode.Position(3, 3), "new ref", new InMemoryMdWorkspace([doc]));
assertEditsEqual(edit!, {
uri, edits: [
new vscode.TextEdit(new vscode.Range(0, 7, 0, 10), 'new ref'),
@ -326,11 +326,11 @@ suite('markdown: rename', () => {
`[ref]: #a-b-c`, // rename here
));
const preparedInfo = await prepareRename(doc, new vscode.Position(3, 10), new InMemoryWorkspaceMarkdownDocuments([doc]));
const preparedInfo = await prepareRename(doc, new vscode.Position(3, 10), new InMemoryMdWorkspace([doc]));
assert.strictEqual(preparedInfo!.placeholder, 'a B c');
assertRangeEqual(preparedInfo!.range, new vscode.Range(3, 8, 3, 13));
const edit = await getRenameEdits(doc, new vscode.Position(3, 10), "x Y z", new InMemoryWorkspaceMarkdownDocuments([doc]));
const edit = await getRenameEdits(doc, new vscode.Position(3, 10), "x Y z", new InMemoryMdWorkspace([doc]));
assertEditsEqual(edit!, {
uri, edits: [
new vscode.TextEdit(new vscode.Range(0, 2, 0, 7), 'x Y z'),
@ -347,7 +347,7 @@ suite('markdown: rename', () => {
`[text](#header)`,
));
await assert.rejects(prepareRename(doc, new vscode.Position(1, 2), new InMemoryWorkspaceMarkdownDocuments([doc])));
await assert.rejects(prepareRename(doc, new vscode.Position(1, 2), new InMemoryMdWorkspace([doc])));
});
test('Path rename should use file path as range', async () => {
@ -357,7 +357,7 @@ suite('markdown: rename', () => {
`[ref]: ./doc.md`,
));
const info = await prepareRename(doc, new vscode.Position(0, 10), new InMemoryWorkspaceMarkdownDocuments([doc]));
const info = await prepareRename(doc, new vscode.Position(0, 10), new InMemoryMdWorkspace([doc]));
assert.strictEqual(info!.placeholder, './doc.md');
assertRangeEqual(info!.range, new vscode.Range(0, 7, 0, 15));
});
@ -369,7 +369,7 @@ suite('markdown: rename', () => {
`[ref]: ./doc.md#some-header`,
));
const info = await prepareRename(doc, new vscode.Position(0, 10), new InMemoryWorkspaceMarkdownDocuments([doc]));
const info = await prepareRename(doc, new vscode.Position(0, 10), new InMemoryMdWorkspace([doc]));
assert.strictEqual(info!.placeholder, './doc.md');
assertRangeEqual(info!.range, new vscode.Range(0, 7, 0, 15));
});
@ -381,7 +381,7 @@ suite('markdown: rename', () => {
`[ref]: ./doc.md`,
));
const edit = await getRenameEdits(doc, new vscode.Position(0, 10), './sub/newDoc.md', new InMemoryWorkspaceMarkdownDocuments([doc]));
const edit = await getRenameEdits(doc, new vscode.Position(0, 10), './sub/newDoc.md', new InMemoryMdWorkspace([doc]));
assertEditsEqual(edit!, {
originalUri: uri,
newUri: workspacePath('sub', 'newDoc.md'),
@ -400,7 +400,7 @@ suite('markdown: rename', () => {
`[ref]: /sub/doc.md`,
));
const edit = await getRenameEdits(doc, new vscode.Position(0, 10), '/newSub/newDoc.md', new InMemoryWorkspaceMarkdownDocuments([doc]));
const edit = await getRenameEdits(doc, new vscode.Position(0, 10), '/newSub/newDoc.md', new InMemoryMdWorkspace([doc]));
assertEditsEqual(edit!, {
originalUri: uri,
newUri: workspacePath('newSub', 'newDoc.md'),
@ -418,7 +418,7 @@ suite('markdown: rename', () => {
`[text](/sub/doc%20with%20spaces.md)`,
));
const info = await prepareRename(doc, new vscode.Position(0, 10), new InMemoryWorkspaceMarkdownDocuments([doc]));
const info = await prepareRename(doc, new vscode.Position(0, 10), new InMemoryMdWorkspace([doc]));
assert.strictEqual(info!.placeholder, '/sub/doc with spaces.md');
});
@ -429,7 +429,7 @@ suite('markdown: rename', () => {
`[ref]: /sub/doc.md`,
));
const edit = await getRenameEdits(doc, new vscode.Position(0, 10), '/NEW sub/new DOC.md', new InMemoryWorkspaceMarkdownDocuments([doc]));
const edit = await getRenameEdits(doc, new vscode.Position(0, 10), '/NEW sub/new DOC.md', new InMemoryMdWorkspace([doc]));
assertEditsEqual(edit!, {
originalUri: uri,
newUri: workspacePath('NEW sub', 'new DOC.md'),
@ -454,7 +454,7 @@ suite('markdown: rename', () => {
`![img](/images/more/image.png)`,
));
const edit = await getRenameEdits(doc1, new vscode.Position(0, 10), '/img/test/new.png', new InMemoryWorkspaceMarkdownDocuments([
const edit = await getRenameEdits(doc1, new vscode.Position(0, 10), '/img/test/new.png', new InMemoryMdWorkspace([
doc1,
doc2
]));
@ -480,7 +480,7 @@ suite('markdown: rename', () => {
`[ref]: /doc#other`,
));
const edit = await getRenameEdits(doc, new vscode.Position(0, 10), '/new File', new InMemoryWorkspaceMarkdownDocuments([doc]));
const edit = await getRenameEdits(doc, new vscode.Position(0, 10), '/new File', new InMemoryMdWorkspace([doc]));
assertEditsEqual(edit!, {
originalUri: uri,
newUri: workspacePath('new File.md'), // Rename on disk should use file extension
@ -518,7 +518,7 @@ suite('markdown: rename', () => {
`[ref]: /sub/doc.md`,
));
const edit = await getRenameEdits(doc1, new vscode.Position(0, 10), './new/new-doc.md', new InMemoryWorkspaceMarkdownDocuments([
const edit = await getRenameEdits(doc1, new vscode.Position(0, 10), './new/new-doc.md', new InMemoryMdWorkspace([
doc1, doc2, doc3, doc4,
]));
assertEditsEqual(edit!, {
@ -561,7 +561,7 @@ suite('markdown: rename', () => {
const uri3 = workspacePath('sub', 'sub2', 'doc3.md');
const doc3 = new InMemoryDocument(uri3, joinLines());
const edit = await getRenameEdits(doc1, new vscode.Position(0, 10), 'sub2/cat.md', new InMemoryWorkspaceMarkdownDocuments([
const edit = await getRenameEdits(doc1, new vscode.Position(0, 10), 'sub2/cat.md', new InMemoryMdWorkspace([
doc1, doc2, doc3
]));
assertEditsEqual(edit!, {
@ -581,7 +581,7 @@ suite('markdown: rename', () => {
`[text](#a-b-c)`,
));
const info = await prepareRename(doc, new vscode.Position(1, 10), new InMemoryWorkspaceMarkdownDocuments([doc]));
const info = await prepareRename(doc, new vscode.Position(1, 10), new InMemoryMdWorkspace([doc]));
assert.strictEqual(info!.placeholder, 'a B c');
assertRangeEqual(info!.range, new vscode.Range(1, 8, 1, 13));
});
@ -595,7 +595,7 @@ suite('markdown: rename', () => {
`<http://example.com>`,
));
const edit = await getRenameEdits(doc, new vscode.Position(1, 10), "https://example.com/sub", new InMemoryWorkspaceMarkdownDocuments([
const edit = await getRenameEdits(doc, new vscode.Position(1, 10), "https://example.com/sub", new InMemoryMdWorkspace([
doc,
new InMemoryDocument(uri2, joinLines(
`[4](http://example.com)`,
@ -622,7 +622,7 @@ suite('markdown: rename', () => {
`[ref]: /file`, // rename here
));
const workspace = new InMemoryWorkspaceMarkdownDocuments([doc]);
const workspace = new InMemoryMdWorkspace([doc]);
const preparedInfo = await prepareRename(doc, new vscode.Position(2, 10), workspace);
assert.strictEqual(preparedInfo!.placeholder, '/file');
@ -648,7 +648,7 @@ suite('markdown: rename', () => {
const uri2 = workspacePath('doc2.md');
const doc2 = new InMemoryDocument(uri2, joinLines());
const workspace = new InMemoryWorkspaceMarkdownDocuments([doc1, doc2]);
const workspace = new InMemoryMdWorkspace([doc1, doc2]);
const preparedInfo = await prepareRename(doc1, new vscode.Position(2, 10), workspace);
assert.strictEqual(preparedInfo!.placeholder, '/doc2');
@ -674,7 +674,7 @@ suite('markdown: rename', () => {
`[ref]: /file#header`, // rename here
));
const workspace = new InMemoryWorkspaceMarkdownDocuments([doc]);
const workspace = new InMemoryMdWorkspace([doc]);
const preparedInfo = await prepareRename(doc, new vscode.Position(2, 16), workspace);
assert.strictEqual(preparedInfo!.placeholder, 'header');

View file

@ -9,7 +9,7 @@ import { MdSmartSelect } from '../languageFeatures/smartSelect';
import { MdTableOfContentsProvider } from '../tableOfContents';
import { InMemoryDocument } from '../util/inMemoryDocument';
import { createNewMarkdownEngine } from './engine';
import { InMemoryWorkspaceMarkdownDocuments } from './inMemoryWorkspace';
import { InMemoryMdWorkspace } from './inMemoryWorkspace';
import { nulLogger } from './nulLogging';
import { CURSOR, getCursorPositions, joinLines } from './util';
@ -723,7 +723,7 @@ function assertLineNumbersEqual(selectionRange: vscode.SelectionRange, startLine
function getSelectionRangesForDocument(contents: string, pos?: vscode.Position[]): Promise<vscode.SelectionRange[] | undefined> {
const doc = new InMemoryDocument(testFileName, contents);
const workspace = new InMemoryWorkspaceMarkdownDocuments([doc]);
const workspace = new InMemoryMdWorkspace([doc]);
const engine = createNewMarkdownEngine();
const provider = new MdSmartSelect(engine, new MdTableOfContentsProvider(engine, workspace, nulLogger));
const positions = pos ? pos : getCursorPositions(contents, doc);

View file

@ -7,14 +7,14 @@ import * as assert from 'assert';
import 'mocha';
import * as vscode from 'vscode';
import { TableOfContents } from '../tableOfContents';
import { ITextDocument } from '../types/textDocument';
import { InMemoryDocument } from '../util/inMemoryDocument';
import { SkinnyTextDocument } from '../workspaceContents';
import { createNewMarkdownEngine } from './engine';
const testFileName = vscode.Uri.file('test.md');
function createToc(doc: SkinnyTextDocument): Promise<TableOfContents> {
function createToc(doc: ITextDocument): Promise<TableOfContents> {
const engine = createNewMarkdownEngine();
return TableOfContents.create(engine, doc);
}

View file

@ -9,14 +9,15 @@ import * as vscode from 'vscode';
import { MdDocumentSymbolProvider } from '../languageFeatures/documentSymbols';
import { MdWorkspaceSymbolProvider } from '../languageFeatures/workspaceSymbols';
import { MdTableOfContentsProvider } from '../tableOfContents';
import { ITextDocument } from '../types/textDocument';
import { InMemoryDocument } from '../util/inMemoryDocument';
import { MdWorkspaceContents, SkinnyTextDocument } from '../workspaceContents';
import { IMdWorkspace } from '../workspace';
import { createNewMarkdownEngine } from './engine';
import { InMemoryWorkspaceMarkdownDocuments } from './inMemoryWorkspace';
import { InMemoryMdWorkspace } from './inMemoryWorkspace';
import { nulLogger } from './nulLogging';
import { workspacePath } from './util';
function getWorkspaceSymbols(workspace: MdWorkspaceContents, query = ''): Promise<vscode.SymbolInformation[]> {
function getWorkspaceSymbols(workspace: IMdWorkspace, query = ''): Promise<vscode.SymbolInformation[]> {
const engine = createNewMarkdownEngine();
const symbolProvider = new MdDocumentSymbolProvider(new MdTableOfContentsProvider(engine, workspace, nulLogger), nulLogger);
return new MdWorkspaceSymbolProvider(symbolProvider, workspace).provideWorkspaceSymbols(query);
@ -24,12 +25,12 @@ function getWorkspaceSymbols(workspace: MdWorkspaceContents, query = ''): Promis
suite('markdown.WorkspaceSymbolProvider', () => {
test('Should not return anything for empty workspace', async () => {
const workspace = new InMemoryWorkspaceMarkdownDocuments([]);
const workspace = new InMemoryMdWorkspace([]);
assert.deepStrictEqual(await getWorkspaceSymbols(workspace, ''), []);
});
test('Should return symbols from workspace with one markdown file', async () => {
const workspace = new InMemoryWorkspaceMarkdownDocuments([
const workspace = new InMemoryMdWorkspace([
new InMemoryDocument(workspacePath('test.md'), `# header1\nabc\n## header2`)
]);
@ -41,13 +42,13 @@ suite('markdown.WorkspaceSymbolProvider', () => {
test('Should return all content basic workspace', async () => {
const fileNameCount = 10;
const files: SkinnyTextDocument[] = [];
const files: ITextDocument[] = [];
for (let i = 0; i < fileNameCount; ++i) {
const testFileName = workspacePath(`test${i}.md`);
files.push(new InMemoryDocument(testFileName, `# common\nabc\n## header${i}`));
}
const workspace = new InMemoryWorkspaceMarkdownDocuments(files);
const workspace = new InMemoryMdWorkspace(files);
const symbols = await getWorkspaceSymbols(workspace, '');
assert.strictEqual(symbols.length, fileNameCount * 2);
@ -55,7 +56,7 @@ suite('markdown.WorkspaceSymbolProvider', () => {
test('Should update results when markdown file changes symbols', async () => {
const testFileName = workspacePath('test.md');
const workspace = new InMemoryWorkspaceMarkdownDocuments([
const workspace = new InMemoryMdWorkspace([
new InMemoryDocument(testFileName, `# header1`, 1 /* version */)
]);
@ -72,7 +73,7 @@ suite('markdown.WorkspaceSymbolProvider', () => {
test('Should remove results when file is deleted', async () => {
const testFileName = workspacePath('test.md');
const workspace = new InMemoryWorkspaceMarkdownDocuments([
const workspace = new InMemoryMdWorkspace([
new InMemoryDocument(testFileName, `# header1`)
]);
@ -87,7 +88,7 @@ suite('markdown.WorkspaceSymbolProvider', () => {
test('Should update results when markdown file is created', async () => {
const testFileName = workspacePath('test.md');
const workspace = new InMemoryWorkspaceMarkdownDocuments([
const workspace = new InMemoryMdWorkspace([
new InMemoryDocument(testFileName, `# header1`)
]);

View file

@ -0,0 +1,27 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import type * as vscode from 'vscode';
/**
* Minimal version of {@link vscode.TextLine}.
*/
export interface ITextLine {
readonly text: string;
readonly isEmptyOrWhitespace: boolean;
}
/**
* Minimal version of {@link vscode.TextDocument}.
*/
export interface ITextDocument {
readonly uri: vscode.Uri;
readonly version: number;
readonly lineCount: number;
getText(range?: vscode.Range): string;
lineAt(line: number): ITextLine;
positionAt(offset: number): vscode.Position;
}

View file

@ -5,13 +5,13 @@
import * as vscode from 'vscode';
import { TextDocument } from 'vscode-languageserver-textdocument';
import { SkinnyTextDocument, SkinnyTextLine } from '../workspaceContents';
import { ITextDocument, ITextLine } from '../types/textDocument';
export class InMemoryDocument implements SkinnyTextDocument {
export class InMemoryDocument implements ITextDocument {
private readonly _doc: TextDocument;
private lines: SkinnyTextLine[] | undefined;
private lines: ITextLine[] | undefined;
constructor(
public readonly uri: vscode.Uri, contents: string,
@ -25,7 +25,7 @@ export class InMemoryDocument implements SkinnyTextDocument {
return this._doc.lineCount;
}
lineAt(index: any): SkinnyTextLine {
lineAt(index: any): ITextLine {
if (!this.lines) {
this.lines = this._doc.getText().split(/\r?\n/).map(text => ({
text,

View file

@ -5,7 +5,8 @@
import * as vscode from 'vscode';
import { MdTableOfContentsProvider, TableOfContents } from '../tableOfContents';
import { MdWorkspaceContents, SkinnyTextDocument } from '../workspaceContents';
import { ITextDocument } from '../types/textDocument';
import { IMdWorkspace } from '../workspace';
import { equals } from './arrays';
import { Delayer } from './async';
import { Disposable } from './dispose';
@ -36,7 +37,7 @@ export class MdTableOfContentsWatcher extends Disposable {
private readonly delayer: Delayer<void>;
public constructor(
private readonly workspaceContents: MdWorkspaceContents,
private readonly workspace: IMdWorkspace,
private readonly tocProvider: MdTableOfContentsProvider,
private readonly delay: number,
) {
@ -44,17 +45,17 @@ export class MdTableOfContentsWatcher extends Disposable {
this.delayer = this._register(new Delayer<void>(delay));
this._register(this.workspaceContents.onDidChangeMarkdownDocument(this.onDidChangeDocument, this));
this._register(this.workspaceContents.onDidCreateMarkdownDocument(this.onDidCreateDocument, this));
this._register(this.workspaceContents.onDidDeleteMarkdownDocument(this.onDidDeleteDocument, this));
this._register(this.workspace.onDidChangeMarkdownDocument(this.onDidChangeDocument, this));
this._register(this.workspace.onDidCreateMarkdownDocument(this.onDidCreateDocument, this));
this._register(this.workspace.onDidDeleteMarkdownDocument(this.onDidDeleteDocument, this));
}
private async onDidCreateDocument(document: SkinnyTextDocument) {
private async onDidCreateDocument(document: ITextDocument) {
const toc = await this.tocProvider.getForDocument(document);
this._files.set(document.uri, { toc });
}
private async onDidChangeDocument(document: SkinnyTextDocument) {
private async onDidChangeDocument(document: ITextDocument) {
if (this.delay > 0) {
this._pending.set(document.uri);
this.delayer.trigger(() => this.flushPending());

View file

@ -4,10 +4,11 @@
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import { ITextDocument } from '../types/textDocument';
import { IMdWorkspace } from '../workspace';
import { Disposable } from './dispose';
import { Lazy, lazy } from './lazy';
import { ResourceMap } from './resourceMap';
import { MdWorkspaceContents, SkinnyTextDocument } from '../workspaceContents';
class LazyResourceMap<T> {
private readonly _map = new ResourceMap<Lazy<Promise<T>>>();
@ -43,16 +44,16 @@ class LazyResourceMap<T> {
export class MdDocumentInfoCache<T> extends Disposable {
private readonly _cache = new LazyResourceMap<T>();
private readonly _loadingDocuments = new ResourceMap<Promise<SkinnyTextDocument | undefined>>();
private readonly _loadingDocuments = new ResourceMap<Promise<ITextDocument | undefined>>();
public constructor(
private readonly workspaceContents: MdWorkspaceContents,
private readonly getValue: (document: SkinnyTextDocument) => Promise<T>,
private readonly workspace: IMdWorkspace,
private readonly getValue: (document: ITextDocument) => Promise<T>,
) {
super();
this._register(this.workspaceContents.onDidChangeMarkdownDocument(doc => this.invalidate(doc)));
this._register(this.workspaceContents.onDidDeleteMarkdownDocument(this.onDidDeleteDocument, this));
this._register(this.workspace.onDidChangeMarkdownDocument(doc => this.invalidate(doc)));
this._register(this.workspace.onDidDeleteMarkdownDocument(this.onDidDeleteDocument, this));
}
public async get(resource: vscode.Uri): Promise<T | undefined> {
@ -75,7 +76,7 @@ export class MdDocumentInfoCache<T> extends Disposable {
return this.resetEntry(doc)?.value;
}
public async getForDocument(document: SkinnyTextDocument): Promise<T> {
public async getForDocument(document: ITextDocument): Promise<T> {
const existing = this._cache.get(document.uri);
if (existing) {
return existing;
@ -83,13 +84,13 @@ export class MdDocumentInfoCache<T> extends Disposable {
return this.resetEntry(document).value;
}
private loadDocument(resource: vscode.Uri): Promise<SkinnyTextDocument | undefined> {
private loadDocument(resource: vscode.Uri): Promise<ITextDocument | undefined> {
const existing = this._loadingDocuments.get(resource);
if (existing) {
return existing;
}
const p = this.workspaceContents.getOrLoadMarkdownDocument(resource);
const p = this.workspace.getOrLoadMarkdownDocument(resource);
this._loadingDocuments.set(resource, p);
p.finally(() => {
this._loadingDocuments.delete(resource);
@ -97,13 +98,13 @@ export class MdDocumentInfoCache<T> extends Disposable {
return p;
}
private resetEntry(document: SkinnyTextDocument): Lazy<Promise<T>> {
private resetEntry(document: ITextDocument): Lazy<Promise<T>> {
const value = lazy(() => this.getValue(document));
this._cache.set(document.uri, value);
return value;
}
private invalidate(document: SkinnyTextDocument): void {
private invalidate(document: ITextDocument): void {
if (this._cache.has(document.uri)) {
this.resetEntry(document);
}
@ -126,8 +127,8 @@ export class MdWorkspaceInfoCache<T> extends Disposable {
private _init?: Promise<void>;
public constructor(
private readonly workspaceContents: MdWorkspaceContents,
private readonly getValue: (document: SkinnyTextDocument) => Promise<T>,
private readonly workspace: IMdWorkspace,
private readonly getValue: (document: ITextDocument) => Promise<T>,
) {
super();
}
@ -146,25 +147,25 @@ export class MdWorkspaceInfoCache<T> extends Disposable {
if (!this._init) {
this._init = this.populateCache();
this._register(this.workspaceContents.onDidChangeMarkdownDocument(this.onDidChangeDocument, this));
this._register(this.workspaceContents.onDidCreateMarkdownDocument(this.onDidChangeDocument, this));
this._register(this.workspaceContents.onDidDeleteMarkdownDocument(this.onDidDeleteDocument, this));
this._register(this.workspace.onDidChangeMarkdownDocument(this.onDidChangeDocument, this));
this._register(this.workspace.onDidCreateMarkdownDocument(this.onDidChangeDocument, this));
this._register(this.workspace.onDidDeleteMarkdownDocument(this.onDidDeleteDocument, this));
}
await this._init;
}
private async populateCache(): Promise<void> {
const markdownDocumentUris = await this.workspaceContents.getAllMarkdownDocuments();
const markdownDocumentUris = await this.workspace.getAllMarkdownDocuments();
for (const document of markdownDocumentUris) {
this.update(document);
}
}
private update(document: SkinnyTextDocument): void {
private update(document: ITextDocument): void {
this._cache.set(document.uri, lazy(() => this.getValue(document)));
}
private onDidChangeDocument(document: SkinnyTextDocument) {
private onDidChangeDocument(document: ITextDocument) {
this.update(document);
}

View file

@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import { ITextDocument } from './types/textDocument';
import { coalesce } from './util/arrays';
import { Disposable } from './util/dispose';
import { isMarkdownFile, looksLikeMarkdownPath } from './util/file';
@ -11,47 +12,26 @@ import { InMemoryDocument } from './util/inMemoryDocument';
import { Limiter } from './util/limiter';
import { ResourceMap } from './util/resourceMap';
/**
* Minimal version of {@link vscode.TextLine}. Used for mocking out in testing.
*/
export interface SkinnyTextLine {
readonly text: string;
readonly isEmptyOrWhitespace: boolean;
}
/**
* Minimal version of {@link vscode.TextDocument}. Used for mocking out in testing.
*/
export interface SkinnyTextDocument {
readonly uri: vscode.Uri;
readonly version: number;
readonly lineCount: number;
getText(range?: vscode.Range): string;
lineAt(line: number): SkinnyTextLine;
positionAt(offset: number): vscode.Position;
}
/**
* Provides set of markdown files in the current workspace.
*/
export interface MdWorkspaceContents {
export interface IMdWorkspace {
/**
* Get list of all known markdown files.
*/
getAllMarkdownDocuments(): Promise<Iterable<SkinnyTextDocument>>;
getAllMarkdownDocuments(): Promise<Iterable<ITextDocument>>;
/**
* Check if a document already exists in the workspace contents.
*/
hasMarkdownDocument(resource: vscode.Uri): boolean;
getOrLoadMarkdownDocument(resource: vscode.Uri): Promise<SkinnyTextDocument | undefined>;
getOrLoadMarkdownDocument(resource: vscode.Uri): Promise<ITextDocument | undefined>;
pathExists(resource: vscode.Uri): Promise<boolean>;
readonly onDidChangeMarkdownDocument: vscode.Event<SkinnyTextDocument>;
readonly onDidCreateMarkdownDocument: vscode.Event<SkinnyTextDocument>;
readonly onDidChangeMarkdownDocument: vscode.Event<ITextDocument>;
readonly onDidCreateMarkdownDocument: vscode.Event<ITextDocument>;
readonly onDidDeleteMarkdownDocument: vscode.Event<vscode.Uri>;
}
@ -60,15 +40,15 @@ export interface MdWorkspaceContents {
*
* This includes both opened text documents and markdown files in the workspace.
*/
export class VsCodeMdWorkspaceContents extends Disposable implements MdWorkspaceContents {
export class VsCodeMdWorkspace extends Disposable implements IMdWorkspace {
private readonly _onDidChangeMarkdownDocumentEmitter = this._register(new vscode.EventEmitter<SkinnyTextDocument>());
private readonly _onDidCreateMarkdownDocumentEmitter = this._register(new vscode.EventEmitter<SkinnyTextDocument>());
private readonly _onDidChangeMarkdownDocumentEmitter = this._register(new vscode.EventEmitter<ITextDocument>());
private readonly _onDidCreateMarkdownDocumentEmitter = this._register(new vscode.EventEmitter<ITextDocument>());
private readonly _onDidDeleteMarkdownDocumentEmitter = this._register(new vscode.EventEmitter<vscode.Uri>());
private _watcher: vscode.FileSystemWatcher | undefined;
private readonly _documentCache = new ResourceMap<SkinnyTextDocument>();
private readonly _documentCache = new ResourceMap<ITextDocument>();
private readonly utf8Decoder = new TextDecoder('utf-8');
@ -78,11 +58,11 @@ export class VsCodeMdWorkspaceContents extends Disposable implements MdWorkspace
*
* @returns Array of processed .md files.
*/
async getAllMarkdownDocuments(): Promise<SkinnyTextDocument[]> {
async getAllMarkdownDocuments(): Promise<ITextDocument[]> {
const maxConcurrent = 20;
const foundFiles = new Set<string>();
const limiter = new Limiter<SkinnyTextDocument | undefined>(maxConcurrent);
const limiter = new Limiter<ITextDocument | undefined>(maxConcurrent);
// Add files on disk
const resources = await vscode.workspace.findFiles('**/*.md', '**/node_modules/**');
@ -167,7 +147,7 @@ export class VsCodeMdWorkspaceContents extends Disposable implements MdWorkspace
return isMarkdownFile(doc) && doc.uri.scheme !== 'vscode-bulkeditpreview';
}
public async getOrLoadMarkdownDocument(resource: vscode.Uri): Promise<SkinnyTextDocument | undefined> {
public async getOrLoadMarkdownDocument(resource: vscode.Uri): Promise<ITextDocument | undefined> {
const existing = this._documentCache.get(resource);
if (existing) {
return existing;