Retrieve Inheritance class full name from Kotlin Psi API

861 views Asked by At

I’m trying to develop a codegen IDEA-Plugin. This plugin should analyze KtClass Inheritance and get all inheritance class full name (like com.example.config.TestConfig)

I have tried to find any useful information by viewing PsiViewer. I find that all inheritance info of KtClass is stored in KtSuperTypeEntry, and I try my best to get full name of inheritance class.

for class Dest:

data class Dest(
    val stringValue: String = "123",
    override val stringConfig: String = "123",
    override val iConfigStr: String = "123",
    val b: B = B(),
    val c: List<List<Set<Map<String, out Any?>>>> = listOf(),
    val config: Config? = Config()
) : Config()
  1. superTypeListEntry.typeAsUserType.referenceExpression.getReferencedName() -return-> "Config"
  2. superTypeListEntry.importReceiverMembers() -return-> null

Seemingly SuperTypeListEntry just contain inheritance class simple name info.

I also try to find inheritance class full name by KtFile, but there is no idea when inheritance class was imported in this KtFile as wildcards:

fun KtSuperTypeListEntry.getType(ktFile: KtFile): String {
    val simpleName = superTypeListEntry.text

    // try to find by declared KtClass ...
    ktFile.children.filterIsInstance<KtClass>().filter { it.name == simpleName }

    // try to find by import ...
    ktFile.importDirectives.filter { it.importPath.toString().contains(simpleName) }

    
    // try to find by import wildcards ...
    ktFile.importDirectives.filter { it.importPath.toString().endWith("*") }.forEach {
        val split = it.importPath.split(".")
        split.set(split.size - 1, simpleName)
        val maybeFullName = split.joinToString(",") { it }
        // confused on how to detect "maybeFullName" is correct ...
    }
}
  • Question

How can I retrieve all inheritance class full name from Kotlin Psi API? Thank you!

1

There are 1 answers

1
ZSpirytus On

After thousand of investigations and debugging, I find that it is possible to find a class's inheritance classes by BindingContext. BindingContext can analyze a TypeReference and find the reference of KotlinType. The code might be like this:

ktClass.superTypeListEntries.map { superTypeEntry ->
    val typeReference = superTypeEntry.typeReference
    val bindingContext = typeReference.analyze()
    bindingContext.get(BindingContext.TYPE, typeReference)
}.forEach { kotlinType ->
    val classId = kotlinType.constructor.declarationDescriptor.classId
    val packageName = classId.packageFqName
    val simpleName = classId.relativeClassName
    // It can also get the generics of this class by KotlinType.arguments
    val generics = kotlinType.arguments
}

Also, you can get super types full name of the class by KtLightClass, the code might be like this:

val ktLightClass = ktClass.toLightClass()
val superTypesFullName = ktLightClass?.supers?.forEach { superType ->
    val packageName = superType.qualifiedName
    val simpleName = superType.name
    // you can get as KtClass by this, which can help you unify design of interface.
    val ktClass = superType.kotlinOrigin
}