[FIR IDE] Implement isInheritor for FirLightClassForClassOrObjectSymbol

This commit is contained in:
Igor Yakovlev
2021-01-28 22:30:51 +03:00
parent 56db4bd1ac
commit e529a7bf9b
3 changed files with 37 additions and 27 deletions
@@ -13,10 +13,10 @@ import com.intellij.psi.search.SearchScope
import com.intellij.psi.stubs.IStubElementType
import com.intellij.psi.stubs.StubElement
import org.jetbrains.annotations.NonNls
import org.jetbrains.kotlin.asJava.classes.getOutermostClassOrObject
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.classes.*
import org.jetbrains.kotlin.asJava.elements.FirLightIdentifier
import org.jetbrains.kotlin.asJava.elements.KtLightField
import org.jetbrains.kotlin.idea.asJava.classes.checkIsInheritor
import org.jetbrains.kotlin.idea.asJava.classes.getOrCreateFirLightClass
import org.jetbrains.kotlin.idea.asJava.elements.FirLightTypeParameterListForSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
@@ -131,9 +131,19 @@ internal abstract class FirLightClassForClassOrObjectSymbol(
override fun isValid(): Boolean = kotlinOrigin?.isValid ?: true
//TODO: Implement inheritance check via symbols
override fun isInheritor(baseClass: PsiClass, checkDeep: Boolean): Boolean =
InheritanceImplUtil.isInheritor(this, baseClass, checkDeep)
override fun isInheritor(baseClass: PsiClass, checkDeep: Boolean): Boolean {
if (manager.areElementsEquivalent(baseClass, this)) return false
LightClassInheritanceHelper.getService(project).isInheritor(this, baseClass, checkDeep).ifSure { return it }
val thisClassOrigin = kotlinOrigin
val baseClassOrigin = (baseClass as? KtLightClass)?.kotlinOrigin
return if (baseClassOrigin != null && thisClassOrigin != null) {
thisClassOrigin.checkIsInheritor(baseClassOrigin, checkDeep)
} else {
InheritanceImplUtil.isInheritor(this, baseClass, checkDeep)
}
}
override fun toString() =
"${this::class.java.simpleName}:${kotlinOrigin?.getDebugText()}"
@@ -9,8 +9,8 @@ import com.intellij.psi.PsiClass
import org.jetbrains.kotlin.asJava.classes.KtFakeLightClass
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.classes.LightClassInheritanceHelper
import org.jetbrains.kotlin.idea.asJava.classes.checkIsInheritor
import org.jetbrains.kotlin.idea.frontend.api.HackToForceAllowRunningAnalyzeOnEDT
import org.jetbrains.kotlin.idea.frontend.api.analyze
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
@@ -32,21 +32,6 @@ class KtFirBasedFakeLightClass(kotlinOrigin: KtClassOrObject) :
LightClassInheritanceHelper.getService(project).isInheritor(this, baseClass, checkDeep).ifSure { return it }
val baseClassOrigin = (baseClass as? KtLightClass)?.kotlinOrigin ?: return false
return analyze(kotlinOrigin) {
val thisSymbol = kotlinOrigin.getClassOrObjectSymbol()
val baseSymbol = baseClassOrigin.getClassOrObjectSymbol()
if (thisSymbol == baseSymbol) return@analyze false
val baseType = baseSymbol.buildTypeForSymbol()
if (checkDeep) {
thisSymbol.buildTypeForSymbol().isSubTypeOf(baseType)
} else {
thisSymbol.superTypes.any { baseType.isEqualTo(it.type) }
}
}
return kotlinOrigin.checkIsInheritor(baseClassOrigin, checkDeep)
}
}
@@ -10,10 +10,7 @@ import com.intellij.psi.PsiReferenceList
import com.intellij.psi.util.CachedValueProvider
import com.intellij.psi.util.CachedValuesManager
import org.jetbrains.kotlin.analyzer.KotlinModificationTrackerService
import org.jetbrains.kotlin.asJava.classes.KotlinSuperTypeListBuilder
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.classes.METHOD_INDEX_BASE
import org.jetbrains.kotlin.asJava.classes.shouldNotBeVisibleAsLightClass
import org.jetbrains.kotlin.asJava.classes.*
import org.jetbrains.kotlin.asJava.elements.KtLightField
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
@@ -330,4 +327,22 @@ internal fun KtSymbolWithMembers.createInnerClasses(manager: PsiManager): List<F
// result.add(KtLightClassForInterfaceDefaultImpls(classOrObject))
//}
return result
}
}
@OptIn(HackToForceAllowRunningAnalyzeOnEDT::class)
internal fun KtClassOrObject.checkIsInheritor(baseClassOrigin: KtClassOrObject, checkDeep: Boolean): Boolean {
return analyze(this) {
val thisSymbol = this@checkIsInheritor.getClassOrObjectSymbol()
val baseSymbol = baseClassOrigin.getClassOrObjectSymbol()
if (thisSymbol == baseSymbol) return@analyze false
val baseType = baseSymbol.buildTypeForSymbol()
if (checkDeep) {
thisSymbol.buildTypeForSymbol().isSubTypeOf(baseType)
} else {
thisSymbol.superTypes.any { baseType.isEqualTo(it.type) }
}
}
}