LexerEditorHighlighter$InvalidStateException

I have followed the custom language plugin tutorial and implemented a FlexLexer and parser which works fine. I've added the SyntaxHighlighting which also works great however, once I change the text of the document I get the following exception: 

com.intellij.openapi.editor.ex.util.LexerEditorHighlighter$InvalidStateException: com.intellij.openapi.editor.ex.util.LexerEditorHighlighter(com.misset.opp.omt.OMTLexerAdapter): Error updating after DocumentEventImpl[myOffset=999, myOldLength=1, myNewLength=0, myOldString='d', myNewString=''].
at com.intellij.openapi.editor.ex.util.LexerEditorHighlighter.documentChanged(LexerEditorHighlighter.java:338)
at com.intellij.openapi.editor.impl.DocumentImpl.changedUpdate(DocumentImpl.java:892)

....

Lexer is not progressing after calling advance()

 

After this all highlighting is out of sync. Reopening the document fixes it. 

I read some things about needing a restartable lexer but couldn't really find anything about that. Is there somewhere an example where this is used?

 

Kr, Tim

3 comments
Comment actions Permalink

I managed to figure out what was going on. The LexerEditorHighlighter  has a loop detection that checks if the lexer is progressing on state, position and token. In my DSL I capture indentation levels by tracking the whitespace and when the first non-whitespace character comes up, returns the Indent/Dedent tokens. While it has to return more tokens it will pushback the non-whitespace character.

This mechanisme will cause the LexerEditorHighlighter to throw the error once identantion levels > 1. 

I could fix it by having the lexer return alternative INDENT/INDENT2 and DEDENT/DENENT2 tokens, however, I wonder if there is a better way to deal with these kind of processes. I can imagine having the INDENT levels being returned as soon as they are discovered, but for the DEDENT I don't have a clue, since there is no actual whitespace to increase the token position on, it reports the lack of whitespace.

Any suggestions on how to improve this mechanisme?

0
Comment actions Permalink

Hello Tim, my DSL is also indention based and I also encountered the same problem.  Here's what I've found in intellij idea CE, hope that'll help:

the official python plugin just implement 2 lexer separately for highlight/parsing. Only when doing highlighting it will check if  the lexer is progressing, so we can just ignore and do not return the empty tokens when doing advance(). And for parsing, all empty/not empty tokens need to be returned to build the correct parsing tree.

source code from IntelliJ CE:

the lexer for parsing: https://github.com/JetBrains/intellij-community/blob/master/python/python-psi-impl/src/com/jetbrains/python/lexer/PythonIndentingLexer.java

the lexer for highlighting: https://github.com/JetBrains/intellij-community/blob/master/python/python-psi-impl/src/com/jetbrains/python/lexer/PythonHighlightingLexer.java

Here's how these lexers registered:

register for parsing: https://github.com/JetBrains/intellij-community/blob/master/python/python-psi-impl/src/com/jetbrains/python/PythonParserDefinition.java#L33

register for highlighting: https://github.com/JetBrains/intellij-community/blob/master/python/src/com/jetbrains/python/highlighting/PyHighlighter.java#L64

 

0
Comment actions Permalink

Hi Xiarui,

thanks for taking the time to leave a comment. I'll have a look at the suggestion, looks promising.

Cheers, Tim

0

Please sign in to leave a comment.