11package dev.robotcode.robotcode4ij.highlighting
22
3+ import com.intellij.lexer.LexerBase
34import com.intellij.openapi.util.registry.Registry
5+ import com.intellij.psi.TokenType
46import com.intellij.psi.tree.IElementType
57import dev.robotcode.robotcode4ij.TextMateBundleHolder
68import dev.robotcode.robotcode4ij.psi.ARGUMENT
@@ -10,6 +12,8 @@ import dev.robotcode.robotcode4ij.psi.CONTINUATION
1012import dev.robotcode.robotcode4ij.psi.CONTROL_FLOW
1113import dev.robotcode.robotcode4ij.psi.ENVIRONMENT_VARIABLE_BEGIN
1214import 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
1317import dev.robotcode.robotcode4ij.psi.HEADER
1418import dev.robotcode.robotcode4ij.psi.KEYWORD_CALL
1519import dev.robotcode.robotcode4ij.psi.KEYWORD_NAME
@@ -20,22 +24,25 @@ import dev.robotcode.robotcode4ij.psi.TESTCASE_NAME
2024import dev.robotcode.robotcode4ij.psi.VARIABLE
2125import dev.robotcode.robotcode4ij.psi.VARIABLE_BEGIN
2226import 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
2531
26- class RobotTextMateHighlightingLexer : TextMateHighlightingLexer (
27- TextMateBundleHolder .descriptor, Registry .get("textmate.line.highlighting.limit").asInteger()
28- ) {
32+ class RobotCodeTextMateHighlightingLexer : LexerBase () {
2933 companion object {
3034 val mapping by lazy {
3135 mapOf (
3236 " comment.line.robotframework" to COMMENT_LINE ,
3337 " comment.line.rest.robotframework" to COMMENT_LINE ,
3438 " comment.block.robotframework" to COMMENT_BLOCK ,
39+
3540 " punctuation.definition.variable.begin.robotframework" to VARIABLE_BEGIN ,
3641 " punctuation.definition.variable.end.robotframework" to VARIABLE_END ,
3742 " punctuation.definition.envvar.begin.robotframework" to ENVIRONMENT_VARIABLE_BEGIN ,
3843 " 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 ,
3946
4047 " entity.name.function.testcase.name.robotframework" to TESTCASE_NAME ,
4148 " entity.name.function.keyword.name.robotframework" to KEYWORD_NAME ,
@@ -63,16 +70,94 @@ class RobotTextMateHighlightingLexer : TextMateHighlightingLexer(
6370 " string.unquoted.argument.robotframework" to ARGUMENT ,
6471
6572 " keyword.operator.continue.robotframework" to CONTINUATION ,
73+
74+ " punctuation.definition.variable.python.begin.robotframework" to VARIABLE_BEGIN ,
6675 )
6776 }
6877 }
6978
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+
70109 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+ )
74133 }
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
76161 }
77162}
78163
0 commit comments