My PsiReference's resolve() method is not called?

I'm developing a(nother) plugin for a custom language that describes
communication message structure. For example:

message Stuff {
int index;
string name;
<java.util.Map> attributes;
}

As you can see, some message fields can have a type which is an
arbitrary Java class. I would like to make that a reference to the class
for navigation and error checking purposes.

The PsiElement implementation that I create for the text "java.util.Map"
in the above example also implements PsiReference and returns 'this'
from getReference(). I've checked with the debugger and getReference()
is called, but resolve() is never called.

What am I doing wrong?

Thanks,
Gordon

=======================================================================
public class PMFQCNImpl extends PMElementImpl implements PsiReference {

public PMFQCNImpl(ASTNode astNode) {
super(astNode);
}

@Override
public String toString() {
return "FQCN: " + getText();
}

@Override
public PsiReference getReference() {
return this;
}

public PsiElement getElement() {
return this;
}

public TextRange getRangeInElement() {
return getTextRange();
}

@Nullable
public PsiElement resolve() {
return getManager().getResolveHelper().
resolveReferencedClass(getText(), this);
}

public String getCanonicalText() {
return getText();
}

public PsiElement handleElementRename(String newElementName)
throws IncorrectOperationException {
// TODO: Implement this method
throw new IncorrectOperationException();
}

public PsiElement bindToElement(PsiElement element)
throws IncorrectOperationException {
// TODO: Implement this method
throw new IncorrectOperationException();
}

public boolean isReferenceTo(PsiElement element) {
return resolve() == element;
}

public Object[] getVariants() {
// TODO: Implement this method
return new Object[0];
}

public boolean isSoft() {
return false;
}

}

--
Gordon Tyler (Software Developer)
Quest Software <http://www.quest.com/>
260 King Street East, Toronto, Ontario M5A 4L5, Canada
Voice: (416) 933-5046 | Fax: (416) 933-5001

3 comments
Comment actions Permalink

Gordon Tyler wrote:

What am I doing wrong?


I bet it's your implementation of getRangeInElement():

public TextRange getRangeInElement() {
return getTextRange();
}


This is supposed to return a TextRange that is relative to the one of the element that is
returned by getElement(). In your case, assuming the angle brackets are not part of the
element, this is TextRange.from(0, getTextLength()).

A good way to see if this method is implemented properly is to check by hovering the mouse
with the Ctrl-key pressed over the place the reference is supposed to be at. IDEA will
underline the reference's text range, making it possible to easily spot one-off errors in
the calculation. If there's no underlining effect in the area at all, the calculation is
probably totally off ;)

Sascha

0
Comment actions Permalink

I think your implementation of getTextRangeInElement is wrong.
PsiElement.getTextRange returns an absolute text range relative to the start of
the file. getTextRangeInElement should return a range relative to the element.
In your case, the correct range is probably TextRange.getInstance(0,
getTextRange().getLength()).

Gordon Tyler wrote:

I'm developing a(nother) plugin for a custom language that describes
communication message structure. For example:

message Stuff {
int index;
string name;
<java.util.Map> attributes;
}

As you can see, some message fields can have a type which is an
arbitrary Java class. I would like to make that a reference to the class
for navigation and error checking purposes.

The PsiElement implementation that I create for the text "java.util.Map"
in the above example also implements PsiReference and returns 'this'
from getReference(). I've checked with the debugger and getReference()
is called, but resolve() is never called.

What am I doing wrong?

Thanks,
Gordon

=======================================================================
public class PMFQCNImpl extends PMElementImpl implements PsiReference {

public PMFQCNImpl(ASTNode astNode) {
super(astNode);
}

@Override
public String toString() {
return "FQCN: " + getText();
}

@Override
public PsiReference getReference() {
return this;
}

public PsiElement getElement() {
return this;
}

public TextRange getRangeInElement() {
return getTextRange();
}

@Nullable
public PsiElement resolve() {
return getManager().getResolveHelper().
resolveReferencedClass(getText(), this);
}

public String getCanonicalText() {
return getText();
}

public PsiElement handleElementRename(String newElementName)
throws IncorrectOperationException {
// TODO: Implement this method
throw new IncorrectOperationException();
}

public PsiElement bindToElement(PsiElement element)
throws IncorrectOperationException {
// TODO: Implement this method
throw new IncorrectOperationException();
}

public boolean isReferenceTo(PsiElement element) {
return resolve() == element;
}

public Object[] getVariants() {
// TODO: Implement this method
return new Object[0];
}

public boolean isSoft() {
return false;
}

}

0
Comment actions Permalink

Nevermind, I realised what the problem is. getRangeInElement() must
return a RELATIVE TextRange.

Ciao,
Gordon

--
Gordon Tyler (Software Developer)
Quest Software <http://www.quest.com/>
260 King Street East, Toronto, Ontario M5A 4L5, Canada
Voice: (416) 933-5046 | Fax: (416) 933-5001

0

Please sign in to leave a comment.