YamlPlainTextImpl not a named element

Answered

I'm extending the bundled YAML language for a custom language. For this we use the concept of variables that are declared in one part of the file and which can be used in another:

variables:
- variableA <-- declaring element (YamlPlainTextImpl)

someOtherSegment: variableA <-- usage (YamlPlainTextImpl)

I can use the PsiReferenceContributor to create a reference on the usage element. However, to make use of things like find-usage and certain refactoring tools (rename, safe-delete), the declaring element should implement PsiNamedElement/PsiNameIdentifierOwner, if I'm not mistaken. 

What would be the best approach to do this?

I currently have a very ugly workaround where I implement a ParserDefinition that extends the YamlParserDefinition with a 'first' priority that specifically checks for a SCALAR_PLAIN_VALUE node to be parsed, and then provides an instance of a custom extension of the YamlPlainTextImpl which does implement PsiNamedElement. This works but I'm trying to get rid of this workaround, so hopefully there is another solution, or you could implement PsiNamedElement on YamlPlainTextImpl also.

0
4 comments

Hi Tim,

Take a look at com.intellij.psi.ElementManipulator registered in lang.elementManipulator extension point.

0

Hi Karol,

Am I correct that this would be helpful for the refactor-rename process?
I don't see how I can make the YamlPlainTextImpl a PsiNamedElement implementation this way? Also, this manipulator appears to react mainly on content changes.

With the solution I have now that 'swaps' the element with an extended version at PsiElement construction I can very easily implement all refactor methods, findUsage, usageScope etc. It would not really be a good trade-off to have a bunch of additional classes that do this via other extensions.

I probably should have formulated my question a bit better: Is there a different way to either swap or wrap a PsiElement with an extension of that specific PsiElement class (i.e. YamlPlainTextImpl -> MyCstomYamlPlainTextIImpl extends YamlPlainTextImpl), other than I have implemented right now?

0

Hi Tim,

I misunderstood your case.

The existing language parsers should never be overridden or hacked.

I've found a similar case (also for YAML and from Tim, isn't it a Matrix error? 🙂). Please take a look:
https://intellij-support.jetbrains.com/hc/en-us/community/posts/4411105229202-Rename-FindUsage-for-adhoc-declaration?page=1

0

Hi Karol,

that was me also :) I implemented all those things but still didn't really get the behavior I wanted which I why I tried replacing it with the parsers which does work and I haven't had any instability issues.

In any case, I'll try to explore that solution again although I find it a bit hard to maintain when I need to implement so many providers and handlers compared to having all the behavior needly in the PsiElement itself, but I guess that's the trade-off for extending a language and not owning it completely.

Another reason why I really would to implement PsiNamedElement is for the unit-test fixture.getElementAtCaret() which requires the caret to either be placed at a PsiNamedElement or be able to resolve to it. The findElementWithText alternative is more cumbersome in my opinion.

0

Please sign in to leave a comment.