Navigation from usage to declaration for custom language

  I am developing a plugin for a custom language. I am following the tutorial at I followed all the steps in the "Reference Contributor" section to support navigation from usage to declaration of a module in my language(when Ctrl + B) is pressed. The usage and declaration are in different files.
  When I ran the project, on pressing Ctrl + B on a module usage, control did not come to the PsiReferenceProvider.getReferencesByElement. I spent quite some time figuring this out but was not able to make it work. Then I came across another post where it was posted
     "In your custom language, there is usually no need to go through  ReferenceProvidersRegistry to provide references for an element.  Instead, you can put all your logic directly into the getReferences()  method of your PsiElement."

In my case, SimpleNamedElementImpl from is the class from PsiElement where I updated the getReferences() method. That worked and I was able to successfully navigate.

Is this the right way to support navigation? Why didn't the reference contributor work? Is there any other tutorial which goes into this in more detail. It took me a combination of going through the forums, the tutorial mentioned above, the CE source code and some debugging to figure this out. I would appreciate any help. Thanks

Comment actions Permalink

You need to override getReference or getReferences method, because default implementation of getReference in PsiElementBase, which is base class of ASTWrapperPsiElement, returns null, so You cannot resolve references. I found somewhere implementation like this and it is working:

    @NotNull     @Override     public PsiReference[] getReferences() {         return ReferenceProvidersRegistry.getReferencesFromProviders(this, PsiReferenceService.Hints.NO_HINTS);     }     @Nullable     @Override     public PsiReference getReference() {         final PsiReference[] references = getReferences();         if (references.length == 1) {             return references[0];         }         if (references.length > 1) {             return new PsiMultiReference(references, this);         }         return null;     }

Comment actions Permalink

Thanks for the answer.

I had overridden the getReferences method in my PsiBaseElement derived class. I had put all the logic of getting the reference in that. I was not able to figure out how the PsiReferenceContributor code mentioned in the tutorial worked. I replaced the PsiLiteralExpression.class in the example with my PsiElement dervied class and updated the logic in the PsiReferenceProvider. I then update the getReferences method like you have mentioned below. Now the contributor code was called.
It looks like one more level of indirection, so for now I have kept the logic of returing the reference in the getReferences method.

Thanks again for the help


Please sign in to leave a comment.