forked from microsoft/vscode
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Contribute to html language server with a custom language.
Fixes microsoft#146730 Signed-off-by: azerr <[email protected]>
- Loading branch information
1 parent
ea42ebd
commit 4059f6b
Showing
4 changed files
with
199 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
153 changes: 153 additions & 0 deletions
153
extensions/html-language-features/client/src/htmlExtension.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
/*--------------------------------------------------------------------------------------------- | ||
* Copyright (c) Microsoft Corporation. All rights reserved. | ||
* Licensed under the MIT License. See License.txt in the project root for license information. | ||
*--------------------------------------------------------------------------------------------*/ | ||
|
||
import * as vscode from 'vscode'; | ||
import { DocumentFilter, DocumentSelector } from 'vscode-languageclient'; | ||
import { isDeepStrictEqual } from 'util'; | ||
|
||
const RELOAD_WINDOW = 'workbench.action.reloadWindow'; | ||
|
||
let existingExtensions: HtmlLanguageContribution[]; | ||
|
||
/** | ||
* Html language contribution | ||
*/ | ||
export interface HtmlLanguageContribution { | ||
documentSelector: DocumentSelector; | ||
activateAutoInsertion: false; | ||
} | ||
|
||
/** | ||
* Returns all Html language contributions from package.json | ||
* | ||
* @param extensions array of extensions to search contributions from | ||
*/ | ||
export function collectHtmlLanguageContributions(extensions: readonly vscode.Extension<any>[]): HtmlLanguageContribution[] { | ||
const result: HtmlLanguageContribution[] = []; | ||
if (extensions && extensions.length) { | ||
for (const extension of extensions) { | ||
const htmlLanguages = extension.packageJSON?.contributes?.html?.languages; | ||
if (Array.isArray(htmlLanguages)) { | ||
htmlLanguages.forEach(htmlExtensionSection => { | ||
const htmlExtension = createHtmlExtension(htmlExtensionSection); | ||
if (htmlExtension) { | ||
result.push(htmlExtension); | ||
} | ||
}); | ||
} | ||
} | ||
} | ||
// Make a copy of extensions: | ||
existingExtensions = result.slice(); | ||
return result; | ||
} | ||
|
||
export function handleExtensionChange(extensions: readonly vscode.Extension<any>[]): void { | ||
if (!existingExtensions) { | ||
return; | ||
} | ||
const oldExtensions = new Set(existingExtensions.slice()); | ||
const newExtensions = collectHtmlLanguageContributions(extensions); | ||
let hasChanged = (oldExtensions.size !== newExtensions.length); | ||
if (!hasChanged) { | ||
for (const newExtension of newExtensions) { | ||
let found = false; | ||
for (const oldExtension of oldExtensions) { | ||
if (isDeepStrictEqual(oldExtension, newExtension)) { | ||
found = true; | ||
break; | ||
} | ||
} | ||
if (found) { | ||
continue; | ||
} else { | ||
hasChanged = true; | ||
break; | ||
} | ||
} | ||
} | ||
|
||
if (hasChanged) { | ||
const msg = `Extensions to the Html Language Server changed, reloading ${vscode.env.appName} is required for the changes to take effect.`; | ||
const action = 'Reload'; | ||
vscode.window.showWarningMessage(msg, action).then((selection) => { | ||
if (action === selection) { | ||
vscode.commands.executeCommand(RELOAD_WINDOW); | ||
} | ||
}); | ||
} | ||
} | ||
|
||
/** | ||
* Returns the document selector. | ||
* | ||
* The returned document selector contains the html document selectors | ||
* and all document selectors contained in `htmlContributions`. | ||
* | ||
* @param htmlContributions Html language server contributions from other VS Code extensions | ||
*/ | ||
export function getDocumentSelector(htmlContributions: HtmlLanguageContribution[]): DocumentSelector { | ||
let documentSelector: DocumentSelector = [ | ||
'html' | ||
]; | ||
htmlContributions.forEach((contribution: HtmlLanguageContribution) => { | ||
documentSelector = documentSelector.concat(contribution.documentSelector); | ||
}); | ||
return documentSelector; | ||
} | ||
|
||
export function getActivateAutoInsertionSupportedLanguages(htmlContributions: HtmlLanguageContribution[]): { [id: string]: boolean } { | ||
const supportedLanguages: { [id: string]: boolean } = { html: true }; | ||
htmlContributions.forEach((contribution: HtmlLanguageContribution) => { | ||
contribution.documentSelector.forEach(selector => { | ||
if (typeof selector === 'string') { | ||
const language: string = selector; | ||
supportedLanguages[language] = contribution.activateAutoInsertion; | ||
} else { | ||
const language = (<DocumentFilter>selector).language; | ||
if (language) { | ||
supportedLanguages[language] = contribution.activateAutoInsertion; | ||
} | ||
} | ||
}); | ||
}); | ||
return supportedLanguages; | ||
} | ||
|
||
function createHtmlExtension(section: any): HtmlLanguageContribution | undefined { | ||
const documentSelector = createSelector(section); | ||
if (documentSelector.length > 0) { | ||
const activateAutoInsertion = section.activateAutoInsertion === true ? true : false; | ||
return { documentSelector, activateAutoInsertion } as HtmlLanguageContribution; | ||
} | ||
return; | ||
} | ||
|
||
function createSelector(section: any): DocumentSelector { | ||
if (!Array.isArray(section.documentSelector)) { | ||
return []; | ||
} | ||
const documentSelector: DocumentSelector = []; | ||
section.documentSelector.forEach((selector: any) => { | ||
if (typeof selector === 'string') { | ||
documentSelector.push(selector); | ||
} else if (selector) { | ||
const documentFilter: { [key: string]: string } = {}; | ||
if (typeof selector.language === 'string') { | ||
documentFilter.language = selector.language; | ||
} | ||
if (typeof selector.scheme === 'string') { | ||
documentFilter.scheme = selector.scheme; | ||
} | ||
if (typeof selector.pattern === 'string') { | ||
documentFilter.pattern = selector.pattern; | ||
} | ||
if (documentFilter.language || documentFilter.scheme || documentFilter.pattern) { | ||
documentSelector.push(documentFilter as DocumentFilter); | ||
} | ||
} | ||
}); | ||
return documentSelector; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters