diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtAnalysisSession.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtAnalysisSession.kt index 35b929837bd..0427b25fe00 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtAnalysisSession.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtAnalysisSession.kt @@ -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 = diagnosticProvider.getDiagnosticsForElement(this) fun KtFile.collectDiagnosticsForFile(): Collection = diagnosticProvider.collectDiagnosticsForFile(this) diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/components/KtTypeProvider.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/components/KtTypeProvider.kt index 4d01d8f7bad..4b46fd1cc68 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/components/KtTypeProvider.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/components/KtTypeProvider.kt @@ -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 } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/classes/FirLightClassForClassOrObjectSymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/classes/FirLightClassForClassOrObjectSymbol.kt index 416d6fbdce1..eb713466546 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/classes/FirLightClassForClassOrObjectSymbol.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/classes/FirLightClassForClassOrObjectSymbol.kt @@ -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 diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/classes/KtFirBasedFakeLightClass.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/classes/KtFirBasedFakeLightClass.kt index 7461da46fb5..a1348a8ece4 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/classes/KtFirBasedFakeLightClass.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/classes/KtFirBasedFakeLightClass.kt @@ -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) } + } + } } } \ No newline at end of file diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/firLightUtils.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/firLightUtils.kt index 3d467304df0..cd4fb1772f1 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/firLightUtils.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/firLightUtils.kt @@ -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) : diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirTypeProvider.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirTypeProvider.kt index 9752bf206ea..5bb0135b9ce 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirTypeProvider.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirTypeProvider.kt @@ -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() + } }