PsiReference: PsiElement.getReference vs. ReferenceProviderRegistry

I'm trying to get a custom language plugin working (for version 7, I'll switch it to 8 later), and I don't know how to get references happening. As a specific example, if I have this code:

(def add (x y)
(+ x y))

...it parses (correctly) into this PSI tree (these are custom PsiElement classes):

PsiFile
....Def
........VariableDefinition (add)
........ParameterList
............VariableDefinition (x)
............VariableDefinition (y)
........Body
............Expression
................VariableReference (x)
................VariableReference (y)

I'd like to be able to nav from variable reference 'x', via "Go to... Declaration", but I'm not sure how to make this happen. The (rather old) documentation indicates that I just need to implement "getReference" in my PsiElement classes, but some of the threads in this forum talk about using the ReferenceProviderRegistry.

Any advice on how I can get this working would be greatly appreciated.

Thanks for your help,
Kurt Christensen

5 comments
Comment actions Permalink

Hello Kurt,

I'm trying to get a custom language plugin working (for version 7,
I'll switch it to 8 later), and I don't know how to get references
happening. As a specific example, if I have this code:

(def add (x y)
(+ x y))
..it parses (correctly) into this PSI tree (these are custom
PsiElement classes):

PsiFile
...Def
.......VariableDefinition (add)
.......ParameterList
...........VariableDefinition (x)
...........VariableDefinition (y)
.......Body
...........Expression
...............VariableReference (x)
...............VariableReference (y)
I'd like to be able to nav from variable reference 'x', via "Go to...
Declaration", but I'm not sure how to make this happen. The (rather
old) documentation indicates that I just need to implement
"getReference" in my PsiElement classes, but some of the threads in
this forum talk about using the ReferenceProviderRegistry.

Any advice on how I can get this working would be greatly appreciated.


ReferenceProviderRegistry is used to inject additional references into standard
Java PSI elements (comments, string literals and so on). For your own language,
PsiElement.getReference() is still the right thing to implement.

--
Dmitry Jemerov
Development Lead
JetBrains, Inc.
http://www.jetbrains.com/
"Develop with Pleasure!"


0
Comment actions Permalink

Hi Dmitry,

Thank you very much for your help. Forgive my ignorance, but I'm still having difficulties. Continuing with the previous example, I implemented "getReference" for the "VariableReference" element, but those elements still don't navigate to their declarations. Could you please point out anything obvious I'm doing wrong?

public class VariableReference extends ArcElement {
....public VariableReference(@NotNull final ASTNode node) {
........super(node);
....}
....public PsiReference getReference() {
........return new PsiReferenceBase]]>(this) {
............public PsiElement resolve() {
................return walkTree(myElement);
............}
............private PsiElement walkTree(PsiElement element)
................PsiElement parent = element.getParent();
................if (parent == null) { return null; }
................if (parent instanceof Def || parent instanceof Mac) {
....................PsiNamedElement p = (PsiNamedElement) parent;
....................ParameterList params = PsiTreeUtil.getChildOfType(p, ParameterList.class);
....................if (params != null) {
........................for (PsiElement param : params.getChildren()) {
............................if (param instanceof VariableDefinition) {
................................VariableDefinition varDef = (VariableDefinition) param;
................................if (varDef.getName().equals(myElement.getText())) {
....................................return varDef;
................................}}}}}
................return walkTree(parent);
............}
............public Object[] getVariants() { return new Object[0]; }
........};
....}
}

Thanks again for your help,
Kurt Christensen

0
Comment actions Permalink

Arc plugin? Sounds great!

0
Comment actions Permalink

Thanks for the encouragement! I love IntelliJ so much, I just did not want to switch to emacs to play with Arc. And so here I am. The plugin still needs a lot of work, but it's usable.

By the way, I found the answer to my question on a different thread - overriding PsiReferenceBase.getRangeInElement made everything work. Thanks for your help!

0

Please sign in to leave a comment.