From 4f002c9e787784d863494181e8b05257363d2eba Mon Sep 17 00:00:00 2001 From: David Thompson Date: Tue, 6 Oct 2020 14:06:14 -0400 Subject: [PATCH] `xml.extension.jars` to add LemMinX extension jars Adds a new setting `xml.extension.jars`, where you can list jars to contribute to the LemMinX classpath. You can use this feature to test LemMinX extensions in VSCode. Closes #251 Signed-off-by: David Thompson --- README.md | 37 +------------------ docs/Extensions.md | 36 ++++++++++++++++++ docs/Preferences.md | 13 +++++++ {images => docs/images}/vscode-xml-maven.gif | Bin package.json | 8 +++- src/extension.ts | 6 +-- src/plugin.ts | 9 +++-- 7 files changed, 67 insertions(+), 42 deletions(-) create mode 100644 docs/Extensions.md rename {images => docs/images}/vscode-xml-maven.gif (100%) diff --git a/README.md b/README.md index e055f80d..f1fb06ca 100644 --- a/README.md +++ b/README.md @@ -93,41 +93,8 @@ Since 0.13.0: ## Custom XML Extensions -The [LemMinX - XML Language Server](https://github.com/eclipse/lemminx) can be extended to support custom completion, hover, validation, rename, etc by using the [Java Service Provider Interface (SPI)](https://www.baeldung.com/java-spi) mechanism. vscode-xml provides the ability use your custom XML support provider, by adding external jars to the XML language server's classpath. - -To do that: - - * create a Java project which provides a custom XML extension providing your custom completion, hover, validation, rename, etc: - * create the XML extension like [MavenPlugin](https://github.com/angelozerr/lsp4xml-extensions-maven/blob/master/org.eclipse.lsp4xml.extensions.maven/src/main/java/org/eclipse/lsp4xml/extensions/maven/MavenPlugin.java). - * register your custom completion participant in the XML extension like [MavenCompletionParticipant](https://github.com/angelozerr/lsp4xml-extensions-maven/blob/master/org.eclipse.lsp4xml.extensions.maven/src/main/java/org/eclipse/lsp4xml/extensions/maven/MavenCompletionParticipant.java#L28) - * register your custom XML extension with [Java Service Provider Interface (SPI)](https://www.baeldung.com/java-spi) mechanism in the [/META-INF/services/org.eclipse.lemminx.services.extensions.IXMLExtension](https://github.com/angelozerr/lsp4xml-extensions-maven/blob/master/org.eclipse.lsp4xml.extensions.maven/src/main/resources/META-INF/services/org.eclipse.lsp4xml.services.extensions.IXMLExtension) file. - * build a JAR `your-custom-xml-extension.jar`. - - * create a `vscode extension` which embeds the `your-custom-xml-extension.jar` JAR and declares this JAR path in the `package.json`: - -```json -"contributes": { - "xml.javaExtensions": [ - "./jar/your-custom-xml-extension.jar" - ] -} -``` - - * You can also list multiple jars or use glob patterns to specify the jars: - -```json -"contributes": { - "xml.javaExtensions": [ - "./jar/dependencies/*.jar", - "./jar/my-xml-extension.jar" - ] -} -``` - - -You can see the [vscode-xml-maven](https://github.com/angelozerr/vscode-xml-maven) sample which registers custom maven completion [MavenCompletionParticipant](https://github.com/angelozerr/lsp4xml-extensions-maven/blob/master/org.eclipse.lsp4xml.extensions.maven/src/main/java/org/eclipse/lsp4xml/extensions/maven/MavenCompletionParticipant.java#L28) for scope: - -![VScode XML Maven](images/vscode-xml-maven.gif) +The [LemMinX - XML Language Server](https://github.com/eclipse/lemminx) can be extended to support custom completion, hover, validation, rename, etc. +Please see the [extensions documentation](./docs/Extensions#custom-xml-extensions) for more information. ## Contributing diff --git a/docs/Extensions.md b/docs/Extensions.md new file mode 100644 index 00000000..b429d9b0 --- /dev/null +++ b/docs/Extensions.md @@ -0,0 +1,36 @@ +# Custom XML Extensions + +The [LemMinX - XML Language Server](https://github.com/eclipse/lemminx) can be extended to support custom completion, hover, validation, rename, etc by using the [Java Service Provider Interface (SPI)](https://www.baeldung.com/java-spi) mechanism. +vscode-xml provides the ability to use your custom XML support provider, by adding external jars to the XML language server's classpath. + +To do that: + + * create a Java project which provides a custom XML extension providing your custom completion, hover, validation, rename, etc: + * create the XML extension like [MavenLemminxExtension](https://github.com/eclipse/lemminx-maven/blob/master/lemminx-maven/src/main/java/org/eclipse/lemminx/extensions/maven/MavenLemminxExtension.java). + * register your custom completion participant in the XML extension like [MavenCompletionParticipant](https://github.com/eclipse/lemminx-maven/blob/master/lemminx-maven/src/main/java/org/eclipse/lemminx/extensions/maven/MavenCompletionParticipant.java#L75) + * register your custom XML extension with [Java Service Provider Interface (SPI)](https://www.baeldung.com/java-spi) mechanism in the [/META-INF/services/org.eclipse.lemminx.services.extensions.IXMLExtension](https://github.com/eclipse/lemminx-maven/blob/master/lemminx-maven/src/main/resources/META-INF/services/org.eclipse.lemminx.services.extensions.IXMLExtension) file. + * build a JAR `your-custom-xml-extension.jar`. + * create a `vscode extension` which embeds the `your-custom-xml-extension.jar` JAR and declares this JAR path in the `package.json`: + +```json +"contributes": { + "xml.javaExtensions": [ + "./jar/your-custom-xml-extension.jar" + ] +} +``` + + * You can also list multiple jars or use glob patterns to specify the jars: + +```json +"contributes": { + "xml.javaExtensions": [ + "./jar/dependencies/*.jar", + "./jar/my-xml-extension.jar" + ] +} +``` + +You can see the [vscode-xml-maven](https://github.com/angelozerr/vscode-xml-maven) sample which registers custom maven completion [MavenCompletionParticipant](https://github.com/eclipse/lemminx-maven/blob/master/lemminx-maven/src/main/java/org/eclipse/lemminx/extensions/maven/MavenCompletionParticipant.java#L210) for scope: + +![demo of vscode xml maven suggesting different scopes for a dependency](./images/vscode-xml-maven.gif) diff --git a/docs/Preferences.md b/docs/Preferences.md index cfb2a0aa..fc699d7a 100644 --- a/docs/Preferences.md +++ b/docs/Preferences.md @@ -161,3 +161,16 @@ The different options are: Here is a demonstration of the effects of the setting on hovering. The above schema is used in the example: ![Changing the documentation type setting changes which text the hover shows when hovering over an element that is in a schema document](./images/Preferences/HoverDocumentationQuickDemo.gif) + +## Extension JARs + +The LemMinX XML Language Server can be extended with custom plugins to provide additional validation and assistance. +Typically this is done for specific files or contexts. +External extensions are are contributed via an external JAR. +Please see [the extension development documentation](https://github.com/eclipse/lemminx/blob/master/docs/LemMinX-Extensions.md) for more information on how this works. + +JARs can be contributed to the LemMinX classpath using the `xml.extension.jars` preference. +These paths can include globs. +This feature is only intended to be used for LemMinX extension development purposes. +Distributing vscode-xml extensions is best done through the mechanism described in the +[vscode-xml extension development documentation](Extensions#custom-xml-extensions). diff --git a/images/vscode-xml-maven.gif b/docs/images/vscode-xml-maven.gif similarity index 100% rename from images/vscode-xml-maven.gif rename to docs/images/vscode-xml-maven.gif diff --git a/package.json b/package.json index 5d63c2b8..0da3f58f 100644 --- a/package.json +++ b/package.json @@ -355,7 +355,13 @@ "xml.symbols.showReferencedGrammars": { "type": "boolean", "default": true, - "markdownDescription": "Show referenced grammars in the Outline. Default is `true.", + "markdownDescription": "Show referenced grammars in the Outline. Default is `true`.", + "scope": "window" + }, + "xml.extension.jars": { + "type": "array", + "default": [], + "markdownDescription": "An array of paths to JARs that should be contributed to the LemMinX classpath. The paths can include glob patterns. This is intended to be used as a tool for developing extensions to vscode-xml. Please see [here](command:xml.open.docs?%5B%7B%22page%22%3A%22Preferences%22%2C%22section%22%3A%22extension-jars%22%7D%5D) for more information", "scope": "window" } } diff --git a/src/extension.ts b/src/extension.ts index 207e2199..8bdef9d1 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -18,7 +18,7 @@ import * as path from 'path'; import * as os from 'os'; import { activateTagClosing, AutoCloseResult } from './tagClosing'; import { Commands } from './commands'; -import { onConfigurationChange, subscribeJDKChangeConfiguration } from './settings'; +import { getXMLConfiguration, onConfigurationChange, subscribeJDKChangeConfiguration } from './settings'; import { collectXmlJavaExtensions, onExtensionChange } from './plugin'; import { markdownPreviewProvider } from "./markdownPreviewProvider"; @@ -203,7 +203,7 @@ export function activate(context: ExtensionContext) { } } - let serverOptions = prepareExecutable(requirements, collectXmlJavaExtensions(extensions.all), context); + let serverOptions = prepareExecutable(requirements, collectXmlJavaExtensions(extensions.all, getXMLConfiguration().get("extension.jars", [])), context); languageClient = new LanguageClient('xml', 'XML Support', serverOptions, clientOptions); let toDispose = context.subscriptions; let disposable = languageClient.start(); @@ -245,7 +245,7 @@ export function activate(context: ExtensionContext) { if (extensions.onDidChange) {// Theia doesn't support this API yet context.subscriptions.push(extensions.onDidChange(() => { - onExtensionChange(extensions.all); + onExtensionChange(extensions.all, getXMLConfiguration().get("extension.jars", [])); })); } diff --git a/src/plugin.ts b/src/plugin.ts index d7bdc7b5..9e9e9f00 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -7,7 +7,7 @@ const glob = require('glob'); let existingExtensions: Array; -export function collectXmlJavaExtensions(extensions: readonly vscode.Extension[]): string[] { +export function collectXmlJavaExtensions(extensions: readonly vscode.Extension[], jars: string[]): string[] { const result = []; if (extensions && extensions.length) { for (const extension of extensions) { @@ -22,17 +22,20 @@ export function collectXmlJavaExtensions(extensions: readonly vscode.Extension[]) { +export function onExtensionChange(extensions: readonly vscode.Extension[], jars: string[]) { if (!existingExtensions) { return; } const oldExtensions = new Set(existingExtensions.slice()); - const newExtensions = collectXmlJavaExtensions(extensions); + const newExtensions = collectXmlJavaExtensions(extensions, jars); let hasChanged = ( oldExtensions.size !== newExtensions.length); if (!hasChanged) { for (const newExtension of newExtensions) {