Skip to content

Commit 21337ae

Browse files
authored
Pick up newest markdown language service (microsoft#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
1 parent 57fbc50 commit 21337ae

File tree

5 files changed

+81
-20
lines changed

5 files changed

+81
-20
lines changed

extensions/markdown-language-features/server/README.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,20 @@ This server uses the [Markdown Language Service](https://github.com/microsoft/vs
2323

2424
- [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.
2525

26+
- [Go to definition](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_definition) from links to headers or link definitions.
27+
2628
- [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.
2729

28-
- [Go to definition](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_definition) from links to headers or link definitions.
30+
- Find all references to a file. Uses a custom `markdown/getReferencesToFileInWorkspace` message.
2931

30-
- (experimental) [Pull diagnostics (validation)](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_pullDiagnostics) for links.
32+
- [Code Actions](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_codeAction)
3133

34+
- Organize link definitions source action.
35+
- Extract link to definition refactoring.
36+
37+
- (experimental) Updating links when a file is moved / renamed. Uses a custom `markdown/getEditForFileRenames` message.
38+
39+
- (experimental) [Pull diagnostics (validation)](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_pullDiagnostics) for links.
3240

3341

3442
## Client requirements

extensions/markdown-language-features/server/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
"vscode-languageserver": "^8.0.2",
1414
"vscode-languageserver-textdocument": "^1.0.5",
1515
"vscode-languageserver-types": "^3.17.1",
16-
"vscode-markdown-languageservice": "^0.0.1",
16+
"vscode-markdown-languageservice": "^0.1.0-alpha.1",
17+
"vscode-nls": "^5.0.1",
1718
"vscode-uri": "^3.0.3"
1819
},
1920
"devDependencies": {

extensions/markdown-language-features/server/src/server.ts

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { CancellationToken, Connection, InitializeParams, InitializeResult, Note
77
import { TextDocument } from 'vscode-languageserver-textdocument';
88
import * as lsp from 'vscode-languageserver-types';
99
import * as md from 'vscode-markdown-languageservice';
10+
import * as nls from 'vscode-nls';
1011
import { URI } from 'vscode-uri';
1112
import { getLsConfiguration, LsConfiguration } from './config';
1213
import { ConfigurationManager } from './configuration';
@@ -16,8 +17,11 @@ import * as protocol from './protocol';
1617
import { IDisposable } from './util/dispose';
1718
import { VsCodeClientWorkspace } from './workspace';
1819

20+
const localize = nls.loadMessageBundle();
21+
1922
interface MdServerInitializationOptions extends LsConfiguration { }
2023

24+
const organizeLinkDefKind = 'source.organizeLinkDefinitions';
2125
export async function startServer(connection: Connection) {
2226
const documents = new TextDocuments(TextDocument);
2327
const notebooks = new NotebookDocuments(documents);
@@ -61,6 +65,7 @@ export async function startServer(connection: Connection) {
6165
interFileDependencies: true,
6266
workspaceDiagnostics: false,
6367
},
68+
codeActionProvider: { resolveProvider: true },
6469
completionProvider: { triggerCharacters: ['.', '/', '#'] },
6570
definitionProvider: true,
6671
documentLinkProvider: { resolveProvider: true },
@@ -97,7 +102,7 @@ export async function startServer(connection: Connection) {
97102
if (!document) {
98103
return [];
99104
}
100-
return mdLs!.getDocumentSymbols(document, token);
105+
return mdLs!.getDocumentSymbols(document, { includeLinkDefinitions: true }, token);
101106
});
102107

103108
connection.onFoldingRanges(async (params, token): Promise<lsp.FoldingRange[]> => {
@@ -152,6 +157,48 @@ export async function startServer(connection: Connection) {
152157
return mdLs!.getRenameEdit(document, params.position, params.newName, token);
153158
});
154159

160+
interface OrganizeLinkActionData {
161+
readonly uri: string;
162+
}
163+
164+
connection.onCodeAction(async (params, token) => {
165+
const document = documents.get(params.textDocument.uri);
166+
if (!document) {
167+
return undefined;
168+
}
169+
170+
if (params.context.only?.some(kind => kind === 'source' || kind.startsWith('source.'))) {
171+
const action: lsp.CodeAction = {
172+
title: localize('organizeLinkDefAction.title', "Organize link definitions"),
173+
kind: organizeLinkDefKind,
174+
data: <OrganizeLinkActionData>{ uri: document.uri }
175+
};
176+
return [action];
177+
}
178+
179+
return mdLs!.getCodeActions(document, params.range, params.context, token);
180+
});
181+
182+
connection.onCodeActionResolve(async (codeAction, token) => {
183+
if (codeAction.kind === organizeLinkDefKind) {
184+
const data = codeAction.data as OrganizeLinkActionData;
185+
const document = documents.get(data.uri);
186+
if (!document) {
187+
return codeAction;
188+
}
189+
190+
const edits = (await mdLs?.organizeLinkDefinitions(document, { removeUnused: true }, token)) || [];
191+
codeAction.edit = {
192+
changes: {
193+
[data.uri]: edits
194+
}
195+
};
196+
return codeAction;
197+
}
198+
199+
return codeAction;
200+
});
201+
155202
connection.onRequest(protocol.getReferencesToFileInWorkspace, (async (params: { uri: string }, token: CancellationToken) => {
156203
return mdLs!.getFileReferences(URI.parse(params.uri), token);
157204
}));

extensions/markdown-language-features/server/src/workspace.ts

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import { ContainingDocumentContext, FileWatcherOptions, IFileSystemWatcher } fro
1010
import { URI } from 'vscode-uri';
1111
import { LsConfiguration } from './config';
1212
import * as protocol from './protocol';
13-
import { coalesce } from './util/arrays';
1413
import { isMarkdownFile, looksLikeMarkdownPath } from './util/file';
1514
import { Limiter } from './util/limiter';
1615
import { ResourceMap } from './util/resourceMap';
@@ -133,29 +132,35 @@ export class VsCodeClientWorkspace implements md.IWorkspaceWithWatching {
133132
}
134133

135134
async getAllMarkdownDocuments(): Promise<Iterable<md.ITextDocument>> {
136-
const maxConcurrent = 20;
135+
// Add opened files (such as untitled files)
136+
const openTextDocumentResults = this.documents.all()
137+
.filter(doc => this.isRelevantMarkdownDocument(doc));
137138

138-
const foundFiles = new ResourceMap<void>();
139-
const limiter = new Limiter<md.ITextDocument | undefined>(maxConcurrent);
139+
const allDocs = new ResourceMap<md.ITextDocument>();
140+
for (const doc of openTextDocumentResults) {
141+
allDocs.set(URI.parse(doc.uri), doc);
142+
}
140143

141-
// Add files on disk
144+
// And then add files on disk
145+
const maxConcurrent = 20;
146+
const limiter = new Limiter<md.ITextDocument | undefined>(maxConcurrent);
142147
const resources = await this.connection.sendRequest(protocol.findMarkdownFilesInWorkspace, {});
143-
const onDiskResults = await Promise.all(resources.map(strResource => {
148+
await Promise.all(resources.map(strResource => {
144149
return limiter.queue(async () => {
145150
const resource = URI.parse(strResource);
151+
if (allDocs.has(resource)) {
152+
return;
153+
}
154+
146155
const doc = await this.openMarkdownDocument(resource);
147156
if (doc) {
148-
foundFiles.set(resource);
157+
allDocs.set(resource, doc);
149158
}
150159
return doc;
151160
});
152161
}));
153162

154-
// Add opened files (such as untitled files)
155-
const openTextDocumentResults = await Promise.all(this.documents.all()
156-
.filter(doc => !foundFiles.has(URI.parse(doc.uri)) && this.isRelevantMarkdownDocument(doc)));
157-
158-
return coalesce([...onDiskResults, ...openTextDocumentResults]);
163+
return allDocs.values();
159164
}
160165

161166
hasMarkdownDocument(resource: URI): boolean {

extensions/markdown-language-features/server/yarn.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,10 @@ vscode-languageserver@^8.0.2:
4242
dependencies:
4343
vscode-languageserver-protocol "3.17.2"
4444

45-
vscode-markdown-languageservice@^0.0.1:
46-
version "0.0.1"
47-
resolved "https://registry.yarnpkg.com/vscode-markdown-languageservice/-/vscode-markdown-languageservice-0.0.1.tgz#40398c7cb2d169359e690bc76bd6618dc377e58a"
48-
integrity sha512-zQuAJXLY3Wmu7LknHaes8dDZt0TWwgJQlLocbHgBtnMp6Tdv7zgNToIkW4k4OReqpiOLt0llIamM29e6ober0Q==
45+
vscode-markdown-languageservice@^0.1.0-alpha.1:
46+
version "0.1.0-alpha.1"
47+
resolved "https://registry.yarnpkg.com/vscode-markdown-languageservice/-/vscode-markdown-languageservice-0.1.0-alpha.1.tgz#60a9b445240eb2f90b5f2cfe203f9cdf1773d674"
48+
integrity sha512-2detAtQRLGdc6MgdQI/8/+Bypa3enw6SA/ia4PCBctwO422kvYjBlyICnqP12ju6DVUNxfLQg5aNqa90xO1H2A==
4949
dependencies:
5050
picomatch "^2.3.1"
5151
vscode-languageserver-textdocument "^1.0.5"

0 commit comments

Comments
 (0)