Skip to content

Commit 2dcdf7c

Browse files
committed
feat(intellij): reimplement and simplified parsing and syntax highlightning
1 parent 6fad9b1 commit 2dcdf7c

19 files changed

+235
-139
lines changed

intellij-client/gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ platformVersion = 2025.1
1818
# Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html
1919
# Example: platformPlugins = com.jetbrains.php:203.4449.22, org.intellij.scala:2023.3.27@EAP
2020
#platformPlugins = com.redhat.devtools.lsp4ij:0.13.0-20250502-121924@nightly
21-
platformPlugins = com.redhat.devtools.lsp4ij:0.12.0
21+
platformPlugins = com.redhat.devtools.lsp4ij:0.13.0
2222

2323

2424
# Example: platformBundledPlugins = com.intellij.java

intellij-client/src/main/kotlin/dev/robotcode/robotcode4ij/configuration/RobotCodeColorSettingsPage.kt

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ class RobotCodeColorSettingsPage : ColorSettingsPage {
3030
AttributesDescriptor("Variable expression", Colors.VARIABLE_EXPRESSION),
3131
AttributesDescriptor("Variable begin", Colors.VARIABLE_BEGIN),
3232
AttributesDescriptor("Variable end", Colors.VARIABLE_END),
33+
AttributesDescriptor("Variable index begin", Colors.VARIABLE_INDEX_BEGIN),
34+
AttributesDescriptor("Variable index end", Colors.VARIABLE_INDEX_END),
35+
AttributesDescriptor("Expression begin", Colors.EXPRESSION_BEGIN),
36+
AttributesDescriptor("Expression end", Colors.EXPRESSION_END),
3337

3438
AttributesDescriptor("Line comment", Colors.LINE_COMMENT),
3539
AttributesDescriptor("Block comment", Colors.BLOCK_COMMENT),
@@ -39,6 +43,8 @@ class RobotCodeColorSettingsPage : ColorSettingsPage {
3943
AttributesDescriptor("BDD prefix", Colors.BDD_PREFIX),
4044

4145
AttributesDescriptor("Continuation", Colors.CONTINUATION),
46+
47+
AttributesDescriptor("Escape", Colors.ESCAPE),
4248
)
4349

4450
override fun getAttributeDescriptors(): Array<AttributesDescriptor> {
@@ -92,9 +98,19 @@ class RobotCodeColorSettingsPage : ColorSettingsPage {
9298
... ${'$'}{arg2}
9399
[Tags] example
94100
[Setup] Open Application with arguments
95-
101+
96102
Log ${'$'}{arg1} ${'$'}{arg2}
97103
Log To Console Hello World
104+
Log ${'$'}{{1+2*"asd"}}
105+
Log \n \x12 \u1234 \U12345678 \N{name}
106+
Log ${'$'}{arg1}[abc]
107+
${'$'}{arg1}[abc] Evaluate 1+2
108+
109+
A Test With Vars
110+
VAR ${'$'}{var1} value1
111+
VAR @{var2} value2 value3
112+
VAR &{var2} v2=value2 v3=value3
113+
Do Something with=A Value
98114
99115
*** Keywords ***
100116
Open Application

intellij-client/src/main/kotlin/dev/robotcode/robotcode4ij/editor/RobotCodeBraceMatcher.kt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,18 @@ import com.intellij.psi.PsiFile
66
import com.intellij.psi.tree.IElementType
77
import dev.robotcode.robotcode4ij.psi.ENVIRONMENT_VARIABLE_BEGIN
88
import dev.robotcode.robotcode4ij.psi.ENVIRONMENT_VARIABLE_END
9+
import dev.robotcode.robotcode4ij.psi.EXPRESSION_BEGIN
10+
import dev.robotcode.robotcode4ij.psi.EXPRESSION_END
911
import dev.robotcode.robotcode4ij.psi.VARIABLE_BEGIN
1012
import dev.robotcode.robotcode4ij.psi.VARIABLE_END
13+
import dev.robotcode.robotcode4ij.psi.VARIABLE_INDEX_BEGIN
14+
import dev.robotcode.robotcode4ij.psi.VARIABLE_INDEX_END
1115

1216
private val PAIRS = arrayOf(
13-
BracePair(VARIABLE_BEGIN, VARIABLE_END, false),
14-
BracePair(ENVIRONMENT_VARIABLE_BEGIN, ENVIRONMENT_VARIABLE_END, false)
17+
BracePair(VARIABLE_BEGIN, VARIABLE_END, true),
18+
BracePair(EXPRESSION_BEGIN, EXPRESSION_END, true),
19+
BracePair(VARIABLE_INDEX_BEGIN, VARIABLE_INDEX_END, true),
20+
BracePair(ENVIRONMENT_VARIABLE_BEGIN, ENVIRONMENT_VARIABLE_END, true)
1521
)
1622

1723
class RobotCodeBraceMatcher : PairedBraceMatcher {

intellij-client/src/main/kotlin/dev/robotcode/robotcode4ij/highlighting/Colors.kt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,16 @@ object Colors {
4141
val VARIABLE_END: TextAttributesKey =
4242
createTextAttributesKey("ROBOTFRAMEWORK_VARIABLE_END", DefaultLanguageHighlighterColors.BRACES)
4343

44+
val VARIABLE_INDEX_BEGIN: TextAttributesKey =
45+
createTextAttributesKey("ROBOTFRAMEWORK_VARIABLE_INDEX_BEGIN", DefaultLanguageHighlighterColors.BRACKETS)
46+
val VARIABLE_INDEX_END: TextAttributesKey =
47+
createTextAttributesKey("ROBOTFRAMEWORK_VARIABLE_INDEX_END", DefaultLanguageHighlighterColors.BRACKETS)
48+
49+
val EXPRESSION_BEGIN: TextAttributesKey =
50+
createTextAttributesKey("ROBOTFRAMEWORK_EXPRESSION_BEGIN", DefaultLanguageHighlighterColors.BRACES)
51+
val EXPRESSION_END: TextAttributesKey =
52+
createTextAttributesKey("ROBOTFRAMEWORK_EXPRESSION_END", DefaultLanguageHighlighterColors.BRACES)
53+
4454
val NAMESPACE: TextAttributesKey =
4555
createTextAttributesKey("ROBOTFRAMEWORK_NAMESPACE", DefaultLanguageHighlighterColors.CLASS_REFERENCE)
4656

@@ -65,4 +75,10 @@ object Colors {
6575

6676
val CONTINUATION: TextAttributesKey =
6777
createTextAttributesKey("ROBOTFRAMEWORK_CONTINUATION", DefaultLanguageHighlighterColors.DOT)
78+
79+
val ESCAPE: TextAttributesKey =
80+
createTextAttributesKey("ROBOTFRAMEWORK_ESCAPE", DefaultLanguageHighlighterColors.VALID_STRING_ESCAPE)
81+
82+
val ERROR: TextAttributesKey =
83+
createTextAttributesKey("ROBOTFRAMEWORK_ERROR", DefaultLanguageHighlighterColors.INVALID_STRING_ESCAPE)
6884
}

intellij-client/src/main/kotlin/dev/robotcode/robotcode4ij/highlighting/RobotCodeLexer.kt

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,22 @@ import dev.robotcode.robotcode4ij.psi.CONTINUATION
1515
import dev.robotcode.robotcode4ij.psi.CONTROL_FLOW
1616
import dev.robotcode.robotcode4ij.psi.ENVIRONMENT_VARIABLE_BEGIN
1717
import dev.robotcode.robotcode4ij.psi.ENVIRONMENT_VARIABLE_END
18-
import dev.robotcode.robotcode4ij.psi.EXPRESSION_VARIABLE_BEGIN
19-
import dev.robotcode.robotcode4ij.psi.EXPRESSION_VARIABLE_END
18+
import dev.robotcode.robotcode4ij.psi.ESCAPE
19+
import dev.robotcode.robotcode4ij.psi.EXPRESSION_BEGIN
20+
import dev.robotcode.robotcode4ij.psi.EXPRESSION_END
2021
import dev.robotcode.robotcode4ij.psi.HEADER
2122
import dev.robotcode.robotcode4ij.psi.KEYWORD_CALL
2223
import dev.robotcode.robotcode4ij.psi.KEYWORD_NAME
2324
import dev.robotcode.robotcode4ij.psi.OPERATOR
2425
import dev.robotcode.robotcode4ij.psi.RobotTextMateElementType
2526
import dev.robotcode.robotcode4ij.psi.SETTING
2627
import dev.robotcode.robotcode4ij.psi.TESTCASE_NAME
28+
import dev.robotcode.robotcode4ij.psi.VAR
2729
import dev.robotcode.robotcode4ij.psi.VARIABLE
2830
import dev.robotcode.robotcode4ij.psi.VARIABLE_BEGIN
2931
import dev.robotcode.robotcode4ij.psi.VARIABLE_END
32+
import dev.robotcode.robotcode4ij.psi.VARIABLE_INDEX_BEGIN
33+
import dev.robotcode.robotcode4ij.psi.VARIABLE_INDEX_END
3034
import org.jetbrains.plugins.textmate.language.syntax.lexer.TextMateCachingSyntaxMatcher
3135
import org.jetbrains.plugins.textmate.language.syntax.lexer.TextMateLexerCore
3236
import org.jetbrains.plugins.textmate.language.syntax.lexer.TextMateScope
@@ -52,8 +56,10 @@ class RobotCodeLexer : LexerBase() {
5256
"punctuation.definition.variable.end.robotframework" to VARIABLE_END,
5357
"punctuation.definition.envvar.begin.robotframework" to ENVIRONMENT_VARIABLE_BEGIN,
5458
"punctuation.definition.envvar.end.robotframework" to ENVIRONMENT_VARIABLE_END,
55-
"punctuation.definition.expression.begin.robotframework" to EXPRESSION_VARIABLE_BEGIN,
56-
"punctuation.definition.expression.end.robotframework" to EXPRESSION_VARIABLE_END,
59+
"punctuation.definition.expression.begin.robotframework" to EXPRESSION_BEGIN,
60+
"punctuation.definition.expression.end.robotframework" to EXPRESSION_END,
61+
"punctuation.definition.variable.index.begin.robotframework" to VARIABLE_INDEX_BEGIN,
62+
"punctuation.definition.variable.index.end.robotframework" to VARIABLE_INDEX_END,
5763

5864
"entity.name.function.testcase.name.robotframework" to TESTCASE_NAME,
5965
"entity.name.function.keyword.name.robotframework" to KEYWORD_NAME,
@@ -73,16 +79,16 @@ class RobotCodeLexer : LexerBase() {
7379
"keyword.control.flow.robotframework" to CONTROL_FLOW,
7480

7581
"keyword.other.robotframework" to SETTING,
82+
"keyword.other.var.robotframework" to VAR,
7683

7784
"variable.name.readwrite.robotframework" to VARIABLE,
7885
"keyword.operator.robotframework" to OPERATOR,
7986

8087
"constant.character.robotframework" to ARGUMENT,
88+
"constant.character.escape.python" to ESCAPE,
8189
"string.unquoted.argument.robotframework" to ARGUMENT,
8290

8391
"keyword.operator.continue.robotframework" to CONTINUATION,
84-
85-
"punctuation.definition.variable.python.begin.robotframework" to VARIABLE_BEGIN,
8692
)
8793
}
8894
}
@@ -95,7 +101,7 @@ class RobotCodeLexer : LexerBase() {
95101
TextMateBundleHolder.descriptor,
96102
syntaxMatcher,
97103
Registry.get("textmate.line.highlighting.limit").asInteger(),
98-
false
104+
true,
99105
)
100106

101107

@@ -138,19 +144,21 @@ class RobotCodeLexer : LexerBase() {
138144
override fun advance() {
139145
if (this.currentOffset >= this.endOffset) {
140146
this.updateState(null, this.endOffset)
141-
} else {
142-
if (currentLineTokens.isEmpty()) {
143-
val app = ApplicationManager.getApplication()
144-
val checkCancelledCallback: Runnable? =
145-
if (app != null && !app.isUnitTestMode) Runnable { ProgressManager.checkCanceled() } else null
146-
currentLineTokens.addAll(lexer.advanceLine(checkCancelledCallback))
147-
}
148-
149-
this.updateState(
150-
currentLineTokens.poll(),
151-
lexer.getCurrentOffset()
152-
)
147+
return
148+
}
149+
150+
if (currentLineTokens.isEmpty()) {
151+
val app = ApplicationManager.getApplication()
152+
val checkCancelledCallback: Runnable? =
153+
if (app != null && !app.isUnitTestMode) Runnable { ProgressManager.checkCanceled() } else null
154+
currentLineTokens.addAll(lexer.advanceLine(checkCancelledCallback))
153155
}
156+
157+
this.updateState(
158+
currentLineTokens.poll(),
159+
lexer.getCurrentOffset()
160+
)
161+
154162
}
155163

156164
private fun updateState(token: TextmateToken?, fallbackOffset: Int) {

intellij-client/src/main/kotlin/dev/robotcode/robotcode4ij/highlighting/RobotCodeSyntaxHighlighter.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,22 @@ import dev.robotcode.robotcode4ij.psi.CONTINUATION
1313
import dev.robotcode.robotcode4ij.psi.CONTROL_FLOW
1414
import dev.robotcode.robotcode4ij.psi.ENVIRONMENT_VARIABLE_BEGIN
1515
import dev.robotcode.robotcode4ij.psi.ENVIRONMENT_VARIABLE_END
16+
import dev.robotcode.robotcode4ij.psi.ESCAPE
17+
import dev.robotcode.robotcode4ij.psi.EXPRESSION_BEGIN
18+
import dev.robotcode.robotcode4ij.psi.EXPRESSION_END
1619
import dev.robotcode.robotcode4ij.psi.HEADER
1720
import dev.robotcode.robotcode4ij.psi.KEYWORD_CALL
1821
import dev.robotcode.robotcode4ij.psi.KEYWORD_NAME
1922
import dev.robotcode.robotcode4ij.psi.OPERATOR
2023
import dev.robotcode.robotcode4ij.psi.RobotTextMateElementType
2124
import dev.robotcode.robotcode4ij.psi.SETTING
2225
import dev.robotcode.robotcode4ij.psi.TESTCASE_NAME
26+
import dev.robotcode.robotcode4ij.psi.VAR
2327
import dev.robotcode.robotcode4ij.psi.VARIABLE
2428
import dev.robotcode.robotcode4ij.psi.VARIABLE_BEGIN
2529
import dev.robotcode.robotcode4ij.psi.VARIABLE_END
30+
import dev.robotcode.robotcode4ij.psi.VARIABLE_INDEX_BEGIN
31+
import dev.robotcode.robotcode4ij.psi.VARIABLE_INDEX_END
2632

2733

2834
class RobotCodeSyntaxHighlighter : SyntaxHighlighterBase() {
@@ -34,16 +40,22 @@ class RobotCodeSyntaxHighlighter : SyntaxHighlighterBase() {
3440
VARIABLE_END to arrayOf(Colors.VARIABLE_END),
3541
ENVIRONMENT_VARIABLE_BEGIN to arrayOf(Colors.VARIABLE_BEGIN),
3642
ENVIRONMENT_VARIABLE_END to arrayOf(Colors.VARIABLE_END),
43+
EXPRESSION_BEGIN to arrayOf(Colors.EXPRESSION_BEGIN),
44+
EXPRESSION_END to arrayOf(Colors.EXPRESSION_END),
45+
VARIABLE_INDEX_BEGIN to arrayOf(Colors.VARIABLE_INDEX_BEGIN),
46+
VARIABLE_INDEX_END to arrayOf(Colors.VARIABLE_INDEX_END),
3747
TESTCASE_NAME to arrayOf(Colors.TESTCASE_NAME),
3848
KEYWORD_NAME to arrayOf(Colors.KEYWORD_NAME),
3949
HEADER to arrayOf(Colors.HEADER),
4050
SETTING to arrayOf(Colors.SETTING),
51+
VAR to arrayOf(Colors.VAR),
4152
KEYWORD_CALL to arrayOf(Colors.KEYWORD_CALL),
4253
CONTROL_FLOW to arrayOf(Colors.CONTROL_FLOW),
4354
VARIABLE to arrayOf(Colors.VARIABLE),
4455
OPERATOR to arrayOf(Colors.OPERATOR),
4556
ARGUMENT to arrayOf(Colors.ARGUMENT),
4657
CONTINUATION to arrayOf(Colors.CONTINUATION),
58+
ESCAPE to arrayOf(Colors.ESCAPE),
4759
)
4860

4961
val textMateElementMap = mapOf(

intellij-client/src/main/kotlin/dev/robotcode/robotcode4ij/lsp/RobotCodeLanguageServerFactory.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import com.redhat.devtools.lsp4ij.client.features.LSPClientFeatures
88
import com.redhat.devtools.lsp4ij.server.StreamConnectionProvider
99
import dev.robotcode.robotcode4ij.lsp.RobotCodeLanguageServerManager.Companion.LANGUAGE_SERVER_ENABLED_KEY
1010
import dev.robotcode.robotcode4ij.lsp.features.RobotDiagnosticsFeature
11+
import dev.robotcode.robotcode4ij.lsp.features.RobotSemanticTokensFeature
1112
import org.eclipse.lsp4j.services.LanguageServer
1213

1314
@Suppress("UnstableApiUsage") class RobotCodeLanguageServerFactory : LanguageServerFactory,
@@ -17,7 +18,9 @@ import org.eclipse.lsp4j.services.LanguageServer
1718
}
1819

1920
override fun createClientFeatures(): LSPClientFeatures {
20-
return super.createClientFeatures().setDiagnosticFeature(RobotDiagnosticsFeature())
21+
return super.createClientFeatures()
22+
.setDiagnosticFeature(RobotDiagnosticsFeature())
23+
.setSemanticTokensFeature(RobotSemanticTokensFeature())
2124
}
2225

2326
override fun createLanguageClient(project: Project): LanguageClientImpl {

intellij-client/src/main/kotlin/dev/robotcode/robotcode4ij/lsp/RobotCodeSemanticTokensColorsProvider.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,12 @@ private val mapping by lazy {
3535
"variableExpression" to Colors.VARIABLE_EXPRESSION,
3636
"variableBegin" to Colors.VARIABLE_BEGIN,
3737
"variableEnd" to Colors.VARIABLE_END,
38-
38+
"expressionBegin" to Colors.EXPRESSION_BEGIN,
39+
"expressionEnd" to Colors.EXPRESSION_END,
3940
"namespace" to Colors.NAMESPACE,
4041
"bddPrefix" to Colors.BDD_PREFIX,
41-
"continuation" to Colors.CONTINUATION
42+
"continuation" to Colors.CONTINUATION,
43+
"error" to Colors.ERROR,
4244
)
4345
}
4446

intellij-client/src/main/kotlin/dev/robotcode/robotcode4ij/lsp/RobotCodeTokensFileViewProviderFactory.kt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,4 @@ class RobotCodeTokensFileViewProvider(
2929
eventSystemEnabled: Boolean,
3030
language: Language
3131
) : LSPSemanticTokensSingleRootFileViewProvider(manager, file, eventSystemEnabled, language),
32-
LSPSemanticTokensFileViewProvider {
33-
34-
35-
}
32+
LSPSemanticTokensFileViewProvider

intellij-client/src/main/kotlin/dev/robotcode/robotcode4ij/lsp/RobotSemanticTokensHighlightVisitor.kt

Lines changed: 0 additions & 64 deletions
This file was deleted.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package dev.robotcode.robotcode4ij.lsp.features
2+
3+
import com.intellij.psi.PsiElement
4+
import com.intellij.psi.PsiFile
5+
import com.redhat.devtools.lsp4ij.client.features.LSPSemanticTokensFeature
6+
import dev.robotcode.robotcode4ij.psi.IRobotFrameworkElementType
7+
import org.toml.lang.psi.ext.elementType
8+
9+
@Suppress("UnstableApiUsage") class RobotSemanticTokensFeature : LSPSemanticTokensFeature() {
10+
11+
override fun isEligibleForSemanticHighlighting(element: PsiElement): Boolean {
12+
return element.elementType is IRobotFrameworkElementType
13+
}
14+
}

intellij-client/src/main/kotlin/dev/robotcode/robotcode4ij/psi/ElementTypes.kt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,24 @@ val COMMENT_LINE = IRobotFrameworkElementType("COMMENT_LINE")
2525
val COMMENT_BLOCK = IRobotFrameworkElementType("COMMENT_BLOCK")
2626

2727
val ARGUMENT = IRobotFrameworkElementType("ARGUMENT")
28+
val ESCAPE = IRobotFrameworkElementType("ESCAPE")
2829

2930
val VARIABLE_BEGIN = IRobotFrameworkElementType("VARIABLE_BEGIN")
3031
val VARIABLE_END = IRobotFrameworkElementType("VARIABLE_END")
31-
val EXPRESSION_VARIABLE_BEGIN = IRobotFrameworkElementType("EXPRESSION_VARIABLE_BEGIN")
32-
val EXPRESSION_VARIABLE_END = IRobotFrameworkElementType("EXPRESSION_VARIABLE_END")
32+
val EXPRESSION_BEGIN = IRobotFrameworkElementType("EXPRESSION_VARIABLE_BEGIN")
33+
val EXPRESSION_END = IRobotFrameworkElementType("EXPRESSION_VARIABLE_END")
3334
val ENVIRONMENT_VARIABLE_BEGIN = IRobotFrameworkElementType("VARIABLE_BEGIN")
3435
val ENVIRONMENT_VARIABLE_END = IRobotFrameworkElementType("VARIABLE_END")
36+
val VARIABLE_INDEX_BEGIN = IRobotFrameworkElementType("VARIABLE_INDEX_BEGIN")
37+
val VARIABLE_INDEX_END = IRobotFrameworkElementType("VARIABLE_INDEX_END")
3538

3639
val KEYWORD_CALL = IRobotFrameworkElementType("KEYWORD_CALL")
3740
val CONTROL_FLOW = IRobotFrameworkElementType("CONTROL_FLOW")
3841
val VARIABLE = IRobotFrameworkElementType("VARIABLE")
3942

4043
val OPERATOR = IRobotFrameworkElementType("OPERATOR")
4144
val CONTINUATION = IRobotFrameworkElementType("CONTINUATION")
42-
45+
val VAR = IRobotFrameworkElementType("VAR")
4346

4447
val COMMENT_TOKENS = TokenSet.create(COMMENT_LINE, COMMENT_BLOCK)
4548
val STRING_TOKENS = TokenSet.create(ARGUMENT)

0 commit comments

Comments
 (0)