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()`.
This commit is contained in:
Jaebaek Seo
2022-06-21 20:59:19 +00:00
committed by Ilya Kirillov
parent 21f65b2fe3
commit ef482bb126
4 changed files with 24 additions and 6 deletions
@@ -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<PsiClass> = mutableSetOf<PsiClass>()
): 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
@@ -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
@@ -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.
@@ -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()