|
10 | 10 | * Microsoft Corporation - Auto Closing Tags |
11 | 11 | */ |
12 | 12 |
|
13 | | -import { prepareExecutable } from './javaServerStarter'; |
14 | | -import { |
15 | | - LanguageClientOptions, |
16 | | - RevealOutputChannelOn, |
17 | | - LanguageClient, |
18 | | - DidChangeConfigurationNotification, |
19 | | - RequestType, |
20 | | - TextDocumentPositionParams, |
21 | | - ReferencesRequest, |
22 | | - NotificationType, |
23 | | - MessageType, |
24 | | - ConfigurationRequest, |
25 | | - ConfigurationParams, |
26 | | - ExecuteCommandParams, |
27 | | - CancellationToken, |
28 | | - ExecuteCommandRequest |
29 | | -} from 'vscode-languageclient'; |
30 | | -import * as requirements from './requirements'; |
31 | | -import { languages, IndentAction, workspace, window, commands, ExtensionContext, TextDocument, Position, LanguageConfiguration, Uri, extensions, Command, TextEditor } from "vscode"; |
32 | | -import * as path from 'path'; |
33 | 13 | import * as os from 'os'; |
34 | | -import { activateTagClosing, AutoCloseResult } from './tagClosing'; |
| 14 | +import * as path from 'path'; |
| 15 | +import { Command, commands, ExtensionContext, extensions, IndentAction, LanguageConfiguration, languages, Position, TextDocument, TextEditor, Uri, window, workspace, WorkspaceFolder } from "vscode"; |
| 16 | +import { CancellationToken, ConfigurationParams, ConfigurationRequest, DidChangeConfigurationNotification, ExecuteCommandParams, ExecuteCommandRequest, LanguageClient, LanguageClientOptions, MessageType, NotificationType, ReferencesRequest, RequestType, RevealOutputChannelOn, TextDocumentPositionParams } from 'vscode-languageclient'; |
35 | 17 | import { Commands } from './commands'; |
36 | | -import { getXMLConfiguration, onConfigurationChange, subscribeJDKChangeConfiguration } from './settings'; |
37 | | -import { collectXmlJavaExtensions, onExtensionChange } from './plugin'; |
| 18 | +import { prepareExecutable } from './javaServerStarter'; |
38 | 19 | import { markdownPreviewProvider } from "./markdownPreviewProvider"; |
| 20 | +import { collectXmlJavaExtensions, onExtensionChange } from './plugin'; |
| 21 | +import * as requirements from './requirements'; |
| 22 | +import { getXMLConfiguration, onConfigurationChange, subscribeJDKChangeConfiguration } from './settings'; |
| 23 | +import { activateTagClosing, AutoCloseResult } from './tagClosing'; |
39 | 24 |
|
40 | 25 | export interface ScopeInfo { |
41 | 26 | scope: "default" | "global" | "workspace" | "folder"; |
@@ -163,9 +148,9 @@ export function activate(context: ExtensionContext) { |
163 | 148 | const sectionId = ''; |
164 | 149 | markdownPreviewProvider.show(context.asAbsolutePath(path.join('docs', uri)), title, sectionId, context); |
165 | 150 | })); |
166 | | - context.subscriptions.push(commands.registerCommand(Commands.OPEN_DOCS, async (params: {page: string, section: string}) => { |
| 151 | + context.subscriptions.push(commands.registerCommand(Commands.OPEN_DOCS, async (params: { page: string, section: string }) => { |
167 | 152 | const page = params.page.endsWith('.md') ? params.page.substr(0, params.page.length - 3) : params.page; |
168 | | - const uri = page + '.md'; |
| 153 | + const uri = page + '.md'; |
169 | 154 | const sectionId = params.section || ''; |
170 | 155 | const title = 'XML ' + page; |
171 | 156 | markdownPreviewProvider.show(context.asAbsolutePath(path.join('docs', uri)), title, sectionId, context); |
@@ -262,25 +247,25 @@ export function activate(context: ExtensionContext) { |
262 | 247 | // Handler for 'xml/executeClientCommand` request message that executes a command on the client |
263 | 248 | languageClient.onRequest(ExecuteClientCommandRequest.type, async (params: ExecuteCommandParams) => { |
264 | 249 | return await commands.executeCommand(params.command, ...params.arguments); |
265 | | - }); |
| 250 | + }); |
266 | 251 |
|
267 | 252 | // Register client command to execute custom XML Language Server command |
268 | 253 | context.subscriptions.push(commands.registerCommand(Commands.EXECUTE_WORKSPACE_COMMAND, (command, ...rest) => { |
269 | | - let token: CancellationToken; |
270 | | - let commandArgs: any[] = rest; |
271 | | - if (rest && rest.length && CancellationToken.is(rest[rest.length - 1])) { |
272 | | - token = rest[rest.length - 1]; |
273 | | - commandArgs = rest.slice(0, rest.length - 1); |
274 | | - } |
275 | | - const params: ExecuteCommandParams = { |
276 | | - command, |
277 | | - arguments: commandArgs |
278 | | - }; |
279 | | - if (token) { |
280 | | - return languageClient.sendRequest(ExecuteCommandRequest.type, params, token); |
281 | | - } else { |
282 | | - return languageClient.sendRequest(ExecuteCommandRequest.type, params); |
283 | | - } |
| 254 | + let token: CancellationToken; |
| 255 | + let commandArgs: any[] = rest; |
| 256 | + if (rest && rest.length && CancellationToken.is(rest[rest.length - 1])) { |
| 257 | + token = rest[rest.length - 1]; |
| 258 | + commandArgs = rest.slice(0, rest.length - 1); |
| 259 | + } |
| 260 | + const params: ExecuteCommandParams = { |
| 261 | + command, |
| 262 | + arguments: commandArgs |
| 263 | + }; |
| 264 | + if (token) { |
| 265 | + return languageClient.sendRequest(ExecuteCommandRequest.type, params, token); |
| 266 | + } else { |
| 267 | + return languageClient.sendRequest(ExecuteCommandRequest.type, params); |
| 268 | + } |
284 | 269 | })); |
285 | 270 |
|
286 | 271 | context.subscriptions.push(commands.registerCommand(Commands.OPEN_SETTINGS, async (settingId?: string) => { |
@@ -319,6 +304,15 @@ export function activate(context: ExtensionContext) { |
319 | 304 | } |
320 | 305 | return result; |
321 | 306 | }); |
| 307 | + // When the current document changes, update ${fileDirname} and ${fileBasenameNoExtension} |
| 308 | + // for the file associations, (but only if these variables are referenced), |
| 309 | + // and send the updated settings to the server |
| 310 | + context.subscriptions.push(window.onDidChangeActiveTextEditor(() => { |
| 311 | + if (fileAssocReferencesCurrentFile()) { |
| 312 | + languageClient.sendNotification(DidChangeConfigurationNotification.type, { settings: getXMLSettings(requirements.java_home) }); |
| 313 | + onConfigurationChange(); |
| 314 | + } |
| 315 | + })); |
322 | 316 |
|
323 | 317 | const api: XMLExtensionApi = { |
324 | 318 | // add API set catalogs to internal memory |
@@ -420,14 +414,70 @@ export function activate(context: ExtensionContext) { |
420 | 414 | xml['xml']['catalogs'].push(catalog); |
421 | 415 | } |
422 | 416 | }) |
423 | | - externalXmlSettings.xmlFileAssociations.forEach(element => { |
424 | | - if (!xml['xml']['fileAssociations'].some(fileAssociation => fileAssociation.systemId === element.systemId)) { |
425 | | - xml['xml']['fileAssociations'].push(element); |
426 | | - } |
427 | | - }); |
| 417 | + const variableSubstitutedAssociations: XMLFileAssociation[] = |
| 418 | + xml['xml']['fileAssociations'].map((association: XMLFileAssociation): XMLFileAssociation => { |
| 419 | + |
| 420 | + const currentFile: TextDocument = window.activeTextEditor.document; |
| 421 | + const currentFileUri: string = currentFile && currentFile.uri.fsPath; |
| 422 | + const currentWorkspace: WorkspaceFolder = workspace.getWorkspaceFolder(currentFile && currentFile.uri); |
| 423 | + const currentWorkspaceUri: string = (currentWorkspace && currentWorkspace.uri.fsPath) |
| 424 | + || (workspace.workspaceFolders && workspace.workspaceFolders[0].uri.fsPath); |
| 425 | + |
| 426 | + if (!currentWorkspaceUri |
| 427 | + && (association.pattern.indexOf('&{workspaceFolder}') >= 0 |
| 428 | + || association.systemId.indexOf('&{workspaceFolder}') >= 0)) { |
| 429 | + return; |
| 430 | + } |
| 431 | + |
| 432 | + if (!currentFileUri |
| 433 | + && (association.pattern.indexOf('&{fileDirname}') >= 0 |
| 434 | + || association.systemId.indexOf('&{fileDirname}') >= 0 |
| 435 | + || association.pattern.indexOf('&{fileBasenameNoExtension}') >= 0 |
| 436 | + || association.systemId.indexOf('&{fileBasenameNoExtension}') >= 0)) { |
| 437 | + return; |
| 438 | + } |
| 439 | + |
| 440 | + /** |
| 441 | + * Returns the string with the values for: |
| 442 | + * * ${workspaceFolder} |
| 443 | + * * ${fileDirname} |
| 444 | + * * ${fileBasenameNoExtension} |
| 445 | + * substituted into the string |
| 446 | + * |
| 447 | + * @param val the value to substitute the variables into |
| 448 | + * @return the string with values for the variables substituted into the string |
| 449 | + */ |
| 450 | + const subVars = (val: string): string => { |
| 451 | + let newVal: string = val.replace(/\$\{workspaceFolder\}/g, currentWorkspaceUri); |
| 452 | + newVal = newVal.replace(/\$\{fileDirname\}/g, path.dirname(currentFileUri)); |
| 453 | + newVal = newVal.replace(/\$\{fileBasenameNoExtension\}/g, path.basename(currentFileUri, path.extname(currentFileUri))); |
| 454 | + return newVal; |
| 455 | + } |
| 456 | + |
| 457 | + return { |
| 458 | + pattern: subVars(association.pattern), |
| 459 | + systemId: subVars(association.systemId) |
| 460 | + }; |
| 461 | + }); |
| 462 | + xml['xml']['fileAssociations'] = [...variableSubstitutedAssociations]; |
428 | 463 |
|
429 | 464 | return xml; |
430 | 465 | } |
| 466 | + |
| 467 | + /** |
| 468 | + * Returns true if the the XML settings contain a file association with a variable reference to either ${fileDirname} or ${fileBasenameNoExtension} and false otherwise |
| 469 | + * |
| 470 | + * @return true if the the XML settings contain a file association with a variable reference to either ${fileDirname} or ${fileBasenameNoExtension} and false otherwise |
| 471 | + */ |
| 472 | + function fileAssocReferencesCurrentFile(): boolean { |
| 473 | + for (const assoc of getXMLConfiguration().get('fileAssociations') as XMLFileAssociation[]) { |
| 474 | + if (assoc.pattern.indexOf('${fileDirname}') >= 0 || assoc.pattern.indexOf('${fileBasenameNoExtension}') >= 0 |
| 475 | + || assoc.systemId.indexOf('${fileDirname}') >= 0 || assoc.systemId.indexOf('${fileBasenameNoExtension}') >= 0) { |
| 476 | + return true; |
| 477 | + } |
| 478 | + } |
| 479 | + return false; |
| 480 | + } |
431 | 481 | } |
432 | 482 |
|
433 | 483 | export function deactivate(): void { |
|
0 commit comments