【问题标题】:Retrieve Inheritance class full name from Kotlin Psi API从 Kotlin Psi API 检索继承类全名
【发布时间】:2021-11-05 18:12:19
【问题描述】:

我正在尝试开发一个 codegen IDEA-Plugin。这个插件应该分析KtClassInheritance并获取所有继承类全名(如com.example.config.TestConfig)

我试图通过查看 PsiViewer 找到任何有用的信息。我发现所有 KtClass的继承信息存放在KtSuperTypeEntry,我尽量得到继承类的全名。

类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

貌似 SuperTypeListEntry 只包含继承类简单名称信息。

我也尝试通过KtFile查找继承类全名,但是不知道这个KtFile中的继承类是什么时候作为通配符导入的:

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 ...
    }
}
  • 问题

如何从 Kotlin Psi API 检索所有继承类全名?谢谢!

【问题讨论】:

    标签: kotlin compiler-construction intellij-plugin psi


    【解决方案1】:

    千方百计的排查调试,发现通过BindingContext可以找到一个类的继承类。 BindingContext 可以分析一个 TypeReference 并找到KotlinType 的引用。代码可能是这样的:

    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
    }
    

    另外,你可以通过KtLightClass获取类的超类型全名,代码可能是这样的:

    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
    }
    

    【讨论】:

      猜你喜欢
      • 2020-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多