I write an IntelliJ Plugin that performs some checks on Java code.
For one of these checks I need to know the type of a generic field.
Example:
// Model classes B and D
public class B {
void doB() {
}
}
public class D extends B {
void doD() {
}
}
// Classes that use the model classes
public class Base<T extends B> {
protected List<T> list;
private void test() {
list.get(0).doB();
}
}
public class Derived extends Base<D> {
private void test() {
list.get(0).doD();
}
}
The class Base
contains a list with a generic parameter T
which is accessed from class Base
and its derived class Derived
.
I have an annotator (might be changed to LocalInspection) that checks the access to list
in both classes.
This is what I have so far (I left out type- and null-checks for simplicity):
public class GenAnno implements Annotator {
@Override
public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) {
if (element instanceof PsiReferenceExpression) {
PsiReferenceExpression refExpr = (PsiReferenceExpression)element;
PsiElement target = refExpr.resolve();
PsiField field = (PsiField) target;
PsiClassType fieldType = (PsiClassType) field.getType();
PsiClassType itTyp = (PsiClassType) PsiUtil.extractIterableTypeParameter(fieldType, false);
PsiClass cl = itTyp.resolve();
PsiTypeParameter tpara = (PsiTypeParameter) cl;
JvmReferenceType[] refTypes = tpara.getBounds();
}
}
}
I want to get the lowest required type of the generic in context of the usage (the PsiReferenceExpression
). Or regarding my example from above:
- At the access to
list
in classBase
, I want typeB
- At the access to
list
in classDerived
, I want typeD
But I always get PsiType:B
in the variable refTypes
. What do I have to change to get the expected types?
Small background info: I want to check if types, used by reflection, contain the field or method.
You may get the type of
list.get(0)
(i.e likerefExpr.getType()
), it will return theD
PsiTpe.