[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:
committed by
TeamCityServer
parent
220f8a9169
commit
a600d18396
+50
-44
@@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user