PsiNamedElement vs PsiNameIdentifierOwner
So, the doc says: "Every element which can be renamed or referenced needs to implement com.intellij.psi.PsiNamedElement interface." and then demonstrates by using PsiNameIdentifierOwner not PsiNamedElement. What's the deal? Typo?
10.1. Define a base named element classhttp://www.jetbrains.org/intellij/sdk/docs/tutorials/custom_language_support/reference_contributor.html#define-a-base-named-element-class
package com.simpleplugin.psi; import com.intellij.psi.PsiNameIdentifierOwner; public interface SimpleNamedElement extends PsiNameIdentifierOwner { }
My jump to declaration and find usages seems to work with plain PsiNamedElement. What functionality relies on the PsiNameIdentifierOwner subinterface?
thanks!
Ter
Please sign in to leave a comment.
We use it to differentiate between declarations and variable names. You could directly use
, but is more specific, and tells us exactly which token is the name identifier. For example, finding usages (in particular those inside ), reveals or , which guard additional functionality within an check. If you use for renaming it will be "clunkier" - you'll get a dialog because we're not quite sure what token we're supposed to rename:Where it gets tricky is when you have matching types and variables like "": the whole statement could be a , but which "x" is supposed to be the identifier? Using helps clarify this ambiguity. uses it indirectly. uses it. uses it. uses it. If you don't explicitly tell us what the name identifier is, we might try to find it by other means, but we might not always get it right or it might not be as user-friendly for certain actions.
Hi Breandan,Thanks very much for the helpful response. I definitely get the idea that there are references and there are definitions or declarations. I just couldn't figure out what functionality triggered the use of the PsiNameIdentifierOwner interface. Your pointers help a lot. I will dig into it. A small clarification as I'm not sure which nodes should be tagged exactly.
What I do now is tag my ID leaf nodes as PsiNamedElement but my variable definition subtree roots (nonleaf PSI nodes) as PsiNameIdentifierOwner. In other words, PsiNameIdentifierOwner points at the root of an entire definition statement rather than the individual ID node within that subtree. I then have getNameIdentifier() return that ID child. Does that sound correct?
Thanks!
Terence
, but you might just as likely store a reference to it somewhere. Here's what the PSI Structure looks like, see how (the ) is the entire definition statement and the name identifier is the actual leaf node:Yep, that sounds right. If you look in the SDK docs under /code-samples/simple-language-plugin there is an example of this (generated by grammar-kit from the BNF). It delegates to a static method that maps to
Ok, great! And then do I ever want the PsiNamedElement for the KEY under a PsiNameIdentifierOwner to return a ref from getReference() or is that literally only for references to a definition? That could be the answer to my question I just posed in another thread where rename is happening twice, once via the reference and once via a simple setName on the definition name node that should be changed.
Ter
For my little "func f() { }" input, I get a spinning ball of death when I avoid creating a reference from the definition ID node. Just like I did in
https://devnet.jetbrains.com/message/5566463#5566463
So, I no longer create a PsiReferenceBase for the "f" node. getReference() returns null. Rename locks the GUI thread. awesome. my setName() could not be simpler:
where that createLeaf... func is just:
return PsiTreeUtil.getDeepestFirst(el); // forces parsing of file!!
It seems to create a proper new node but then after the "finding usage" dialogue comes up it freezes after the progress bar goes all the way and it hits my setName method.
The spinning ball of death seems to be a recurring theme for me. Looking at the threads in the debugger shows everybody is just parked so I have no idea what is deadlocking it.
hope this extra bit of data helps. Does my setName() look ok?
Thanks,
Ter