How to get generic type of PsiField?

171 Views Asked by At

Making an IDEA Plugin and stuck with this thing. Here is the class I have:

open class Class1<A, B : Class2> {
    open var value1: Map<String, A>? = null
    open var value2: Map<String, B> = emptyMap()
}

In my plugin I need to know somehow the real types of variables value1 and value2 Is that possible with PSI library?

So I have PsiClassReferenceType object, it's canonicalText method returns java.util.Map<java.lang.String,? extends B>.

psiType.reference.typeParameters returns two parameters:

  1. PsiClassReferenceType - this is for String parameter
  2. PsiWildcardType - this is for generic value parameter (having canonicalText as ? extends B)

Also tried to use PsiUtil.resolveGenericsClassInType(psiType).substitutor.substitutionMap, but this still brings me ? extends B and nothing more.

Any suggestions of how to get actual type parameter (which im my case is Class2)?

2

There are 2 best solutions below

0
On BEST ANSWER

Had to admit that there is no way to achieve desired result by just a couple of utility methods. So the best way I can find is to get the type parameters of the field and then parse class name to extract real types by the names of generics.

1
On

To get the actual type parameters of value1 and value2 in your IDEA Plugin using the PSI library, you can follow these steps:

1.Find the PsiField representing value1 or value2.

2.Retrieve the PsiType of the field using PsiField.getType().

Once you have the PsiType, you can extract the actual type parameters. Here's an example of how to do this:

    PsiField field = // Retrieve your PsiField here
    PsiType fieldType = field.getType();
    
    if (fieldType instanceof PsiClassReferenceType) {
        PsiClassReferenceType classReferenceType = (PsiClassReferenceType) fieldType;

    // Get the type parameters
    PsiType[] typeParameters = classReferenceType.getParameters();

    // Check if the type has parameters
    if (typeParameters.length >= 1) {
        PsiType firstTypeParameter = typeParameters[0]; // This is your "A" or "B" type parameter
        String canonicalText = firstTypeParameter.getCanonicalText();
        // Now, you can work with the canonical text to extract the actual type information.
    }
}

This code snippet checks if the field's type is a PsiClassReferenceType, which is typically the case for generic types. It then retrieves the type parameters and processes them to extract the actual type information.

Keep in mind that handling generics and type parameters can be complex, especially if there are multiple levels of generic types involved. You may need to recursively traverse the type hierarchy to obtain the most specific type information.