Annotator not visit parent element if syntax error happens

Answered

I'm now having two annotators, one for highlight syntax errors, and one for highlight the keywords. But the keywords annotator is not working if syntax error happens. 

Then I did some debug, it turns out that the GeneralHighlightingPass#runVisitors with parameter “skipParentsSet” just skiped the parents highlighting behavior. Which are not visited  in the keywords annotator.

I've tried to register the HighlightRangeExtension and return true in the isForceHighlightParents method, that worked eventually. But since you have noticed that returning true may decrease highlighting performance/increase latency, I was wondering is there any suggestions for a more official way to achive this?

Any way, this is how it looks like in my plugin:

 

my bnf file:

Namespace ::= 'namespace' LanguageType (IDENTIFIER | StringValue) {
  pin = 1
}

and this is how I annotate the elements:

@Override
    public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) {
        if (element instanceof Namespace) {
            holder.newSilentAnnotation(HighlightInfoType.SYMBOL_TYPE_SEVERITY)
                    .textAttributes(BjscSyntaxHighlighter.KEYWORD)
                    .range(element.getFirstChild().getTextRange())
                    .create();
        }
    }

I mentioned the same problem here: Missing highlight when multiple annotators applied to same TextRange? – IDEs Support (IntelliJ Platform) | JetBrains, but seems that's not the same reason.

waiting for your reply, thanks.

0
4 comments

Hi,

I don't understand why you highlight the namespace keyword with Annotator. Syntax highlighting is usually implemented via Syntax Highlighter:

https://plugins.jetbrains.com/docs/intellij/syntax-highlighter-and-color-settings-page.html

I suggest implementing this approach and defining color for keywords.

0

In my language, “namespace" is not only a keyword, but also an identifier. So if I use syntax highlighter to highlight it, I should define it as a token in .flex file:

"namespace"         { return NAMESPACE; }

this will make every "namespace" highlighted, and that's not I'm expected. For example:

May be I misunderstanding something?

0

I see now. If it is possible in your lexer to distinguish between these two cases, I think your PSI would be easier and the issue wouldn't exist.

Yes, you should define something like:

"namespace"         { return NAMESPACE; }

but you should accept it as NAMESPACE only if it is the actual “namespace” keyword. If a “namespace” identifier can be only defined inside a class or other similar entity, or just at the beginning of files, you can use a helper flag, e.g.:

// in the .flex file:
%{
  ...
  private boolean namespacesFinished = false;
  ...
%}

// I assume when "class" is accepted, then any "namespace" will be an identifier

"class"     { namespacesFinished = true; return CLASS; } 
"namespace" { return namespacesFinished ? IDENTIFIER : NAMESPACE; }

 

0

That really helped a lot, thank you so much!

But there is still one more thing that confuse me a lot. It's quite similar. As you can see, I can define some fields in class body, but just like the problem above, "string" can be used as both keyword and identifier.  I can't define this in my .flex file cause I don't know when I should set the helperFlag to true.

<YYINITIAL> "string"  { return helperFlag ? IDENTIFIER : STRING; }

Which means, I can't define like below, because this will always return IDENTIFIER:

<YYINITIAL> "string"  { helperFlag = true; return helperFlag ? IDENTIFIER : STRING; }

Also this will not work cause all string will highlight the same way because the are inside the class body

"class"     { helperFlag = true; return CLASS; } 
"string"    { return helperFlag ? IDENTIFIER : STRING; }
0

Please sign in to leave a comment.