Pick up new markdown LS version (#157843)

This commit is contained in:
Matt Bierner 2022-08-10 18:16:24 -07:00 committed by GitHub
parent f3e488a7b7
commit 38ea5c22a6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 118 additions and 142 deletions

View file

@ -531,12 +531,21 @@
},
"markdown.experimental.updateLinksOnFileMove.externalFileGlobs": {
"type": "string",
"default": "**/*.{jpg,jpe,jpeg,png,bmp,gif,ico,webp,avif}",
"default": "**/*.{jpg,jpe,jpeg,png,bmp,gif,ico,webp,avif,tiff,svg,mp4}",
"description": "%configuration.markdown.experimental.updateLinksOnFileMove.fileGlobs%",
"scope": "resource",
"tags": [
"experimental"
]
},
"markdown.experimental.updateLinksOnFileMove.enableForDirectories": {
"type": "boolean",
"default": true,
"description": "%configuration.markdown.experimental.updateLinksOnFileMove.enableForDirectories%",
"scope": "resource",
"tags": [
"experimental"
]
}
}
},

View file

@ -42,5 +42,6 @@
"configuration.markdown.experimental.updateLinksOnFileMove.enabled.always": "Always update links automatically.",
"configuration.markdown.experimental.updateLinksOnFileMove.enabled.never": "Never try to update link and don't prompt.",
"configuration.markdown.experimental.updateLinksOnFileMove.fileGlobs": "A glob that specifies which files besides markdown should trigger a link update.",
"configuration.markdown.experimental.updateLinksOnFileMove.enableForDirectories": "enable/disable updating links when a directory is moved or renamed in the workspace.",
"workspaceTrust": "Required for loading styles configured in the workspace."
}

View file

@ -13,7 +13,7 @@
"vscode-languageserver": "^8.0.2",
"vscode-languageserver-textdocument": "^1.0.5",
"vscode-languageserver-types": "^3.17.1",
"vscode-markdown-languageservice": "^0.0.0-alpha.14",
"vscode-markdown-languageservice": "^0.0.0-alpha.15",
"vscode-uri": "^3.0.3"
},
"devDependencies": {

View file

@ -3,17 +3,25 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export interface LsConfiguration {
/**
* List of file extensions should be considered as markdown.
*
* These should not include the leading `.`.
*/
readonly markdownFileExtensions: readonly string[];
}
import { LsConfiguration } from 'vscode-markdown-languageservice/out/config';
export { LsConfiguration };
const defaultConfig: LsConfiguration = {
markdownFileExtensions: ['md'],
knownLinkedToFileExtensions: [
'jpg',
'jpeg',
'png',
'gif',
'webp',
'bmp',
'tiff',
],
excludePaths: [
'**/.*',
'**/node_modules/**',
]
};
export function getLsConfiguration(overrides: Partial<LsConfiguration>): LsConfiguration {

View file

@ -7,22 +7,24 @@ 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 { IDisposable } from 'vscode-markdown-languageservice/out/util/dispose';
import { URI } from 'vscode-uri';
import { getLsConfiguration } from './config';
import { getLsConfiguration, LsConfiguration } from './config';
import { ConfigurationManager } from './configuration';
import { registerValidateSupport } from './languageFeatures/diagnostics';
import { LogFunctionLogger } from './logging';
import * as protocol from './protocol';
import { IDisposable } from './util/dispose';
import { VsCodeClientWorkspace } from './workspace';
interface MdServerInitializationOptions extends LsConfiguration { }
export async function startServer(connection: Connection) {
const documents = new TextDocuments(TextDocument);
const notebooks = new NotebookDocuments(documents);
const configurationManager = new ConfigurationManager(connection);
let provider: md.IMdLanguageService | undefined;
let mdLs: md.IMdLanguageService | undefined;
let workspace: VsCodeClientWorkspace | undefined;
connection.onInitialize((params: InitializeParams): InitializeResult => {
@ -34,21 +36,21 @@ export async function startServer(connection: Connection) {
}
};
const config = getLsConfiguration({
markdownFileExtensions: params.initializationOptions.markdownFileExtensions,
});
const initOptions = params.initializationOptions as MdServerInitializationOptions | undefined;
const config = getLsConfiguration(initOptions ?? {});
const logger = new LogFunctionLogger(connection.console.log.bind(connection.console));
workspace = new VsCodeClientWorkspace(connection, config, documents, notebooks, logger);
provider = md.createLanguageService({
mdLs = md.createLanguageService({
workspace,
parser,
logger,
markdownFileExtensions: config.markdownFileExtensions,
excludePaths: config.excludePaths,
});
registerCompletionsSupport(connection, documents, provider, configurationManager);
registerValidateSupport(connection, workspace, provider, configurationManager, logger);
registerCompletionsSupport(connection, documents, mdLs, configurationManager);
registerValidateSupport(connection, workspace, mdLs, configurationManager, logger);
workspace.workspaceFolders = (params.workspaceFolders ?? []).map(x => URI.parse(x.uri));
return {
@ -77,139 +79,84 @@ export async function startServer(connection: Connection) {
};
});
connection.onDocumentLinks(async (params, token): Promise<lsp.DocumentLink[]> => {
try {
const document = documents.get(params.textDocument.uri);
if (document) {
return await provider!.getDocumentLinks(document, token);
}
} catch (e) {
console.error(e.stack);
const document = documents.get(params.textDocument.uri);
if (!document) {
return [];
}
return [];
return mdLs!.getDocumentLinks(document, token);
});
connection.onDocumentLinkResolve(async (link, token): Promise<lsp.DocumentLink | undefined> => {
try {
return await provider!.resolveDocumentLink(link, token);
} catch (e) {
console.error(e.stack);
}
return undefined;
return mdLs!.resolveDocumentLink(link, token);
});
connection.onDocumentSymbol(async (params, token): Promise<lsp.DocumentSymbol[]> => {
try {
const document = documents.get(params.textDocument.uri);
if (document) {
return await provider!.getDocumentSymbols(document, token);
}
} catch (e) {
console.error(e.stack);
const document = documents.get(params.textDocument.uri);
if (!document) {
return [];
}
return [];
return mdLs!.getDocumentSymbols(document, token);
});
connection.onFoldingRanges(async (params, token): Promise<lsp.FoldingRange[]> => {
try {
const document = documents.get(params.textDocument.uri);
if (document) {
return await provider!.getFoldingRanges(document, token);
}
} catch (e) {
console.error(e.stack);
const document = documents.get(params.textDocument.uri);
if (!document) {
return [];
}
return [];
return mdLs!.getFoldingRanges(document, token);
});
connection.onSelectionRanges(async (params, token): Promise<lsp.SelectionRange[] | undefined> => {
try {
const document = documents.get(params.textDocument.uri);
if (document) {
return await provider!.getSelectionRanges(document, params.positions, token);
}
} catch (e) {
console.error(e.stack);
const document = documents.get(params.textDocument.uri);
if (!document) {
return [];
}
return [];
return mdLs!.getSelectionRanges(document, params.positions, token);
});
connection.onWorkspaceSymbol(async (params, token): Promise<lsp.WorkspaceSymbol[]> => {
try {
return await provider!.getWorkspaceSymbols(params.query, token);
} catch (e) {
console.error(e.stack);
}
return [];
return mdLs!.getWorkspaceSymbols(params.query, token);
});
connection.onReferences(async (params, token): Promise<lsp.Location[]> => {
try {
const document = documents.get(params.textDocument.uri);
if (document) {
return await provider!.getReferences(document, params.position, params.context, token);
}
} catch (e) {
console.error(e.stack);
const document = documents.get(params.textDocument.uri);
if (!document) {
return [];
}
return [];
return mdLs!.getReferences(document, params.position, params.context, token);
});
connection.onDefinition(async (params, token): Promise<lsp.Definition | undefined> => {
try {
const document = documents.get(params.textDocument.uri);
if (document) {
return await provider!.getDefinition(document, params.position, token);
}
} catch (e) {
console.error(e.stack);
const document = documents.get(params.textDocument.uri);
if (!document) {
return undefined;
}
return undefined;
return mdLs!.getDefinition(document, params.position, token);
});
connection.onPrepareRename(async (params, token) => {
try {
const document = documents.get(params.textDocument.uri);
if (document) {
return await provider!.prepareRename(document, params.position, token);
}
} catch (e) {
console.error(e.stack);
const document = documents.get(params.textDocument.uri);
if (!document) {
return undefined;
}
return undefined;
return mdLs!.prepareRename(document, params.position, token);
});
connection.onRenameRequest(async (params, token) => {
try {
const document = documents.get(params.textDocument.uri);
if (document) {
const edit = await provider!.getRenameEdit(document, params.position, params.newName, token);
console.log(JSON.stringify(edit));
return edit;
}
} catch (e) {
console.error(e.stack);
const document = documents.get(params.textDocument.uri);
if (!document) {
return undefined;
}
return undefined;
return mdLs!.getRenameEdit(document, params.position, params.newName, token);
});
connection.onRequest(protocol.getReferencesToFileInWorkspace, (async (params: { uri: string }, token: CancellationToken) => {
try {
return await provider!.getFileReferences(URI.parse(params.uri), token);
} catch (e) {
console.error(e.stack);
}
return undefined;
return mdLs!.getFileReferences(URI.parse(params.uri), token);
}));
connection.onRequest(protocol.getEditForFileRenames, (async (params, token: CancellationToken) => {
try {
return await provider!.getRenameFilesInWorkspaceEdit(params.map(x => ({ oldUri: URI.parse(x.oldUri), newUri: URI.parse(x.newUri) })), token);
} catch (e) {
console.error(e.stack);
}
return undefined;
return mdLs!.getRenameFilesInWorkspaceEdit(params.map(x => ({ oldUri: URI.parse(x.oldUri), newUri: URI.parse(x.newUri) })), token);
}));
documents.listen(connection);

View file

@ -42,10 +42,10 @@ vscode-languageserver@^8.0.2:
dependencies:
vscode-languageserver-protocol "3.17.2"
vscode-markdown-languageservice@^0.0.0-alpha.14:
version "0.0.0-alpha.14"
resolved "https://registry.yarnpkg.com/vscode-markdown-languageservice/-/vscode-markdown-languageservice-0.0.0-alpha.14.tgz#befe2fd1571213db0abbd9c93a4b9adf22f68d5c"
integrity sha512-6rxEZKnYTJfZBOIWfPeUm5cjss7hgnJ7lQ8ZA4b918SjcOlDT0NOCQZ/88vMuxWdKKQCywcD9YoXNMRYsT+N5w==
vscode-markdown-languageservice@^0.0.0-alpha.15:
version "0.0.0-alpha.15"
resolved "https://registry.yarnpkg.com/vscode-markdown-languageservice/-/vscode-markdown-languageservice-0.0.0-alpha.15.tgz#f11b18eb2ced8b13d90abc50825d99ce825d88b8"
integrity sha512-OLMd6LlDf3v4/ULU354gwsEcNyuUjEGDFQIYwi78gFXd89K2eWG4KewDR9fl3ip00lOcHcvQWqFBRgkfr72DRg==
dependencies:
picomatch "^2.3.1"
vscode-languageserver-textdocument "^1.0.5"
@ -54,9 +54,9 @@ vscode-markdown-languageservice@^0.0.0-alpha.14:
vscode-uri "^3.0.3"
vscode-nls@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.0.1.tgz#ba23fc4d4420d25e7f886c8e83cbdcec47aa48b2"
integrity sha512-hHQV6iig+M21lTdItKPkJAaWrxALQb/nqpVffakO4knJOh3DrU2SXOMzUzNgo1eADPzu3qSsJY1weCzvR52q9A==
version "5.1.0"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.1.0.tgz#443b301a7465d88c81c0f4e1914f9857f0dce1e4"
integrity sha512-37Ha44QrLFwR2IfSSYdOArzUvOyoWbOYTwQC+wS0NfqKjhW7s0WQ1lMy5oJXgSZy9sAiZS5ifELhbpXodeMR8w==
vscode-uri@^3.0.3:
version "3.0.3"

View file

@ -11,7 +11,7 @@ import { registerPasteSupport } from './languageFeatures/copyPaste';
import { registerDiagnosticSupport } from './languageFeatures/diagnostics';
import { registerDropIntoEditorSupport } from './languageFeatures/dropIntoEditor';
import { registerFindFileReferenceSupport } from './languageFeatures/fileReferences';
import { registerUpdatePathsOnRename } from './languageFeatures/updatePathsOnRename';
import { registerUpdateLinksOnRename } from './languageFeatures/updatePathsOnRename';
import { ILogger } from './logging';
import { MarkdownItEngine, MdParsingProvider } from './markdownEngine';
import { MarkdownContributionProvider } from './markdownExtensions';
@ -63,7 +63,7 @@ function registerMarkdownLanguageFeatures(
registerDropIntoEditorSupport(selector),
registerFindFileReferenceSupport(commandManager, client),
registerPasteSupport(selector),
registerUpdatePathsOnRename(client),
registerUpdateLinksOnRename(client),
);
}

View file

@ -19,7 +19,8 @@ const localize = nls.loadMessageBundle();
const settingNames = Object.freeze({
enabled: 'experimental.updateLinksOnFileMove.enabled',
externalFileGlobs: 'experimental.updateLinksOnFileMove.externalFileGlobs'
externalFileGlobs: 'experimental.updateLinksOnFileMove.externalFileGlobs',
enableForDirectories: 'experimental.updateLinksOnFileMove.enableForDirectories',
});
const enum UpdateLinksOnFileMoveSetting {
@ -33,7 +34,7 @@ interface RenameAction {
readonly newUri: vscode.Uri;
}
class UpdateImportsOnFileRenameHandler extends Disposable {
class UpdateLinksOnFileRenameHandler extends Disposable {
private readonly _delayer = new Delayer(50);
private readonly _pendingRenames = new Set<RenameAction>();
@ -44,27 +45,23 @@ class UpdateImportsOnFileRenameHandler extends Disposable {
super();
this._register(vscode.workspace.onDidRenameFiles(async (e) => {
const [{ newUri, oldUri }] = e.files; // TODO: only handles first file
for (const { newUri, oldUri } of e.files) {
const config = this.getConfiguration(newUri);
if (!await this.shouldParticipateInLinkUpdate(config, newUri)) {
continue;
}
const config = this.getConfiguration(newUri);
const setting = config.get<UpdateLinksOnFileMoveSetting>(settingNames.enabled);
if (setting === UpdateLinksOnFileMoveSetting.Never) {
return;
this._pendingRenames.add({ newUri, oldUri });
}
if (!this.shouldParticipateInLinkUpdate(config, newUri)) {
return;
if (this._pendingRenames.size) {
this._delayer.trigger(() => {
vscode.window.withProgress({
location: vscode.ProgressLocation.Window,
title: localize('renameProgress.title', "Checking for Markdown links to update")
}, () => this.flushRenames());
});
}
this._pendingRenames.add({ oldUri, newUri });
this._delayer.trigger(() => {
vscode.window.withProgress({
location: vscode.ProgressLocation.Window,
title: localize('renameProgress.title', "Checking for Markdown links to update")
}, () => this.flushRenames());
});
}));
}
@ -110,13 +107,27 @@ class UpdateImportsOnFileRenameHandler extends Disposable {
return vscode.workspace.getConfiguration('markdown', resource);
}
private shouldParticipateInLinkUpdate(config: vscode.WorkspaceConfiguration, newUri: vscode.Uri) {
private async shouldParticipateInLinkUpdate(config: vscode.WorkspaceConfiguration, newUri: vscode.Uri): Promise<boolean> {
const setting = config.get<UpdateLinksOnFileMoveSetting>(settingNames.enabled);
if (setting === UpdateLinksOnFileMoveSetting.Never) {
return false;
}
if (looksLikeMarkdownPath(newUri)) {
return true;
}
const externalGlob = config.get<string>(settingNames.externalFileGlobs);
return !!externalGlob && picomatch.isMatch(newUri.fsPath, externalGlob);
if (!!externalGlob && picomatch.isMatch(newUri.fsPath, externalGlob)) {
return true;
}
const stat = await vscode.workspace.fs.stat(newUri);
if (stat.type === vscode.FileType.Directory) {
return config.get<boolean>(settingNames.enableForDirectories, true);
}
return false;
}
private async promptUser(newResources: readonly vscode.Uri[]): Promise<boolean> {
@ -229,6 +240,6 @@ class UpdateImportsOnFileRenameHandler extends Disposable {
}
}
export function registerUpdatePathsOnRename(client: BaseLanguageClient) {
return new UpdateImportsOnFileRenameHandler(client);
export function registerUpdateLinksOnRename(client: BaseLanguageClient) {
return new UpdateLinksOnFileRenameHandler(client);
}