diff --git a/src/extension.ts b/src/extension.ts index 207e2199..3ef51ada 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -11,7 +11,7 @@ */ import { prepareExecutable } from './javaServerStarter'; -import { LanguageClientOptions, RevealOutputChannelOn, LanguageClient, DidChangeConfigurationNotification, RequestType, TextDocumentPositionParams, ReferencesRequest, NotificationType, MessageType } from 'vscode-languageclient'; +import { LanguageClientOptions, RevealOutputChannelOn, LanguageClient, DidChangeConfigurationNotification, RequestType, TextDocumentPositionParams, ReferencesRequest, NotificationType, MessageType, ShowMessageNotification } from 'vscode-languageclient'; import * as requirements from './requirements'; import { languages, IndentAction, workspace, window, commands, ExtensionContext, TextDocument, Position, LanguageConfiguration, Uri, extensions, Command } from "vscode"; import * as path from 'path'; @@ -249,6 +249,13 @@ export function activate(context: ExtensionContext) { })); } + // When the current document changes, update ${fileDirname} and ${fileBasenameNoExtension} + // for the file associations, and send the updated settings to the server + context.subscriptions.push(window.onDidChangeActiveTextEditor(() => { + languageClient.sendNotification(DidChangeConfigurationNotification.type, { settings: getXMLSettings(requirements.java_home) }); + onConfigurationChange(); + })); + const api: XMLExtensionApi = { // add API set catalogs to internal memory addXMLCatalogs: (catalogs: string[]) => { @@ -349,11 +356,50 @@ export function activate(context: ExtensionContext) { xml['xml']['catalogs'].push(catalog); } }) - externalXmlSettings.xmlFileAssociations.forEach(element => { - if (!xml['xml']['fileAssociations'].some(fileAssociation => fileAssociation.systemId === element.systemId)) { - xml['xml']['fileAssociations'].push(element); + const variableSubstitutedAssociations: XMLFileAssociation[] = + xml['xml']['fileAssociations'].map((association: XMLFileAssociation): XMLFileAssociation => { + + const currentFile: string = window.activeTextEditor.document.uri.fsPath; + const currentWorkspace: string = workspace.getWorkspaceFolder(window.activeTextEditor.document.uri).uri.fsPath + ?? workspace.workspaceFolders[0].uri.fsPath; + + if (!currentWorkspace + && (association.pattern.indexOf('&{workspaceFolder}') >= 0 + || association.systemId.indexOf('&{workspaceFolder}') >= 0)) { + return; + } + + if (!currentFile + && (association.pattern.indexOf('&{fileDirname}') >= 0 + || association.systemId.indexOf('&{fileDirname}') >= 0 + || association.pattern.indexOf('&{fileBasenameNoExtension}') >= 0 + || association.systemId.indexOf('&{fileBasenameNoExtension}') >= 0)) { + return; + } + + /** + * Returns the string with the values for: + * * ${workspaceFolder} + * * ${fileDirname} + * * ${fileBasenameNoExtension} + * substituted into the string + * + * @param val the value to substitute the variables into + * @return the string with values for the variables subtituted into the string + */ + const subVars = (val: string): string => { + let newVal: string = val.replace(/\$\{workspaceFolder\}/g, currentWorkspace); + newVal = newVal.replace(/\$\{fileDirname\}/g, path.dirname(currentFile)); + newVal = newVal.replace(/\$\{fileBasenameNoExtension\}/g, path.basename(currentFile, path.extname(currentFile))); + return newVal; } + + return { + pattern: subVars(association.pattern), + systemId: subVars(association.systemId) + }; }); + xml['xml']['fileAssociations'] = [...variableSubstitutedAssociations]; return xml; }