如何通过Kotlin Psi API获取KtClass继承类的全限定名
解决方案
核心逻辑是不要手动解析导入语句,直接调用Kotlin官方提供的语义解析API,即可直接拿到父类的全限定名,完美覆盖通配符导入、默认导入、别名导入、同包类无需导入等所有场景。
以下是两种可直接使用的实现方案:
方案1:使用Kotlin Analysis API(推荐,适配IDEA 2021.3+)
新版本IDEA推荐使用官方新出的Analysis API,不需要手动管理解析上下文,API更稳定易用:
import org.jetbrains.kotlin.analysis.api.analyze import org.jetbrains.kotlin.analysis.api.symbols.KtClassOrObjectSymbol import org.jetbrains.kotlin.analysis.api.types.KtNonErrorClassType import org.jetbrains.kotlin.psi.KtClass import org.jetbrains.kotlin.psi.KtSuperTypeListEntry fun KtSuperTypeListEntry.getSuperClassQualifiedName(): String? { val typeRef = typeReference ?: return null analyze(typeRef) { // 解析类型引用得到类型对象 val ktType = typeRef.getKtType() as? KtNonErrorClassType ?: return null // 获取类对应的符号 val classSymbol = ktType.classSymbol as? KtClassOrObjectSymbol ?: return null // 返回全限定名 return classSymbol.classId?.asFqNameString() } } // 从KtClass直接批量获取所有父类全限定名的扩展方法 fun KtClass.getAllSuperClassQualifiedNames(): List<String> { return superTypeListEntries.mapNotNull { it.getSuperClassQualifiedName() } }
方案2:使用旧版BindingContext(兼容IDEA 2021.3之前的版本)
如果需要兼容旧版本IDEA,可以使用传统的BindingContext解析方案:
import org.jetbrains.kotlin.psi.KtClass import org.jetbrains.kotlin.psi.KtSuperTypeListEntry import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe fun KtSuperTypeListEntry.getSuperClassQualifiedName(bindingContext: BindingContext): String? { val typeRef = typeReference ?: return null // 从上下文获取类型的解析结果 val type = bindingContext[BindingContext.TYPE, typeRef] ?: return null // 从类型描述符中获取全限定名 return type.constructor.declarationDescriptor?.fqNameSafe?.asString() } fun KtClass.getAllSuperClassQualifiedNames(bindingContext: BindingContext): List<String> { return superTypeListEntries.mapNotNull { it.getSuperClassQualifiedName(bindingContext) } }
说明
两种方案都支持识别Kotlin、Java编写的父类,也能正确处理泛型父类、嵌套类父类等特殊场景,不需要自己处理任何导入相关的逻辑。
内容的提问来源于stack exchange,提问作者ZSpirytus
相关产品推荐
相关产品推荐

