Pick up newest markdown language service (#159619)

This brings support for code actions and source actions, along with some bug fixes

Also fixes `getAllMarkdownDocuments` to prefer open documents instead of those on disk
This commit is contained in:
Matt Bierner 2022-08-31 00:20:41 -07:00 committed by GitHub
parent 57fbc50857
commit 21337aed3f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 82 additions and 21 deletions

View file

@ -23,12 +23,20 @@ This server uses the [Markdown Language Service](https://github.com/microsoft/vs
- [Find all references](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_references) to headers and links across all Markdown files in the workspace.
- [Rename](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_rename) of headers and links across all Markdown files in the workspace.
- [Go to definition](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_definition) from links to headers or link definitions.
- (experimental) [Pull diagnostics (validation)](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_pullDiagnostics) for links.
- [Rename](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_rename) of headers and links across all Markdown files in the workspace.
- Find all references to a file. Uses a custom `markdown/getReferencesToFileInWorkspace` message.
- [Code Actions](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_codeAction)
- Organize link definitions source action.
- Extract link to definition refactoring.
- (experimental) Updating links when a file is moved / renamed. Uses a custom `markdown/getEditForFileRenames` message.
- (experimental) [Pull diagnostics (validation)](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_pullDiagnostics) for links.
## Client requirements

View file

@ -13,7 +13,8 @@
"vscode-languageserver": "^8.0.2",
"vscode-languageserver-textdocument": "^1.0.5",
"vscode-languageserver-types": "^3.17.1",
"vscode-markdown-languageservice": "^0.0.1",
"vscode-markdown-languageservice": "^0.1.0-alpha.1",
"vscode-nls": "^5.0.1",
"vscode-uri": "^3.0.3"
},
"devDependencies": {

View file

@ -7,6 +7,7 @@ import { CancellationToken, Connection, InitializeParams, InitializeResult, Note
import { TextDocument } from 'vscode-languageserver-textdocument';
import * as lsp from 'vscode-languageserver-types';
import * as md from 'vscode-markdown-languageservice';
import * as nls from 'vscode-nls';
import { URI } from 'vscode-uri';
import { getLsConfiguration, LsConfiguration } from './config';
import { ConfigurationManager } from './configuration';
@ -16,8 +17,11 @@ import * as protocol from './protocol';
import { IDisposable } from './util/dispose';
import { VsCodeClientWorkspace } from './workspace';
const localize = nls.loadMessageBundle();
interface MdServerInitializationOptions extends LsConfiguration { }
const organizeLinkDefKind = 'source.organizeLinkDefinitions';
export async function startServer(connection: Connection) {
const documents = new TextDocuments(TextDocument);
const notebooks = new NotebookDocuments(documents);
@ -61,6 +65,7 @@ export async function startServer(connection: Connection) {
interFileDependencies: true,
workspaceDiagnostics: false,
},
codeActionProvider: { resolveProvider: true },
completionProvider: { triggerCharacters: ['.', '/', '#'] },
definitionProvider: true,
documentLinkProvider: { resolveProvider: true },
@ -97,7 +102,7 @@ export async function startServer(connection: Connection) {
if (!document) {
return [];
}
return mdLs!.getDocumentSymbols(document, token);
return mdLs!.getDocumentSymbols(document, { includeLinkDefinitions: true }, token);
});
connection.onFoldingRanges(async (params, token): Promise<lsp.FoldingRange[]> => {
@ -152,6 +157,48 @@ export async function startServer(connection: Connection) {
return mdLs!.getRenameEdit(document, params.position, params.newName, token);
});
interface OrganizeLinkActionData {
readonly uri: string;
}
connection.onCodeAction(async (params, token) => {
const document = documents.get(params.textDocument.uri);
if (!document) {
return undefined;
}
if (params.context.only?.some(kind => kind === 'source' || kind.startsWith('source.'))) {
const action: lsp.CodeAction = {
title: localize('organizeLinkDefAction.title', "Organize link definitions"),
kind: organizeLinkDefKind,
data: <OrganizeLinkActionData>{ uri: document.uri }
};
return [action];
}
return mdLs!.getCodeActions(document, params.range, params.context, token);
});
connection.onCodeActionResolve(async (codeAction, token) => {
if (codeAction.kind === organizeLinkDefKind) {
const data = codeAction.data as OrganizeLinkActionData;
const document = documents.get(data.uri);
if (!document) {
return codeAction;
}
const edits = (await mdLs?.organizeLinkDefinitions(document, { removeUnused: true }, token)) || [];
codeAction.edit = {
changes: {
[data.uri]: edits
}
};
return codeAction;
}
return codeAction;
});
connection.onRequest(protocol.getReferencesToFileInWorkspace, (async (params: { uri: string }, token: CancellationToken) => {
return mdLs!.getFileReferences(URI.parse(params.uri), token);
}));

View file

@ -10,7 +10,6 @@ import { ContainingDocumentContext, FileWatcherOptions, IFileSystemWatcher } fro
import { URI } from 'vscode-uri';
import { LsConfiguration } from './config';
import * as protocol from './protocol';
import { coalesce } from './util/arrays';
import { isMarkdownFile, looksLikeMarkdownPath } from './util/file';
import { Limiter } from './util/limiter';
import { ResourceMap } from './util/resourceMap';
@ -133,29 +132,35 @@ export class VsCodeClientWorkspace implements md.IWorkspaceWithWatching {
}
async getAllMarkdownDocuments(): Promise<Iterable<md.ITextDocument>> {
// Add opened files (such as untitled files)
const openTextDocumentResults = this.documents.all()
.filter(doc => this.isRelevantMarkdownDocument(doc));
const allDocs = new ResourceMap<md.ITextDocument>();
for (const doc of openTextDocumentResults) {
allDocs.set(URI.parse(doc.uri), doc);
}
// And then add files on disk
const maxConcurrent = 20;
const foundFiles = new ResourceMap<void>();
const limiter = new Limiter<md.ITextDocument | undefined>(maxConcurrent);
// Add files on disk
const resources = await this.connection.sendRequest(protocol.findMarkdownFilesInWorkspace, {});
const onDiskResults = await Promise.all(resources.map(strResource => {
await Promise.all(resources.map(strResource => {
return limiter.queue(async () => {
const resource = URI.parse(strResource);
if (allDocs.has(resource)) {
return;
}
const doc = await this.openMarkdownDocument(resource);
if (doc) {
foundFiles.set(resource);
allDocs.set(resource, doc);
}
return doc;
});
}));
// Add opened files (such as untitled files)
const openTextDocumentResults = await Promise.all(this.documents.all()
.filter(doc => !foundFiles.has(URI.parse(doc.uri)) && this.isRelevantMarkdownDocument(doc)));
return coalesce([...onDiskResults, ...openTextDocumentResults]);
return allDocs.values();
}
hasMarkdownDocument(resource: URI): boolean {

View file

@ -42,10 +42,10 @@ vscode-languageserver@^8.0.2:
dependencies:
vscode-languageserver-protocol "3.17.2"
vscode-markdown-languageservice@^0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/vscode-markdown-languageservice/-/vscode-markdown-languageservice-0.0.1.tgz#40398c7cb2d169359e690bc76bd6618dc377e58a"
integrity sha512-zQuAJXLY3Wmu7LknHaes8dDZt0TWwgJQlLocbHgBtnMp6Tdv7zgNToIkW4k4OReqpiOLt0llIamM29e6ober0Q==
vscode-markdown-languageservice@^0.1.0-alpha.1:
version "0.1.0-alpha.1"
resolved "https://registry.yarnpkg.com/vscode-markdown-languageservice/-/vscode-markdown-languageservice-0.1.0-alpha.1.tgz#60a9b445240eb2f90b5f2cfe203f9cdf1773d674"
integrity sha512-2detAtQRLGdc6MgdQI/8/+Bypa3enw6SA/ia4PCBctwO422kvYjBlyICnqP12ju6DVUNxfLQg5aNqa90xO1H2A==
dependencies:
picomatch "^2.3.1"
vscode-languageserver-textdocument "^1.0.5"