Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions extensions/markdown-language-features/src/docIndex.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import * as vscode from 'vscode';
import { Disposable } from './util/dispose';


export class DocumentIndex extends Disposable {
private readonly _uriMap = new Map();

constructor() {
super();

for (let doc of vscode.workspace.textDocuments) {
this._registerDoc(doc);
}

this._register(
vscode.workspace.onDidOpenTextDocument((doc) => {
this._registerDoc(doc);
})
);
this._register(
vscode.workspace.onDidCloseTextDocument((doc) => {
this._unregisterDoc(doc.uri);
})
);
}

getByUri(uri: vscode.Uri): vscode.TextDocument | undefined {
return this._uriMap.get(uri.toString());
}

private _registerDoc(doc: vscode.TextDocument) {
const uri = doc.uri.toString();
if (this._uriMap.has(uri)) {
throw new Error(`The document ${uri} is already registered.`);
}
this._uriMap.set(uri, doc);
}

private _unregisterDoc(uri: vscode.Uri) {
if (!this._uriMap.has(uri.toString())) {
throw new Error(`The document ${uri.toString()} is not registered.`);
}
this._uriMap.delete(uri.toString());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ import { Disposable } from '../util/dispose';
import { isMarkdownFile } from '../util/file';
import { Lazy, lazy } from '../util/lazy';
import MDDocumentSymbolProvider from './documentSymbolProvider';
import { SkinnyTextDocument } from '../tableOfContentsProvider';
import { SkinnyTextDocument, SkinnyTextLine } from '../tableOfContentsProvider';
import { flatten } from '../util/arrays';
import { DocumentIndex } from '../docIndex';

export interface WorkspaceMarkdownDocumentProvider {
getAllMarkdownDocuments(): Thenable<Iterable<SkinnyTextDocument>>;
Expand All @@ -26,6 +27,7 @@ class VSCodeWorkspaceMarkdownDocumentProvider extends Disposable implements Work
private readonly _onDidDeleteMarkdownDocumentEmitter = this._register(new vscode.EventEmitter<vscode.Uri>());

private _watcher: vscode.FileSystemWatcher | undefined;
private _docIndex: DocumentIndex = this._register(new DocumentIndex());

async getAllMarkdownDocuments() {
const resources = await vscode.workspace.findFiles('**/*.md', '**/node_modules/**');
Expand Down Expand Up @@ -81,12 +83,39 @@ class VSCodeWorkspaceMarkdownDocumentProvider extends Disposable implements Work
}

private async getMarkdownDocument(resource: vscode.Uri): Promise<SkinnyTextDocument | undefined> {
const doc = await vscode.workspace.openTextDocument(resource);
return doc && isMarkdownFile(doc) ? doc : undefined;
const existingDocument = this._docIndex.getByUri(resource);
if (existingDocument) {
return existingDocument;
}

const bytes = await vscode.workspace.fs.readFile(resource);

// We assume that markdown is in UTF-8
const text = Buffer.from(bytes).toString('utf-8');

const lines: SkinnyTextLine[] = [];
const parts = text.split(/(\r?\n)/);
const lineCount = Math.floor(parts.length / 2) + 1;
for (let line = 0; line < lineCount; line++) {
lines.push({
text: parts[line * 2]
});
}

return Promise.resolve({
uri: resource,
version: 0,
lineCount: lineCount,
lineAt: (index) => {
return lines[index];
},
getText: () => {
return text;
}
});
}
}


export default class MarkdownWorkspaceSymbolProvider extends Disposable implements vscode.WorkspaceSymbolProvider {
private _symbolCache = new Map<string, Lazy<Thenable<vscode.SymbolInformation[]>>>();
private _symbolCachePopulated: boolean = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,17 @@ export interface TocEntry {
readonly location: vscode.Location;
}

export interface SkinnyTextLine {
text: string;
}

export interface SkinnyTextDocument {
readonly uri: vscode.Uri;
readonly version: number;
readonly lineCount: number;

lineAt(line: number): SkinnyTextLine;
getText(): string;
lineAt(line: number): vscode.TextLine;
}

export class TableOfContentsProvider {
Expand Down Expand Up @@ -72,7 +77,8 @@ export class TableOfContentsProvider {
text: TableOfContentsProvider.getHeaderText(line.text),
level: TableOfContentsProvider.getHeaderLevel(heading.markup),
line: lineNumber,
location: new vscode.Location(document.uri, line.range)
location: new vscode.Location(document.uri,
new vscode.Range(lineNumber, 0, lineNumber, line.text.length))
});
}

Expand All @@ -85,13 +91,13 @@ export class TableOfContentsProvider {
break;
}
}
const endLine = typeof end === 'number' ? end : document.lineCount - 1;
const endLine = end !== undefined ? end : document.lineCount - 1;
return {
...entry,
location: new vscode.Location(document.uri,
new vscode.Range(
entry.location.range.start,
new vscode.Position(endLine, document.lineAt(endLine).range.end.character)))
new vscode.Position(endLine, document.lineAt(endLine).text.length)))
};
});
}
Expand Down