[FIR IDE] Implement isInheritor for KtFirBasedFakeLightClass

This commit is contained in:
Igor Yakovlev
2021-01-28 22:16:48 +03:00
parent 5d4606daaa
commit 56db4bd1ac
6 changed files with 54 additions and 16 deletions
@@ -12,8 +12,8 @@ import org.jetbrains.kotlin.idea.frontend.api.components.*
import org.jetbrains.kotlin.idea.frontend.api.scopes.*
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithDeclarations
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithMembers
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithKind
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithMembers
import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.idea.references.KtReference
@@ -80,6 +80,8 @@ abstract class KtAnalysisSession(final override val token: ValidityToken) : Vali
val builtinTypes: KtBuiltinTypes get() = typeProvider.builtinTypes
fun KtClassOrObjectSymbol.buildTypeForSymbol(): KtType = typeProvider.buildTypeForSymbol(this)
fun KtElement.getDiagnostics(): Collection<Diagnostic> = diagnosticProvider.getDiagnosticsForElement(this)
fun KtFile.collectDiagnosticsForFile(): Collection<Diagnostic> = diagnosticProvider.collectDiagnosticsForFile(this)
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.idea.frontend.api.components
import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassOrObjectSymbol
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
abstract class KtTypeProvider : KtAnalysisSessionComponent() {
@@ -13,6 +14,8 @@ abstract class KtTypeProvider : KtAnalysisSessionComponent() {
abstract fun isBuiltinFunctionalType(type: KtType): Boolean
abstract val builtinTypes: KtBuiltinTypes
abstract fun buildTypeForSymbol(symbol: KtClassOrObjectSymbol): KtType
}
@@ -19,7 +19,6 @@ import org.jetbrains.kotlin.asJava.elements.FirLightIdentifier
import org.jetbrains.kotlin.asJava.elements.KtLightField
import org.jetbrains.kotlin.idea.asJava.classes.getOrCreateFirLightClass
import org.jetbrains.kotlin.idea.asJava.elements.FirLightTypeParameterListForSymbol
import org.jetbrains.kotlin.idea.frontend.api.fir.analyzeWithSymbolAsContext
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolKind
import org.jetbrains.kotlin.idea.util.ifFalse
@@ -6,15 +6,18 @@
package org.jetbrains.kotlin.idea.asJava
import com.intellij.psi.PsiClass
import com.intellij.psi.impl.InheritanceImplUtil
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.frontend.api.HackToForceAllowRunningAnalyzeOnEDT
import org.jetbrains.kotlin.idea.frontend.api.analyze
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
//TODO Make fake class symbol based
class KtFirBasedFakeLightClass(kotlinOrigin: KtClassOrObject) : KtFakeLightClass(kotlinOrigin) {
class KtFirBasedFakeLightClass(kotlinOrigin: KtClassOrObject) :
KtFakeLightClass(kotlinOrigin) {
override fun copy(): KtFakeLightClass = KtFirBasedFakeLightClass(kotlinOrigin)
private val _containingClass: KtFakeLightClass? by lazy {
@@ -23,12 +26,27 @@ class KtFirBasedFakeLightClass(kotlinOrigin: KtClassOrObject) : KtFakeLightClass
override fun getContainingClass(): KtFakeLightClass? = _containingClass
@OptIn(HackToForceAllowRunningAnalyzeOnEDT::class)
override fun isInheritor(baseClass: PsiClass, checkDeep: Boolean): Boolean {
//TODO Implement correct inheritance check with symbols
if (manager.areElementsEquivalent(baseClass, this)) return false
LightClassInheritanceHelper.getService(project).isInheritor(this, baseClass, checkDeep).ifSure { return it }
if ((baseClass as? KtLightClass)?.kotlinOrigin == null) return false
return InheritanceImplUtil.isInheritor(this, baseClass, checkDeep)
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) }
}
}
}
}
@@ -24,10 +24,9 @@ import org.jetbrains.kotlin.fir.resolve.substitution.AbstractConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState
import org.jetbrains.kotlin.idea.fir.low.level.api.api.withFirDeclaration
import org.jetbrains.kotlin.idea.frontend.api.fir.analyzeWithSymbolAsContext
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirClassOrObjectSymbol
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirSymbol
import org.jetbrains.kotlin.idea.frontend.api.fir.types.KtFirClassType
@@ -65,14 +64,14 @@ internal fun KtTypeAndAnnotations.asPsiType(
internal fun KtClassOrObjectSymbol.typeForClassSymbol(psiElement: PsiElement): PsiType {
require(this is KtFirClassOrObjectSymbol)
val (session, type) = firRef.withFir(FirResolvePhase.TYPES) { firClass ->
firClass.session to ConeClassLikeTypeImpl(
firClass.symbol.toLookupTag(),
firClass.typeParameters.map { ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), isNullable = false) }.toTypedArray(),
isNullable = false
)
val types = analyzeWithSymbolAsContext(this) {
this@typeForClassSymbol.buildTypeForSymbol()
}
return type.asPsiType(session, this.firRef.resolveState, TypeMappingMode.DEFAULT, psiElement)
require(types is KtFirType)
val session = firRef.withFir { it.session }
return types.coneType.asPsiType(session, firRef.resolveState, TypeMappingMode.DEFAULT, psiElement)
}
private class AnonymousTypesSubstitutor(private val session: FirSession, private val state: FirModuleResolveState) :
@@ -5,12 +5,17 @@
package org.jetbrains.kotlin.idea.frontend.api.fir.components
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.resolve.inference.isBuiltinFunctionalType
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.idea.frontend.api.ValidityToken
import org.jetbrains.kotlin.idea.frontend.api.components.KtBuiltinTypes
import org.jetbrains.kotlin.idea.frontend.api.components.KtTypeProvider
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirClassOrObjectSymbol
import org.jetbrains.kotlin.idea.frontend.api.fir.types.KtFirType
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassOrObjectSymbol
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion
@@ -25,4 +30,16 @@ internal class KtFirTypeProvider(
override val builtinTypes: KtBuiltinTypes =
KtFirBuiltInTypes(analysisSession.firResolveState.rootModuleSession.builtinTypes, analysisSession.firSymbolBuilder, token)
override fun buildTypeForSymbol(symbol: KtClassOrObjectSymbol): KtType {
require(symbol is KtFirClassOrObjectSymbol)
val type = symbol.firRef.withFir(FirResolvePhase.TYPES) { firClass ->
ConeClassLikeTypeImpl(
firClass.symbol.toLookupTag(),
firClass.typeParameters.map { ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), isNullable = false) }.toTypedArray(),
isNullable = false
)
}
return type.asKtType()
}
}