[FIR] Resolve statuses of all classes on path in FirDesignatedStatusResolveTransformer

This is required for calculating of effective visibility, because it
  depends on effective visibility of outer class (those changes are
  added in next commit)
Also fix incorrect designation building for local classes
This commit is contained in:
Dmitriy Novozhilov
2021-04-02 14:52:06 +03:00
committed by TeamCityServer
parent 220f8a9169
commit a600d18396
@@ -12,14 +12,12 @@ import org.jetbrains.kotlin.fir.expressions.FirStatement
import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.firProvider 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.resolve.transformers.body.resolve.LocalClassesNavigationInfo
import org.jetbrains.kotlin.fir.scopes.FirCompositeScope import org.jetbrains.kotlin.fir.scopes.FirCompositeScope
import org.jetbrains.kotlin.fir.scopes.FirScope 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.FirTypeRef
import org.jetbrains.kotlin.fir.types.classId
import org.jetbrains.kotlin.fir.types.coneType 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.CompositeTransformResult
import org.jetbrains.kotlin.fir.visitors.compose import org.jetbrains.kotlin.fir.visitors.compose
import org.jetbrains.kotlin.fir.visitors.transformSingle import org.jetbrains.kotlin.fir.visitors.transformSingle
@@ -143,7 +141,7 @@ private class FirDesignatedStatusResolveTransformer(
} }
currentElement = null currentElement = null
} }
return false return !result
} }
override fun FirDeclaration.needResolveMembers(): Boolean { override fun FirDeclaration.needResolveMembers(): Boolean {
@@ -172,6 +170,11 @@ private class FirDesignatedStatusResolveTransformer(
updateResolvePhaseOfMembers(regularClass) updateResolvePhaseOfMembers(regularClass)
regularClass.transformStatus(this, statusResolver.resolveStatus(regularClass, containingClass, isLocal = false)) 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 { return transformClass(regularClass, data).also {
if (classLocated) statusComputationSession.endComputing(regularClass) if (classLocated) statusComputationSession.endComputing(regularClass)
@@ -184,9 +187,13 @@ sealed class StatusComputationSession {
abstract fun startComputing(klass: FirClass<*>): StatusComputationStatus abstract fun startComputing(klass: FirClass<*>): StatusComputationStatus
abstract fun endComputing(klass: FirClass<*>) abstract fun endComputing(klass: FirClass<*>)
abstract fun computeOnlyClassStatus(klass: FirClass<*>)
enum class StatusComputationStatus { enum class StatusComputationStatus(val requiresComputation: Boolean) {
NotComputed, Computing, Computed NotComputed(true),
Computing(false),
ComputedOnlyClassStatus(true),
Computed(false)
} }
class Regular : StatusComputationSession() { class Regular : StatusComputationSession() {
@@ -202,6 +209,13 @@ sealed class StatusComputationSession {
override fun endComputing(klass: FirClass<*>) { override fun endComputing(klass: FirClass<*>) {
statusMap[klass] = StatusComputationStatus.Computed 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<FirClassLikeDeclaration<*>>) : StatusComputationSession() { class ForLocalClassResolution(private val localClasses: Set<FirClassLikeDeclaration<*>>) : StatusComputationSession() {
@@ -219,6 +233,10 @@ sealed class StatusComputationSession {
override fun endComputing(klass: FirClass<*>) { override fun endComputing(klass: FirClass<*>) {
delegate.endComputing(klass) 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() protected val containingClass: FirClass<*>? get() = classes.lastOrNull()
private val symbolProvider = session.symbolProvider
protected abstract fun FirDeclaration.needResolveMembers(): Boolean protected abstract fun FirDeclaration.needResolveMembers(): Boolean
protected abstract fun FirDeclaration.needResolveNestedClassifiers(): Boolean protected abstract fun FirDeclaration.needResolveNestedClassifiers(): Boolean
@@ -353,64 +369,54 @@ abstract class AbstractFirStatusResolveTransformer(
protected fun forceResolveStatusesOfSupertypes(regularClass: FirRegularClass) { protected fun forceResolveStatusesOfSupertypes(regularClass: FirRegularClass) {
for (superTypeRef in regularClass.superTypeRefs) { for (superTypeRef in regularClass.superTypeRefs) {
forceResolveStatusOfCorrespondingClass(superTypeRef, regularClass) forceResolveStatusOfCorrespondingClass(superTypeRef)
} }
} }
private fun forceResolveStatusOfCorrespondingClass(typeRef: FirTypeRef, subClass: FirRegularClass?) { private fun forceResolveStatusOfCorrespondingClass(typeRef: FirTypeRef) {
val classId = typeRef.coneType.classId ?: return when (val superClass = typeRef.coneType.toSymbol(session)?.fir) {
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) {
is FirRegularClass -> forceResolveStatusesOfClass(superClass) is FirRegularClass -> forceResolveStatusesOfClass(superClass)
is FirTypeAlias -> forceResolveStatusOfCorrespondingClass(superClass.expandedTypeRef, subClass = null) is FirTypeAlias -> forceResolveStatusOfCorrespondingClass(superClass.expandedTypeRef)
} }
} }
@OptIn(ExperimentalStdlibApi::class) @OptIn(ExperimentalStdlibApi::class)
private fun forceResolveStatusesOfClass(regularClass: FirRegularClass) { private fun forceResolveStatusesOfClass(regularClass: FirRegularClass) {
val firProvider = regularClass.session.firProvider if (regularClass.origin == FirDeclarationOrigin.Java) {
if (statusComputationSession[regularClass] == StatusComputationSession.StatusComputationStatus.Computed) return
val file = firProvider.getFirClassifierContainerFileIfAny(regularClass.symbol)
if (regularClass.status is FirResolvedDeclarationStatus) {
statusComputationSession.endComputing(regularClass)
/* /*
* If regular class has no corresponding file then it is platform class, * If regular class has no corresponding file then it is platform class,
* so we need to resolve supertypes of this class because they could * so we need to resolve supertypes of this class because they could
* come from kotlin sources * come from kotlin sources
*/ */
if (file == null) { forceResolveStatusesOfSupertypes(regularClass)
forceResolveStatusesOfSupertypes(regularClass)
}
return return
} }
require(file != null) { if (regularClass.resolvePhase > FirResolvePhase.STATUS) return
"Containing file was not found for\n${regularClass.render()}" 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 val symbol = regularClass.symbol
var declarationToStart: FirDeclaration? = null val designation = if (regularClass.isLocal) buildList {
val designation = designationMapForLocalClasses[regularClass]?.let(::listOf)?.also { var klass: FirClassLikeDeclaration<*> = regularClass
declarationToStart = it.first() while (true) {
} ?: buildList<FirDeclaration> { this.add(klass)
klass = designationMapForLocalClasses[klass]?.takeIf { it !is FirAnonymousObject } ?: break
}
reverse()
} else buildList<FirDeclaration> {
val outerClasses = generateSequence(symbol.classId) { classId -> val outerClasses = generateSequence(symbol.classId) { classId ->
classId.outerClassId classId.outerClassId
}.mapTo(mutableListOf()) { firProvider.getFirClassifierByFqName(it) } }.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() this += outerClasses.filterNotNull().asReversed()
} }
if (designation.isEmpty()) return if (designation.isEmpty()) return
val transformer = FirDesignatedStatusResolveTransformer( val transformer = FirDesignatedStatusResolveTransformer(
@@ -422,7 +428,7 @@ abstract class AbstractFirStatusResolveTransformer(
designationMapForLocalClasses, designationMapForLocalClasses,
scopeForLocalClass scopeForLocalClass
) )
declarationToStart!!.transformSingle(transformer, null) designation.first().transformSingle(transformer, null)
statusComputationSession.endComputing(regularClass) statusComputationSession.endComputing(regularClass)
} }