From ef482bb126890c76d63e1e0295b2faec8d400ba1 Mon Sep 17 00:00:00 2001 From: Jaebaek Seo Date: Tue, 21 Jun 2022 20:59:19 +0000 Subject: [PATCH] FIR find usage: correctly set extendsList of FirLightInterfaceClassSymbol The existing code does not set the list of bases that FirLightInterfaceClassSymbol extends for "extendsList". It collects only the set of interfaces for "extendsList" of FirLightInterfaceClassSymbol. However, interfaces can "extend" other classes and/or interfaces, but they cannot "implement" other interfaces. Therefore, we have to includes all interfaces and classes that the child interface extends in the "extendsList". Additionally, this commit adds `private fun PsiClass.hasSuper(..): Boolean` to FirLightClassBase that returns whether one of recursive super classes of the PsiClass is `baseClass` or not. This commit lets `isInheritor()` method use `PsiClass.hasSuper()`. --- .../classes/symbol/classes/FirLightClassBase.kt | 17 ++++++++++++++++- .../classes/FirLightInterfaceClassSymbol.kt | 2 +- .../symbol/classes/firLightClassUtils.kt | 9 ++++++--- .../ExtendingInterfaceWithDefaultImpls.fir.java | 2 +- 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/FirLightClassBase.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/FirLightClassBase.kt index 5eed3830c48..6d696c1d34f 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/FirLightClassBase.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/FirLightClassBase.kt @@ -22,6 +22,8 @@ import org.jetbrains.kotlin.analysis.api.KtAllowAnalysisOnEdt import org.jetbrains.kotlin.analysis.api.KtAnalysisSession import org.jetbrains.kotlin.analysis.api.lifetime.allowAnalysisOnEdt import org.jetbrains.kotlin.analysis.providers.createProjectWideOutOfBlockModificationTracker +import org.jetbrains.kotlin.analysis.api.symbols.KtClassOrObjectSymbol +import org.jetbrains.kotlin.analysis.api.types.KtType import org.jetbrains.kotlin.asJava.classes.* import org.jetbrains.kotlin.idea.KotlinLanguage import org.jetbrains.kotlin.light.classes.symbol.classes.checkIsInheritor @@ -104,10 +106,23 @@ abstract class FirLightClassBase protected constructor( return if (baseClassOrigin != null && thisClassOrigin != null) { thisClassOrigin.checkIsInheritor(baseClassOrigin, checkDeep) } else { - InheritanceImplUtil.isInheritor(this, baseClass, checkDeep) + hasSuper(baseClass, checkDeep) || + InheritanceImplUtil.isInheritor(this, baseClass, checkDeep) } } + private fun PsiClass.hasSuper( + baseClass: PsiClass, + checkDeep: Boolean, + visitedSupers: MutableSet = mutableSetOf() + ): Boolean { + visitedSupers.add(this) + val notVisitedSupers = supers.filterNot { visitedSupers.contains(it) } + if (notVisitedSupers.any { it == baseClass }) return true + if (!checkDeep) return false + return notVisitedSupers.any { it.hasSuper(baseClass, true, visitedSupers) } + } + override fun getText(): String = kotlinOrigin?.text ?: "" override fun getLanguage(): KotlinLanguage = KotlinLanguage.INSTANCE diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/FirLightInterfaceClassSymbol.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/FirLightInterfaceClassSymbol.kt index 30db7f4e095..2c000830ea9 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/FirLightInterfaceClassSymbol.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/FirLightInterfaceClassSymbol.kt @@ -64,7 +64,7 @@ internal open class FirLightInterfaceClassSymbol( FirLightInterfaceClassSymbol(classOrObjectSymbol, manager) private val _extendsList: PsiReferenceList by lazyPub { - createInheritanceList(forExtendsList = false, classOrObjectSymbol.superTypes) + createInheritanceList(forExtendsList = true, classOrObjectSymbol.superTypes) } override fun getExtendsList(): PsiReferenceList? = _extendsList diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/firLightClassUtils.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/firLightClassUtils.kt index 2e202e4bb2f..65fcbc1e05b 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/firLightClassUtils.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/firLightClassUtils.kt @@ -398,10 +398,13 @@ context(KtAnalysisSession) // We don't have Enum among enums supertype in sources neither we do for decompiled class-files and light-classes if (isEnum && this.classId == StandardClassIds.Enum) return false - val isInterfaceType = - (this.classSymbol as? KtClassOrObjectSymbol)?.classKind == KtClassKind.INTERFACE + // Interfaces have only extends lists + if (isInterface) return forExtendsList - return forExtendsList == !isInterfaceType + val classKind = (classSymbol as? KtClassOrObjectSymbol)?.classKind + val isJvmInterface = classKind == KtClassKind.INTERFACE || classKind == KtClassKind.ANNOTATION_CLASS + + return forExtendsList == !isJvmInterface } //TODO Add support for kotlin.collections. diff --git a/compiler/testData/asJava/lightClasses/ExtendingInterfaceWithDefaultImpls.fir.java b/compiler/testData/asJava/lightClasses/ExtendingInterfaceWithDefaultImpls.fir.java index ec5c0ee2dd8..3ede4b52513 100644 --- a/compiler/testData/asJava/lightClasses/ExtendingInterfaceWithDefaultImpls.fir.java +++ b/compiler/testData/asJava/lightClasses/ExtendingInterfaceWithDefaultImpls.fir.java @@ -3,7 +3,7 @@ public abstract interface C /* p.C*/ extends p.B { public abstract java.lang.String c();// c() -public static final class DefaultImpls /* p.C.DefaultImpls*/ extends p.B { +public static final class DefaultImpls /* p.C.DefaultImpls*/ { @org.jetbrains.annotations.NotNull() public java.lang.String c();// c()