Overriding ParserDefinition vs looking up in PSI when needed

Answered

I'm building a plugin for editing YAML files for Home Assistant. In some points (completion contributor, references contributor, documentation provider) I need to identify some precise YAML elements in order to do the right thing. For example, this is a script definition:

script:
   my_super_script:
     description: "Some documentation about the script"
     [...]

This script definition can be referenced ("called" like a function, if you wish) in other files. To identify that particular piece of YAML as a script, I created an element pattern that finds YAMLKeyValues having a “script” parent mapping key.

That is working well and to reuse that I made utility methods so I don't duplicate code. But I do PSI tree traversals everytime I need those.

Then I found YAMLParserDefinition and I thought: what if I extend that class and override the createElement method, inspect the ASTNode (make the same checks I would make in the PSI tree) and create a custom PSI element that wraps YAMLKeyValueImpl? That way, in my contributors/providers I could just do an “instanceof” check on my custom PSI classes (working example of the ParserDefinition here).

So the question is: do I use (and traverse) PSI everytime I need to identify those particular elements when I need it (in the completion contributor, reference, contributor, and so forth) or do I do that once in the ParserDefinition and use custom PSI elements later with a simple “instanceof” check? In terms of performance, which one is more expensive? And which one is the more “architecturally correct”?

Personally I did test both but I couldn't notice a significant difference in performance (we are talking about relatively small files anyway), anyway I wanted to be sure that I am on the right track and not overengineering stuff.

Thanks!

0
3 comments

I noticed one weird thing using the ParserDefinition: the CPU stays 100% constant. If I restart the IDE without the ParserDefinition, CPU usage goes back to normal. createElement() is not called very often though…

0

Hi Daniele,

Extending ParserDefinition looks hacky to me. The standard approach is to traverse PSI when you need it. If computations are expensive, you can cache the values for later use: https://plugins.jetbrains.com/docs/intellij/psi-performance.html#cache-results-of-heavy-computations

1

Thank you Karol, I'll do PSI traversal when needed.

0

Please sign in to leave a comment.