diff --git a/extensions/html-language-features/server/src/modes/javascriptSemanticTokens.ts b/extensions/html-language-features/server/src/modes/javascriptSemanticTokens.ts index 7e4deafa262..9a1f394977a 100644 --- a/extensions/html-language-features/server/src/modes/javascriptSemanticTokens.ts +++ b/extensions/html-language-features/server/src/modes/javascriptSemanticTokens.ts @@ -55,37 +55,42 @@ export function getSemanticTokens(jsLanguageService: ts.LanguageService, current return resultTokens; } +enum TokenType { + 'class', + 'enum', + 'interface', + 'namespace', + 'typeParameter', + 'type', + 'parameter', + 'variable', + 'property', + 'constant', + 'function', + 'member', + _sentinel +} + + +enum TokenModifier { + 'declaration', + 'static', + 'async', + _sentinel +} export function getSemanticTokenLegend() { + const tokenTypes = []; + for (let i = 0; i < TokenType._sentinel; i++) { + tokenTypes.push(TokenType[i]); + } + const tokenModifiers = []; + for (let i = 0; i < TokenModifier._sentinel; i++) { + tokenModifiers.push(TokenModifier[i]); + } return { types: tokenTypes, modifiers: tokenModifiers }; } - -const tokenTypes: string[] = ['class', 'enum', 'interface', 'namespace', 'typeParameter', 'type', 'parameter', 'variable', 'property', 'constant', 'function', 'member']; -const tokenModifiers: string[] = ['declaration', 'static', 'async']; - -const enum TokenType { - 'class' = 0, - 'enum' = 1, - 'interface' = 2, - 'namespace' = 3, - 'typeParameter' = 4, - 'type' = 5, - 'parameter' = 6, - 'variable' = 7, - 'property' = 8, - 'constant' = 9, - 'function' = 10, - 'member' = 11 -} - - -const enum TokenModifier { - 'declaration' = 0x01, - 'static' = 0x02, - 'async' = 0x04, -} - const tokenFromDeclarationMapping: { [name: string]: TokenType } = { [ts.SyntaxKind.VariableDeclaration]: TokenType.variable, [ts.SyntaxKind.Parameter]: TokenType.parameter, diff --git a/extensions/typescript-language-features/package.json b/extensions/typescript-language-features/package.json index 577a4fd1686..ce453e58d9a 100644 --- a/extensions/typescript-language-features/package.json +++ b/extensions/typescript-language-features/package.json @@ -20,7 +20,8 @@ "rimraf": "^2.6.3", "semver": "5.5.1", "vscode-extension-telemetry": "0.1.1", - "vscode-nls": "^4.0.0" + "vscode-nls": "^4.0.0", + "typescript-vscode-sh-plugin":"^0.1.0" }, "devDependencies": { "@types/node": "^12.11.7", @@ -953,6 +954,11 @@ } ] } + ], + "typescriptServerPlugins": [ + { + "name": "typescript-vscode-sh-plugin" + } ] } } diff --git a/extensions/typescript-language-features/src/features/semanticColoring.ts b/extensions/typescript-language-features/src/features/semanticTokens.ts similarity index 81% rename from extensions/typescript-language-features/src/features/semanticColoring.ts rename to extensions/typescript-language-features/src/features/semanticTokens.ts index 10a92c50bd2..cc9a8ba582a 100644 --- a/extensions/typescript-language-features/src/features/semanticColoring.ts +++ b/extensions/typescript-language-features/src/features/semanticTokens.ts @@ -56,14 +56,19 @@ class SemanticTokensProvider implements vscode.SemanticTokensProvider { return null; } + const versionBeforeRequest = document.version; + + if (_options.ranges) { + + // const allArgs = _options.ranges.map(r => ({file, start: document.offsetAt(r.start), length: document.offsetAt(r.end) - document.offsetAt(r.start)})); + } + const args: ExperimentalProtocol.EncodedSemanticClassificationsRequestArgs = { file: file, start: 0, length: document.getText().length, }; - const versionBeforeRequest = document.version; - const response = await (this.client as ExperimentalProtocol.IExtendedTypeScriptServiceClient).execute('encodedSemanticClassifications-full', args, token); const versionAfterRequest = document.version; @@ -84,23 +89,33 @@ class SemanticTokensProvider implements vscode.SemanticTokensProvider { const tsTokens = response.body.spans; for (let i = 0, len = Math.floor(tsTokens.length / 3); i < len; i++) { - const tokenType = tokenTypeMap[tsTokens[3 * i + 2]]; - if (typeof tokenType === 'number') { - console.log(TokenType[tokenType]); - const offset = tsTokens[3 * i]; - const length = tsTokens[3 * i + 1]; - - // we can use the document's range conversion methods because - // the result is at the same version as the document - const startPos = document.positionAt(offset); - const endPos = document.positionAt(offset + length); - - for (let line = startPos.line; line <= endPos.line; line++) { - const startCharacter = (line === startPos.line ? startPos.character : 0); - const endCharacter = (line === endPos.line ? endPos.character : document.lineAt(line).text.length); - builder.push(line, startCharacter, endCharacter - startCharacter, tokenType, 0); + const tsClassification = tsTokens[3 * i + 2]; + let tokenType = 0; + let tokenModifiers = 0; + if (tsClassification > 0xFF) { + // classifications as returned by the typescript-vscode-sh-plugin + tokenType = (tsClassification >> 8) - 1; + tokenModifiers = tsClassification & 0xFF; + } else { + tokenType = tokenTypeMap[tsClassification]; + if (tokenType === undefined) { + continue; } } + + const offset = tsTokens[3 * i]; + const length = tsTokens[3 * i + 1]; + + // we can use the document's range conversion methods because + // the result is at the same version as the document + const startPos = document.positionAt(offset); + const endPos = document.positionAt(offset + length); + + for (let line = startPos.line; line <= endPos.line; line++) { + const startCharacter = (line === startPos.line ? startPos.character : 0); + const endCharacter = (line === endPos.line ? endPos.character : document.lineAt(line).text.length); + builder.push(line, startCharacter, endCharacter - startCharacter, tokenType, tokenModifiers); + } } return new vscode.SemanticTokens(builder.build()); diff --git a/extensions/typescript-language-features/src/languageProvider.ts b/extensions/typescript-language-features/src/languageProvider.ts index 692cee35cbb..644eed40441 100644 --- a/extensions/typescript-language-features/src/languageProvider.ts +++ b/extensions/typescript-language-features/src/languageProvider.ts @@ -78,7 +78,7 @@ export default class LanguageProvider extends Disposable { import('./features/signatureHelp').then(provider => this._register(provider.register(selector, this.client))), import('./features/tagClosing').then(provider => this._register(provider.register(selector, this.description.id, this.client))), import('./features/typeDefinitions').then(provider => this._register(provider.register(selector, this.client))), - import('./features/semanticColoring').then(provider => this._register(provider.register(selector, this.client))), + import('./features/semanticTokens').then(provider => this._register(provider.register(selector, this.client))), import('./features/callHierarchy').then(provider => this._register(provider.register(selector, this.client))), ]); }