getRangeInElement for PsiReference in comments

Hi Community,

I would like to implement the getRangeInElement Method of the PsiReference properly.
The problem is that the Reference is a Java Comment but it seems that comments can't be underlined, so no reference is found.

If I set the TextRange to something which can be underlined, like a variable or a classname, it works correctly.

I tried different ways but none helped.

Is it possible to set the TextRange of the reference element on a Java Comment?

Thanks in advance,
Markus

7 comments
Comment actions Permalink

I'm not sure I understansd your question. The getRangeInElement() method returns a relative range within the element where the text corresponding to your reference is found; it's difficult to implement it "properly" or "improperly".

If your problem is that "Find usages" for the target element does not find references in comments, then it can't be solved by changing the implementation of getRangeInElement(). What you need is a searcher implementation that plugs into the referencesSearch extension point and finds the necessary text in comment context. Specifically, you need to call queryParameters.getOptimizer().searchWord() with UsageSearchContext.IN_COMMENTS as the value of the second parameter.

0
Comment actions Permalink

Thank you for your reply.

I implemented PsiReference.getRangeInElement() in two ways. First one is returning the correct TextRange for the element, second one is a TextRange from 1 to eof. The resulting behavior can be seen on the two pictures I attached.

So the correct TextRange should underline the target element and resolve the reference, but this does not happen.

I hope this helps to understand my problem.

Markus



Attachment(s):
complete_Textrange.png
correct_Textrange.png
0
Comment actions Permalink

This method returns a relative range. The correct text range for an element is 0 to element.getTextLength()-1.

0
Comment actions Permalink

That is exactly what I implemented in the first try and is the complete_TextRange picture

0
Comment actions Permalink

@Override
public void registerReferenceProviders(final PsiReferenceRegistrar registrar) {
    PsiReferenceProvider psiReferenceProvider = new PsiReferenceProvider() {
        @NotNull
        @Override
        public
PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) {
            String text = element.getText();
            PsiReference[] result = new PsiReference[1];

            if (text != null && text.contains("link/:") && text.contains(".") && text.contains(":/")) {
                int startIndex = text.indexOf("/:") + 2;
                int endIndex = text.lastIndexOf(":/");

                String className = text.substring(startIndex, endIndex);

                PsiClass psiClass = JavaPsiFacade.getInstance(element.getProject()).findClass(className, GlobalSearchScope.allScope(element.getProject()));
                TextRange textRange = new TextRange(0, element.getTextLength() - 1);

                if (psiClass != null) {
                    result[0] = new PCPReference(psiClass, textRange);
                }
            }
            return result;
        }
    };

    registrar.registerReferenceProvider(PlatformPatterns.psiComment(), psiReferenceProvider);


public class PCPReference implements PsiReference {
    private PsiClass referenceElement;
    private TextRange textRange;

    public PCPReference(PsiClass psiElement, TextRange textRange) {
        referenceElement = psiElement;
        this.textRange = textRange;
    }

    @Override
    public
PsiElement getElement() {
        return referenceElement;
    }

    @Override
    public
TextRange getRangeInElement() {
        return textRange;
    }
...


This is the implementation I have done so far

0
Comment actions Permalink

So what you're doing here is finding a PsiClass by qualified name (which is very likely located in a different file) and retuning it as the element to which the reference is attached. IntelliJ IDEA kind of does what you ask it to, and highlights the TextRange that you return relative to the range of the PsiClass in your current file, which leads to the broken behavior that you observe.

The getElement() and getRangeInElement() methods need to return the element to which the refererence is attached, not the element that the reference resolves to. The latter is returned from PsiReference.resolve().

On a related note, it's not OK to return an array containing null elements from your getReferencesByElement() implementation. If you don't have any references, return an empty array.

0
Comment actions Permalink

Thank you very much Dmitry, Now I got it and
it works.

Kind regards,
Markus

0

Please sign in to leave a comment.