diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirStatusResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirStatusResolveTransformer.kt index 40e061fbcd0..d4538c98811 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirStatusResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirStatusResolveTransformer.kt @@ -12,14 +12,12 @@ import org.jetbrains.kotlin.fir.expressions.FirStatement import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.firProvider -import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.LocalClassesNavigationInfo import org.jetbrains.kotlin.fir.scopes.FirCompositeScope import org.jetbrains.kotlin.fir.scopes.FirScope -import org.jetbrains.kotlin.fir.scopes.processClassifiersByName import org.jetbrains.kotlin.fir.types.FirTypeRef -import org.jetbrains.kotlin.fir.types.classId import org.jetbrains.kotlin.fir.types.coneType +import org.jetbrains.kotlin.fir.types.toSymbol import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult import org.jetbrains.kotlin.fir.visitors.compose import org.jetbrains.kotlin.fir.visitors.transformSingle @@ -143,7 +141,7 @@ private class FirDesignatedStatusResolveTransformer( } currentElement = null } - return false + return !result } override fun FirDeclaration.needResolveMembers(): Boolean { @@ -172,6 +170,11 @@ private class FirDesignatedStatusResolveTransformer( updateResolvePhaseOfMembers(regularClass) regularClass.transformStatus(this, statusResolver.resolveStatus(regularClass, containingClass, isLocal = false)) } + } else { + if (regularClass.status !is FirResolvedDeclarationStatus) { + regularClass.transformStatus(this, statusResolver.resolveStatus(regularClass, containingClass, isLocal = false)) + statusComputationSession.computeOnlyClassStatus(regularClass) + } } return transformClass(regularClass, data).also { if (classLocated) statusComputationSession.endComputing(regularClass) @@ -184,9 +187,13 @@ sealed class StatusComputationSession { abstract fun startComputing(klass: FirClass<*>): StatusComputationStatus abstract fun endComputing(klass: FirClass<*>) + abstract fun computeOnlyClassStatus(klass: FirClass<*>) - enum class StatusComputationStatus { - NotComputed, Computing, Computed + enum class StatusComputationStatus(val requiresComputation: Boolean) { + NotComputed(true), + Computing(false), + ComputedOnlyClassStatus(true), + Computed(false) } class Regular : StatusComputationSession() { @@ -202,6 +209,13 @@ sealed class StatusComputationSession { override fun endComputing(klass: FirClass<*>) { statusMap[klass] = StatusComputationStatus.Computed } + + override fun computeOnlyClassStatus(klass: FirClass<*>) { + val existedStatus = statusMap.getValue(klass) + if (existedStatus < StatusComputationStatus.ComputedOnlyClassStatus) { + statusMap[klass] = StatusComputationStatus.ComputedOnlyClassStatus + } + } } class ForLocalClassResolution(private val localClasses: Set>) : StatusComputationSession() { @@ -219,6 +233,10 @@ sealed class StatusComputationSession { override fun endComputing(klass: FirClass<*>) { delegate.endComputing(klass) } + + override fun computeOnlyClassStatus(klass: FirClass<*>) { + delegate.computeOnlyClassStatus(klass) + } } } @@ -234,8 +252,6 @@ abstract class AbstractFirStatusResolveTransformer( protected val containingClass: FirClass<*>? get() = classes.lastOrNull() - private val symbolProvider = session.symbolProvider - protected abstract fun FirDeclaration.needResolveMembers(): Boolean protected abstract fun FirDeclaration.needResolveNestedClassifiers(): Boolean @@ -353,64 +369,54 @@ abstract class AbstractFirStatusResolveTransformer( protected fun forceResolveStatusesOfSupertypes(regularClass: FirRegularClass) { for (superTypeRef in regularClass.superTypeRefs) { - forceResolveStatusOfCorrespondingClass(superTypeRef, regularClass) + forceResolveStatusOfCorrespondingClass(superTypeRef) } } - private fun forceResolveStatusOfCorrespondingClass(typeRef: FirTypeRef, subClass: FirRegularClass?) { - val classId = typeRef.coneType.classId ?: return - val superClass = when { - classId.isLocal -> { - requireNotNull(subClass) - var parent = designationMapForLocalClasses[subClass] as? FirRegularClass - if (parent == null && scopeForLocalClass != null) { - scopeForLocalClass.processClassifiersByName(classId.shortClassName) { - if (it is FirRegularClass && it.classId == classId) { - parent = it - } - } - } - parent - } - else -> symbolProvider.getClassLikeSymbolByFqName(classId)?.fir - } ?: return - when (superClass) { + private fun forceResolveStatusOfCorrespondingClass(typeRef: FirTypeRef) { + when (val superClass = typeRef.coneType.toSymbol(session)?.fir) { is FirRegularClass -> forceResolveStatusesOfClass(superClass) - is FirTypeAlias -> forceResolveStatusOfCorrespondingClass(superClass.expandedTypeRef, subClass = null) + is FirTypeAlias -> forceResolveStatusOfCorrespondingClass(superClass.expandedTypeRef) } } @OptIn(ExperimentalStdlibApi::class) private fun forceResolveStatusesOfClass(regularClass: FirRegularClass) { - val firProvider = regularClass.session.firProvider - if (statusComputationSession[regularClass] == StatusComputationSession.StatusComputationStatus.Computed) return - val file = firProvider.getFirClassifierContainerFileIfAny(regularClass.symbol) - if (regularClass.status is FirResolvedDeclarationStatus) { - statusComputationSession.endComputing(regularClass) + if (regularClass.origin == FirDeclarationOrigin.Java) { /* * If regular class has no corresponding file then it is platform class, * so we need to resolve supertypes of this class because they could * come from kotlin sources */ - if (file == null) { - forceResolveStatusesOfSupertypes(regularClass) - } + forceResolveStatusesOfSupertypes(regularClass) return } - require(file != null) { - "Containing file was not found for\n${regularClass.render()}" + if (regularClass.resolvePhase > FirResolvePhase.STATUS) return + val firProvider = regularClass.session.firProvider + val statusComputationStatus = statusComputationSession[regularClass] + if (!statusComputationStatus.requiresComputation) return + + if (regularClass.status is FirResolvedDeclarationStatus && statusComputationStatus == StatusComputationSession.StatusComputationStatus.Computed) { + statusComputationSession.endComputing(regularClass) + return } val symbol = regularClass.symbol - var declarationToStart: FirDeclaration? = null - val designation = designationMapForLocalClasses[regularClass]?.let(::listOf)?.also { - declarationToStart = it.first() - } ?: buildList { + val designation = if (regularClass.isLocal) buildList { + var klass: FirClassLikeDeclaration<*> = regularClass + while (true) { + this.add(klass) + klass = designationMapForLocalClasses[klass]?.takeIf { it !is FirAnonymousObject } ?: break + } + reverse() + } else buildList { val outerClasses = generateSequence(symbol.classId) { classId -> classId.outerClassId }.mapTo(mutableListOf()) { firProvider.getFirClassifierByFqName(it) } - declarationToStart = file + val file = firProvider.getFirClassifierContainerFileIfAny(regularClass.symbol) + requireNotNull(file) { "Containing file was not found for\n${regularClass.render()}" } this += outerClasses.filterNotNull().asReversed() } + if (designation.isEmpty()) return val transformer = FirDesignatedStatusResolveTransformer( @@ -422,7 +428,7 @@ abstract class AbstractFirStatusResolveTransformer( designationMapForLocalClasses, scopeForLocalClass ) - declarationToStart!!.transformSingle(transformer, null) + designation.first().transformSingle(transformer, null) statusComputationSession.endComputing(regularClass) }