From 7fc7ef523d9531319ab783b34ad1e8b09d665fb8 Mon Sep 17 00:00:00 2001 From: Ilya Rodionov Date: Sun, 18 Aug 2024 22:28:18 +0300 Subject: [PATCH] [JavaScript] const variable highlighting (fixes #22) --- .../webcalm/css/CssSyntaxHighlighter.kt | 18 ++++--- .../JavaScriptHighlightingAnnotator.kt | 47 +++++++++++++------ .../javascript/JavaScriptSyntaxHighlighter.kt | 26 +++++----- .../javascript/reassinged-variables.js | 8 ++++ 4 files changed, 67 insertions(+), 32 deletions(-) create mode 100644 src/test/testData/javascript/reassinged-variables.js diff --git a/src/main/kotlin/ris58h/webcalm/css/CssSyntaxHighlighter.kt b/src/main/kotlin/ris58h/webcalm/css/CssSyntaxHighlighter.kt index 13738c0..75c9525 100644 --- a/src/main/kotlin/ris58h/webcalm/css/CssSyntaxHighlighter.kt +++ b/src/main/kotlin/ris58h/webcalm/css/CssSyntaxHighlighter.kt @@ -22,6 +22,16 @@ class CssSyntaxHighlighter : SyntaxHighlighterBase() { } private fun tokenColor(tokenType: IElementType): TextAttributesKey? { + //TODO: other token types + return when (tokenType) { + CssTypes.NUMBER, CssTypes.DIMENSION, CssTypes.PERCENTAGE -> CssSyntaxHighlighterColors.NUMBER + CssTypes.HASH -> CssSyntaxHighlighterColors.CONSTANT + CssTypes.VARIABLE -> CssSyntaxHighlighterColors.VARIABLE + else -> tokenColorFromTokenSets(tokenType) + } + } + + private fun tokenColorFromTokenSets(tokenType: IElementType): TextAttributesKey? { if (CssTokenSets.COMMENTS.contains(tokenType)) { return CssSyntaxHighlighterColors.COMMENT } @@ -49,12 +59,6 @@ class CssSyntaxHighlighter : SyntaxHighlighterBase() { if (CssTokenSets.FUNCTIONS.contains(tokenType)) { return CssSyntaxHighlighterColors.FUNCTION_CALL } - //TODO: other token types - return when (tokenType) { - CssTypes.NUMBER, CssTypes.DIMENSION, CssTypes.PERCENTAGE -> CssSyntaxHighlighterColors.NUMBER - CssTypes.HASH -> CssSyntaxHighlighterColors.CONSTANT - CssTypes.VARIABLE -> CssSyntaxHighlighterColors.VARIABLE - else -> null - } + return null } } \ No newline at end of file diff --git a/src/main/kotlin/ris58h/webcalm/javascript/JavaScriptHighlightingAnnotator.kt b/src/main/kotlin/ris58h/webcalm/javascript/JavaScriptHighlightingAnnotator.kt index 423b401..d54b133 100644 --- a/src/main/kotlin/ris58h/webcalm/javascript/JavaScriptHighlightingAnnotator.kt +++ b/src/main/kotlin/ris58h/webcalm/javascript/JavaScriptHighlightingAnnotator.kt @@ -7,6 +7,7 @@ import com.intellij.openapi.editor.DefaultLanguageHighlighterColors import com.intellij.openapi.editor.colors.TextAttributesKey import com.intellij.openapi.project.DumbAware import com.intellij.psi.PsiElement +import com.intellij.psi.util.PsiTreeUtil import ris58h.webcalm.javascript.psi.* class JavaScriptHighlightingAnnotator : Annotator, DumbAware { @@ -15,8 +16,33 @@ class JavaScriptHighlightingAnnotator : Annotator, DumbAware { override fun annotate(element: PsiElement, holder: AnnotationHolder) { if (element !is JavaScriptIdentifier) return - val color = when (val parent = element.parent) { - is JavaScriptVariableDeclaration -> DefaultLanguageHighlighterColors.LOCAL_VARIABLE + var color = colorFromElement(element) + + if (color == null) { + val resolved = element.reference?.resolve() + if (resolved is JavaScriptIdentifier) { + color = colorFromElement(resolved) + } + } + + if (color != null) { + holder.newSilentAnnotation(HighlightSeverity.INFORMATION) + .textAttributes(color) + .create() + } + } + + private fun colorFromElement(element: JavaScriptIdentifier) = + when (val parent = element.parent) { + is JavaScriptVariableDeclaration -> { + val variableStatement = PsiTreeUtil.getParentOfType(parent, JavaScriptVariableStatement::class.java) + if (variableStatement != null + && PsiTreeUtil.getParentOfType(variableStatement, JavaScriptStatementsOwner::class.java) is JavaScriptFile) { + DefaultLanguageHighlighterColors.CONSTANT + } + else DefaultLanguageHighlighterColors.LOCAL_VARIABLE + } + is JavaScriptFormalParameter -> DefaultLanguageHighlighterColors.PARAMETER is JavaScriptIdentifierExpression -> colorWhenParentIsIdentifierExpression(parent, element) is JavaScriptFunctionDeclaration -> { @@ -39,21 +65,14 @@ class JavaScriptHighlightingAnnotator : Annotator, DumbAware { else -> null } - if (color != null) { - holder.newSilentAnnotation(HighlightSeverity.INFORMATION) - .textAttributes(color) - .create() - } - } - private fun colorWhenParentIsIdentifierExpression(parent: JavaScriptIdentifierExpression, element: JavaScriptIdentifier): TextAttributesKey? { return when (val parent2 = parent.parent) { is JavaScriptCallExpression -> DefaultLanguageHighlighterColors.FUNCTION_CALL - is JavaScriptUpdateExpression -> DefaultLanguageHighlighterColors.REASSIGNED_LOCAL_VARIABLE - is JavaScriptAssignmentExpression -> { - if (parent2.firstChild === parent) DefaultLanguageHighlighterColors.REASSIGNED_LOCAL_VARIABLE - else null - } +// is JavaScriptUpdateExpression -> DefaultLanguageHighlighterColors.REASSIGNED_LOCAL_VARIABLE +// is JavaScriptAssignmentExpression -> { +// if (parent2.firstChild === parent) DefaultLanguageHighlighterColors.REASSIGNED_LOCAL_VARIABLE +// else null +// } is JavaScriptFormalRestParameter -> DefaultLanguageHighlighterColors.PARAMETER else -> { // TODO: check for a param with the same name that can override predefined globals diff --git a/src/main/kotlin/ris58h/webcalm/javascript/JavaScriptSyntaxHighlighter.kt b/src/main/kotlin/ris58h/webcalm/javascript/JavaScriptSyntaxHighlighter.kt index 0192a3d..a8ee99c 100644 --- a/src/main/kotlin/ris58h/webcalm/javascript/JavaScriptSyntaxHighlighter.kt +++ b/src/main/kotlin/ris58h/webcalm/javascript/JavaScriptSyntaxHighlighter.kt @@ -22,6 +22,20 @@ class JavaScriptSyntaxHighlighter : SyntaxHighlighterBase() { } private fun tokenColor(tokenType: IElementType): TextAttributesKey? { + //TODO: other token types + return when (tokenType) { + JavaScriptTypes.NULL_LITERAL -> JavaScriptHighlighterColors.KEYWORD + JavaScriptTypes.BOOLEAN_LITERAL -> JavaScriptHighlighterColors.KEYWORD + JavaScriptTypes.IDENTIFIER -> JavaScriptHighlighterColors.IDENTIFIER + JavaScriptTypes.DOT, JavaScriptTypes.QUESTION_MARK_DOT -> JavaScriptHighlighterColors.DOT + JavaScriptTypes.SEMICOLON -> JavaScriptHighlighterColors.SEMICOLON + JavaScriptTypes.COMMA -> JavaScriptHighlighterColors.COMMA + JavaScriptTypes.REGEX_LITERAL -> JavaScriptHighlighterColors.STRING + else -> tokenColorFromTokenSets(tokenType) + } + } + + private fun tokenColorFromTokenSets(tokenType: IElementType): TextAttributesKey? { if (JavaScriptTokenSets.COMMENTS.contains(tokenType)) { return JavaScriptHighlighterColors.COMMENT } @@ -49,16 +63,6 @@ class JavaScriptSyntaxHighlighter : SyntaxHighlighterBase() { if (JavaScriptTokenSets.NUMBERS.contains(tokenType)) { return JavaScriptHighlighterColors.NUMBER } - //TODO: other token types - return when (tokenType) { - JavaScriptTypes.NULL_LITERAL -> JavaScriptHighlighterColors.KEYWORD - JavaScriptTypes.BOOLEAN_LITERAL -> JavaScriptHighlighterColors.KEYWORD - JavaScriptTypes.IDENTIFIER -> JavaScriptHighlighterColors.IDENTIFIER - JavaScriptTypes.DOT, JavaScriptTypes.QUESTION_MARK_DOT -> JavaScriptHighlighterColors.DOT - JavaScriptTypes.SEMICOLON -> JavaScriptHighlighterColors.SEMICOLON - JavaScriptTypes.COMMA -> JavaScriptHighlighterColors.COMMA - JavaScriptTypes.REGEX_LITERAL -> JavaScriptHighlighterColors.STRING - else -> null - } + return null } } \ No newline at end of file diff --git a/src/test/testData/javascript/reassinged-variables.js b/src/test/testData/javascript/reassinged-variables.js new file mode 100644 index 0000000..784175b --- /dev/null +++ b/src/test/testData/javascript/reassinged-variables.js @@ -0,0 +1,8 @@ +var a = 0; +a = a + 1; + +let b = 0; +b = b + 1; + +const c = 0; +c = c + 1;