How to integrate a Java language block/fragment into a custom language plugin

In my custom language plugin, I have tried to integrate support for embedded Java code blocks.

When my lexer encounters a { in reads up to the corresponding } and returns a token of type JavaElementType.CODE_BLOCK. The PSI Structure seems to look good and the Java code location is properly represented under a PsiCodeBlock node. References to variables defined outside the Java code black can be resolved, because I implemented the processDeclarations() method, and the "goto declaration" also works. But there are still some features that don't work:

1) Java code does not get highlighted (no reserved keywords, no literals, ...)

2) Java code completion does not work

3) References to variables defined outside the Java code are marked bad (marked red) with error "Qualifier must be an expression"

Is there any documention about how to get the missing features workng?

Best Regards,

Heiko

12 comments
Comment actions Permalink

Thanks for your reply. I was trying to follow the instructions at the "Custom Language Plugin How to" (http://confluence.jetbrains.net/display/IDEADEV/Developing+Custom+Language+Plugins+for+IntelliJ+IDEA).

"...An important feature which can be implemented at lexer level is mixing languages within a file (for example, embedding fragments of Java code in some template language). If a language supports embedding its fragments in another language, it needs to define the chameleon token types for different types of fragments which can be embedded, and these token types need to implement the ILazyParseableElementType interface..."

Since JavaElementType.CODE_BLOCK is of type ILazyParseableElementType, it seemed like a viable candidate for integrating Java code fragments.

Could you please explain how my PSI Tree should represent the Java code fragment and how I mark this PSI element for language injection and how I could resolve referenced to variables defines outside of the Java code block?

Best Regards,

Heiko

4
Comment actions Permalink

Not sure if it's fully related to that topic but I think that may be helpful for the people implementing Java injection into their plugin's PSI tree:

Java language injection into JFlex

 

2
Comment actions Permalink

Hi Lev. Semantic analysis (as well as additional highlighting and many other things) are usually done through Annotators and Inspections. I didn't check if it possible to apply them to the piece of code with injected language. Also, it looks like observed examples of language injection made by JB in IDEA (like pieces of code in Find Usages popup) don't have that as well. I can only see highlighting provided by Parser, same as in our cases with language injections. So, it might be not possible to do that at all.

The only my suggestion would be to try to find open source plugin, where such functionality implemented, or dive into IDEA source code (hardcore way...) and see if it is principally possible to apply annotators and inspections to injected language.

PS If you find the way how to do that, please write at least short summary here for fellows.

2
Comment actions Permalink

Hi Artsiom. Thank you for a quick answer. I’ve asked this question in a couple of related threads: https://intellij-support.jetbrains.com/hc/en-us/community/posts/206483119-Java-code-Injection-in-custom-language- and https://intellij-support.jetbrains.com/hc/en-us/community/posts/206756905-Inject-code-in-custom-language You can follow those in case someone from JB will answer. Of course, if I’ll figure it out, I’m gonna let everyone know. :)

2
Comment actions Permalink

It's generally better to use language injection, rather than mixing multiple languages in the same PSI tree in the way you do.

1
Comment actions Permalink

Hi!

Artsiom, I’ve implemented your suggestion for my own custom language. Now java is correctly parsed and highlighted. But I’m not able to make Platform do semantic analysis for injected code. For example, if I write ‘return “qwerty”;’ from a void method, it doesn’t highlight it as an error. Nor does it highlight any other errors.
Do you have any ideas how to achieve this?

1
Comment actions Permalink

Is there any information on this question? I'm working on a Drools language plugin and need to be able to support embedded Java in the right hand side of each rule. If JavaElementType.CODE_BLOCK does not work then I'll need to find another way to impliment java fragments.

0
Comment actions Permalink

Someone found a solution? My plugin has very similar thing, and I can not come up with what to do.

P.S. It would be cool to get the source code of  similar plugin.

0
Comment actions Permalink

It is pity, intellij guys have no documentation on this topic except for ‘chameleon tokens’ which are not working. At least in my implementation :)

0
Comment actions Permalink

I've been searching for a solution to the same problem as OP for a few months now, and can't find any project that does this successfully, despite IntelliJ's implementation of the Java language highlighter implementing the correct classes. Lev, were you able to make any progress in this past year?

0
Comment actions Permalink

Hi JJ,
Nope, we suspended development of the plugin for an indefinite time in favor of writing DSL with kotlin typesafe builder. We didn’t give up an idea of writing plugin in some future though. :)

0
Comment actions Permalink

I see - sorry to hear! I appreciate your reply. Hopefully the JetBrains team can provide some guidance soon.

0

Please sign in to leave a comment.