从 Kotlin Psi API 检索继承类全名
Posted
技术标签:
【中文标题】从 Kotlin Psi API 检索继承类全名【英文标题】:Retrieve Inheritance class full name from Kotlin Psi API 【发布时间】:2021-11-05 18:12:19 【问题描述】:我正在尝试开发一个 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 检索所有继承类全名?谢谢!
【问题讨论】:
【参考方案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
【讨论】:
以上是关于从 Kotlin Psi API 检索继承类全名的主要内容,如果未能解决你的问题,请参考以下文章
如何通过 Java/Kotlin API 从 KeyCloak 请求 JWT 令牌