Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix activation of linters on unopened files caused by markdown plugin #80506

Merged
merged 11 commits into from
Sep 11, 2019
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