From 2ca09d93aaa1e7b3e49db0ff7377249b83f1815c Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Mon, 16 Dec 2019 23:13:14 +0100 Subject: [PATCH] visit ast --- .../src/modes/javascriptSemanticTokens.ts | 81 ++++++++++++++++--- .../common/tokenClassificationRegistry.ts | 5 +- 2 files changed, 73 insertions(+), 13 deletions(-) diff --git a/extensions/html-language-features/server/src/modes/javascriptSemanticTokens.ts b/extensions/html-language-features/server/src/modes/javascriptSemanticTokens.ts index 99965fe7617..fc4f3824f0e 100644 --- a/extensions/html-language-features/server/src/modes/javascriptSemanticTokens.ts +++ b/extensions/html-language-features/server/src/modes/javascriptSemanticTokens.ts @@ -14,12 +14,41 @@ export function getSemanticTokens(jsLanguageService: ts.LanguageService, current let resultTokens: SemanticTokenData[] = []; const tokens = jsLanguageService.getSemanticClassifications(fileName, { start: 0, length: currentTextDocument.getText().length }); for (let token of tokens) { - const typeIdx = tokenMapping[token.classificationType]; + const typeIdx = tokenFromClassificationMapping[token.classificationType]; if (typeIdx !== undefined) { resultTokens.push({ offset: token.textSpan.start, length: token.textSpan.length, typeIdx, modifierSet: 0 }); } } + const program = jsLanguageService.getProgram(); + if (program) { + const typeChecker = program.getTypeChecker(); + + + function visit(node: ts.Node) { + if (node.kind === ts.SyntaxKind.Identifier) { + const symbol = typeChecker.getSymbolAtLocation(node); + if (symbol) { + let typeIdx = tokenFromDeclarationMapping[symbol.valueDeclaration.kind]; + let modifierSet = 0; + if (symbol.valueDeclaration === node.parent) { + modifierSet = TokenModifier.declaration; + } + if (typeIdx !== undefined) { + resultTokens.push({ offset: node.pos, length: node.end - node.pos, typeIdx, modifierSet }); + } + } + } + + ts.forEachChild(node, visit); + } + const sourceFile = program.getSourceFile(fileName); + if (sourceFile) { + visit(sourceFile); + } + } + + resultTokens = resultTokens.sort((d1, d2) => d1.offset - d2.offset); const offsetRanges = ranges.map(r => ({ startOffset: currentTextDocument.offsetAt(r.start), endOffset: currentTextDocument.offsetAt(r.end) })).sort((d1, d2) => d1.startOffset - d2.startOffset); @@ -62,15 +91,45 @@ export function getSemanticTokenLegend() { } -const tokenTypes: string[] = ['class', 'enum', 'interface', 'namespace', 'parameterType', 'type', 'parameter']; -const tokenModifiers: string[] = []; +const tokenTypes: string[] = ['class', 'enum', 'interface', 'namespace', 'parameterType', 'type', 'parameter', 'variable', 'property', 'constant', 'function']; +const tokenModifiers: string[] = ['declaration',]; + +enum TokenType { + 'class' = 0, + 'enum' = 1, + 'interface' = 2, + 'namespace' = 3, + 'parameterType' = 4, + 'type' = 5, + 'parameter' = 6, + 'variable' = 7, + 'property' = 8, + 'constant' = 9, + 'function' = 10, +} + +enum TokenModifier { + 'declaration' = 0x01, + +} + +const tokenFromClassificationMapping: { [name: string]: TokenType } = { + [ts.ClassificationTypeNames.className]: TokenType.class, + [ts.ClassificationTypeNames.enumName]: TokenType.enum, + [ts.ClassificationTypeNames.interfaceName]: TokenType.interface, + [ts.ClassificationTypeNames.moduleName]: TokenType.namespace, + [ts.ClassificationTypeNames.typeParameterName]: TokenType.parameterType, + [ts.ClassificationTypeNames.typeAliasName]: TokenType.type, + [ts.ClassificationTypeNames.parameterName]: TokenType.parameter +}; -const tokenMapping: { [name: string]: number } = { - [ts.ClassificationTypeNames.className]: tokenTypes.indexOf('class'), - [ts.ClassificationTypeNames.enumName]: tokenTypes.indexOf('enum'), - [ts.ClassificationTypeNames.interfaceName]: tokenTypes.indexOf('interface'), - [ts.ClassificationTypeNames.moduleName]: tokenTypes.indexOf('namespace'), - [ts.ClassificationTypeNames.typeParameterName]: tokenTypes.indexOf('parameterType'), - [ts.ClassificationTypeNames.typeAliasName]: tokenTypes.indexOf('type'), - [ts.ClassificationTypeNames.parameterName]: tokenTypes.indexOf('parameter') +const tokenFromDeclarationMapping: { [name: string]: TokenType } = { + [ts.SyntaxKind.VariableDeclaration]: TokenType.variable, + [ts.SyntaxKind.Parameter]: TokenType.parameter, + [ts.SyntaxKind.PropertyDeclaration]: TokenType.property, + [ts.SyntaxKind.ModuleDeclaration]: TokenType.namespace, + [ts.SyntaxKind.EnumDeclaration]: TokenType.enum, + [ts.SyntaxKind.EnumMember]: TokenType.property, + [ts.SyntaxKind.ClassDeclaration]: TokenType.property, + [ts.SyntaxKind.MethodDeclaration]: TokenType.function }; diff --git a/src/vs/platform/theme/common/tokenClassificationRegistry.ts b/src/vs/platform/theme/common/tokenClassificationRegistry.ts index a9355a0eb83..a67211cf7ed 100644 --- a/src/vs/platform/theme/common/tokenClassificationRegistry.ts +++ b/src/vs/platform/theme/common/tokenClassificationRegistry.ts @@ -381,12 +381,13 @@ function registerDefaultClassifications(): void { registerTokenType('parameterType', nls.localize('parameterType', "Style for parameter types."), undefined, 'type'); registerTokenType('function', nls.localize('function', "Style for functions"), [['entity.name.function'], ['support.function']]); + registerTokenType('member', nls.localize('member', "Style for member"), [['entity.name.function'], ['support.function']]); registerTokenType('macro', nls.localize('macro', "Style for macros."), undefined, 'function'); registerTokenType('variable', nls.localize('variable', "Style for variables."), [['variable'], ['entity.name.variable']]); registerTokenType('constant', nls.localize('constant', "Style for constants."), undefined, 'variable'); registerTokenType('parameter', nls.localize('parameter', "Style for parameters."), undefined, 'variable'); - registerTokenType('property', nls.localize('propertie', "Style for properties."), undefined, 'variable'); + registerTokenType('property', nls.localize('property', "Style for properties."), undefined, 'variable'); registerTokenType('label', nls.localize('labels', "Style for labels. "), undefined); @@ -394,7 +395,7 @@ function registerDefaultClassifications(): void { tokenClassificationRegistry.registerTokenModifier('declaration', nls.localize('declaration', "Style for all symbol declarations."), undefined); tokenClassificationRegistry.registerTokenModifier('documentation', nls.localize('documentation', "Style to use for references in documentation."), undefined); - tokenClassificationRegistry.registerTokenModifier('member', nls.localize('member', "Style to use for member functions, variables (fields) and types."), undefined); + //tokenClassificationRegistry.registerTokenModifier('member', nls.localize('member', "Style to use for member functions, variables (fields) and types."), undefined); tokenClassificationRegistry.registerTokenModifier('static', nls.localize('static', "Style to use for symbols that are static."), undefined); tokenClassificationRegistry.registerTokenModifier('abstract', nls.localize('abstract', "Style to use for symbols that are abstract."), undefined); tokenClassificationRegistry.registerTokenModifier('deprecated', nls.localize('deprecated', "Style to use for symbols that are deprecated."), undefined); -- GitLab