kotlin - 从 Kotlin Psi API 检索继承类全名
问题描述
我正在尝试开发一个 codegen IDEA-Plugin。这个插件应该分析KtClass
Inheritance 并获取所有继承类的全名(如 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()
- superTypeListEntry.typeAsUserType.referenceExpression.getReferencedName() -return->
"Config"
- 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 检索所有继承类全名?谢谢!
解决方案
经过千方百计的排查和调试,我发现通过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
}
推荐阅读
- scala - Spark:基于列值的行过滤器
- android - 如何创建两个相邻的实体的图层列表?
- node.js - 如何让 axios 在 API 调用之间维护 cookie/会话?
- perl - 在 foreach 中将 undef 变量提升为 ARRAY ref
- c# - MS Dynamics - 使用 ConditionOperator.In 的 QueryExpression 没有结果,但可以使用 ConditionOperator.Equal
- angular - 如何有条件地使用 router.navigate 进行导航?
- ios - Apple Mach-O 链接器警告,在 xcode 9.4 中
- winapi - 按 Esc 关闭任务对话框
- python - 在没有通信()阻塞行为的情况下写入 Python 子进程的标准输入
- python - 整个程序打字效果