1
1
package dev.robotcode.robotcode4ij.highlighting
2
2
3
+ import com.intellij.lexer.LexerBase
3
4
import com.intellij.openapi.util.registry.Registry
5
+ import com.intellij.psi.TokenType
4
6
import com.intellij.psi.tree.IElementType
5
7
import dev.robotcode.robotcode4ij.TextMateBundleHolder
6
8
import dev.robotcode.robotcode4ij.psi.ARGUMENT
@@ -10,6 +12,8 @@ import dev.robotcode.robotcode4ij.psi.CONTINUATION
10
12
import dev.robotcode.robotcode4ij.psi.CONTROL_FLOW
11
13
import dev.robotcode.robotcode4ij.psi.ENVIRONMENT_VARIABLE_BEGIN
12
14
import dev.robotcode.robotcode4ij.psi.ENVIRONMENT_VARIABLE_END
15
+ import dev.robotcode.robotcode4ij.psi.EXPRESSION_VARIABLE_BEGIN
16
+ import dev.robotcode.robotcode4ij.psi.EXPRESSION_VARIABLE_END
13
17
import dev.robotcode.robotcode4ij.psi.HEADER
14
18
import dev.robotcode.robotcode4ij.psi.KEYWORD_CALL
15
19
import dev.robotcode.robotcode4ij.psi.KEYWORD_NAME
@@ -20,22 +24,25 @@ import dev.robotcode.robotcode4ij.psi.TESTCASE_NAME
20
24
import dev.robotcode.robotcode4ij.psi.VARIABLE
21
25
import dev.robotcode.robotcode4ij.psi.VARIABLE_BEGIN
22
26
import dev.robotcode.robotcode4ij.psi.VARIABLE_END
23
- import org.jetbrains.plugins.textmate.language.syntax.lexer.TextMateElementType
24
- import org.jetbrains.plugins.textmate.language.syntax.lexer.TextMateHighlightingLexer
27
+ import org.jetbrains.plugins.textmate.language.syntax.lexer.TextMateLexer
28
+ import org.jetbrains.plugins.textmate.language.syntax.lexer.TextMateScope
29
+ import java.util.*
30
+ import kotlin.math.min
25
31
26
- class RobotTextMateHighlightingLexer : TextMateHighlightingLexer (
27
- TextMateBundleHolder .descriptor, Registry .get("textmate.line.highlighting.limit").asInteger()
28
- ) {
32
+ class RobotCodeTextMateHighlightingLexer : LexerBase () {
29
33
companion object {
30
34
val mapping by lazy {
31
35
mapOf (
32
36
" comment.line.robotframework" to COMMENT_LINE ,
33
37
" comment.line.rest.robotframework" to COMMENT_LINE ,
34
38
" comment.block.robotframework" to COMMENT_BLOCK ,
39
+
35
40
" punctuation.definition.variable.begin.robotframework" to VARIABLE_BEGIN ,
36
41
" punctuation.definition.variable.end.robotframework" to VARIABLE_END ,
37
42
" punctuation.definition.envvar.begin.robotframework" to ENVIRONMENT_VARIABLE_BEGIN ,
38
43
" punctuation.definition.envvar.end.robotframework" to ENVIRONMENT_VARIABLE_END ,
44
+ " punctuation.definition.expression.begin.robotframework" to EXPRESSION_VARIABLE_BEGIN ,
45
+ " punctuation.definition.expression.end.robotframework" to EXPRESSION_VARIABLE_END ,
39
46
40
47
" entity.name.function.testcase.name.robotframework" to TESTCASE_NAME ,
41
48
" entity.name.function.keyword.name.robotframework" to KEYWORD_NAME ,
@@ -63,16 +70,94 @@ class RobotTextMateHighlightingLexer : TextMateHighlightingLexer(
63
70
" string.unquoted.argument.robotframework" to ARGUMENT ,
64
71
65
72
" keyword.operator.continue.robotframework" to CONTINUATION ,
73
+
74
+ " punctuation.definition.variable.python.begin.robotframework" to VARIABLE_BEGIN ,
66
75
)
67
76
}
68
77
}
69
78
79
+
80
+ private val myLexer =
81
+ TextMateLexer (
82
+ TextMateBundleHolder .descriptor, Registry .get(" textmate.line.highlighting.limit" ).asInteger(),
83
+ true
84
+ )
85
+ private var currentLineTokens = LinkedList <TextMateLexer .Token ?>()
86
+ private lateinit var buffer: CharSequence
87
+ private var endOffset = 0
88
+ private var currentOffset = 0
89
+ private var tokenType: IElementType ? = null
90
+ private var tokenStart = 0
91
+ private var tokenEnd = 0
92
+ private var restartable = false
93
+
94
+ override fun start (buffer : CharSequence , startOffset : Int , endOffset : Int , initialState : Int ) {
95
+ this .buffer = buffer
96
+ this .endOffset = endOffset
97
+ this .currentOffset = startOffset
98
+ this .endOffset = endOffset
99
+ this .currentLineTokens.clear()
100
+ this .restartable = initialState == 0
101
+ myLexer.init (buffer, startOffset)
102
+ this .advance()
103
+ }
104
+
105
+ override fun getState (): Int {
106
+ return if (restartable) 0 else 1
107
+ }
108
+
70
109
override fun getTokenType (): IElementType ? {
71
- val result = super .getTokenType() ? : return null
72
- if (result is TextMateElementType ) {
73
- return mapping[result.scope.scopeName] ? : RobotTextMateElementType (result)
110
+ return tokenType
111
+ }
112
+
113
+ override fun getTokenStart (): Int {
114
+ return tokenStart
115
+ }
116
+
117
+ override fun getTokenEnd (): Int {
118
+ return tokenEnd
119
+ }
120
+
121
+ override fun advance () {
122
+ if (this .currentOffset >= this .endOffset) {
123
+ this .updateState(null as TextMateLexer .Token ? , this .endOffset)
124
+ } else {
125
+ if (currentLineTokens.isEmpty()) {
126
+ myLexer.advanceLine(this .currentLineTokens)
127
+ }
128
+
129
+ this .updateState(
130
+ currentLineTokens.poll(),
131
+ myLexer.currentOffset
132
+ )
74
133
}
75
- return result
134
+ }
135
+
136
+ private fun updateState (token : TextMateLexer .Token ? , fallbackOffset : Int ) {
137
+ if (token != null ) {
138
+ this .tokenType =
139
+ (if (token.scope == = TextMateScope .WHITESPACE ) TokenType .WHITE_SPACE else mapping[token.scope.scopeName]
140
+ ? : RobotTextMateElementType .create(token.scope))
141
+
142
+ tokenStart = token.startOffset
143
+ tokenEnd = min(token.endOffset.toDouble(), endOffset.toDouble()).toInt()
144
+ currentOffset = token.endOffset
145
+ restartable = token.restartable
146
+ } else {
147
+ tokenType = null
148
+ tokenStart = fallbackOffset
149
+ tokenEnd = fallbackOffset
150
+ currentOffset = fallbackOffset
151
+ restartable = true
152
+ }
153
+ }
154
+
155
+ override fun getBufferSequence (): CharSequence {
156
+ return buffer
157
+ }
158
+
159
+ override fun getBufferEnd (): Int {
160
+ return endOffset
76
161
}
77
162
}
78
163
0 commit comments