diff --git a/src/client/xmlClient.ts b/src/client/xmlClient.ts index 0ed6c447..a7365bb5 100644 --- a/src/client/xmlClient.ts +++ b/src/client/xmlClient.ts @@ -123,7 +123,8 @@ function getLanguageClientOptions(logfile: string, externalXmlSettings: External codeLens: { codeLensKind: { valueSet: [ - 'references' + 'references', + 'association' ] } }, diff --git a/src/commands/commandConstants.ts b/src/commands/commandConstants.ts index 13d1a130..dd396109 100644 --- a/src/commands/commandConstants.ts +++ b/src/commands/commandConstants.ts @@ -52,11 +52,18 @@ export namespace CommandConstants { export const OPEN_DOCS_HOME = "xml.open.docs.home"; /** - * VSCode client command to executes an LSP command on the XML Language Server + * VSCode client commands to revalidate files with an LSP command on the XML Language Server */ export const EXECUTE_WORKSPACE_COMMAND = "xml.workspace.executeCommand"; export const VALIDATE_CURRENT_FILE = "xml.validation.current.file"; export const VALIDATE_ALL_FILES = "xml.validation.all.files"; + + /** + * VSCode client commands to associate a XML file with a grammar to select + */ + export const ASSOCIATE_GRAMMAR_SELECT_FILE = "xml.associate.grammar.selectFile"; + + export const ASSOCIATE_GRAMMAR_INSERT = "xml.associate.grammar.insert"; } diff --git a/src/commands/registerCommands.ts b/src/commands/registerCommands.ts index 7c38901a..64ba793c 100644 --- a/src/commands/registerCommands.ts +++ b/src/commands/registerCommands.ts @@ -1,6 +1,6 @@ import * as path from 'path'; -import { commands, ExtensionContext, Position, Uri, window, workspace } from "vscode"; -import { CancellationToken, ExecuteCommandParams, ExecuteCommandRequest, ReferencesRequest, TextDocumentIdentifier } from "vscode-languageclient"; +import { commands, ExtensionContext, OpenDialogOptions, Position, Uri, window, workspace, WorkspaceEdit } from "vscode"; +import { CancellationToken, ExecuteCommandParams, ExecuteCommandRequest, ReferencesRequest, TextDocumentIdentifier, TextDocumentEdit } from "vscode-languageclient"; import { LanguageClient } from 'vscode-languageclient/node'; import { markdownPreviewProvider } from "../markdownPreviewProvider"; import { CommandConstants } from "./commandConstants"; @@ -15,6 +15,7 @@ export async function registerCommands(context: ExtensionContext, languageClient registerDocsCommands(context); registerCodeLensCommands(context, languageClient); registerValidationCommands(context); + registerAssociateGrammarCommands(context, languageClient); // Register client command to execute custom XML Language Server command context.subscriptions.push(commands.registerCommand(CommandConstants.EXECUTE_WORKSPACE_COMMAND, (command, ...rest) => { @@ -108,4 +109,82 @@ async function registerValidationCommands(context: ExtensionContext): Promise { + context.subscriptions.push(commands.registerCommand(CommandConstants.ASSOCIATE_GRAMMAR_SELECT_FILE, (uriString: string, bindingType: string) => { + + // A click on Bind with... has been processed in the XMLdocument which is not bound to a grammar + const documentURI = Uri.parse(uriString); + workspace.openTextDocument(documentURI).then(document => { + + // Open a dialog to select the XSD,DTD to bind. + const options = createDialogOptions(bindingType); + window.showOpenDialog(options).then(fileUri => { + if (fileUri && fileUri[0]) { + + // The XSD, DTD has been selected, get the proper syntax for binding this grammar file in the XML document. + const identifier = TextDocumentIdentifier.create(documentURI.toString()); + const grammarURI = fileUri[0]; + commands.executeCommand(CommandConstants.EXECUTE_WORKSPACE_COMMAND, CommandConstants.ASSOCIATE_GRAMMAR_INSERT, identifier, grammarURI.toString(), bindingType). + then((result) => { + // Insert the proper syntax for binding + const lspTextDocumentEdit = result; + const workEdits = new WorkspaceEdit(); + for (const edit of lspTextDocumentEdit.edits) { + workEdits.replace(documentURI, languageClient.protocol2CodeConverter.asRange(edit.range), edit.newText); + } + workspace.applyEdit(workEdits); // apply the edits + }, error => { + window.showErrorMessage('Error during grammar binding: ' + error.message); + }); + } + }); + + }) + })); + + function createDialogOptions(bindingType : string) : OpenDialogOptions { + switch(bindingType) { + case "xsd": { + const options: OpenDialogOptions = { + canSelectMany: false, + openLabel: 'Select XSD file', + filters: { + 'XSD files': ['xsd'], + } + }; + return options; + } + + case "dtd": { + const options: OpenDialogOptions = { + canSelectMany: false, + openLabel: 'Select DTD file', + filters: { + 'DTD files': ['dtd'] + } + }; + return options; + } + + case "xml-model": { + const options: OpenDialogOptions = { + canSelectMany: false, + openLabel: 'Select XSD or DTD file', + filters: { + 'XSD files': ['xsd'], + 'DTD files': ['dtd'] + } + }; + return options; + } + } + + } } \ No newline at end of file