diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/ComponentsContainers.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/ComponentsContainers.kt index 1ea8f78b22c..bb4bed81e96 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/ComponentsContainers.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/ComponentsContainers.kt @@ -26,6 +26,8 @@ import org.jetbrains.kotlin.fir.resolve.calls.jvm.JvmCallConflictResolverFactory import org.jetbrains.kotlin.fir.resolve.inference.InferenceComponents import org.jetbrains.kotlin.fir.resolve.providers.impl.FirQualifierResolverImpl import org.jetbrains.kotlin.fir.resolve.providers.impl.FirTypeResolverImpl +import org.jetbrains.kotlin.fir.resolve.transformers.FirPhaseCheckingPhaseManager +import org.jetbrains.kotlin.fir.resolve.transformers.FirPhaseManager import org.jetbrains.kotlin.fir.resolve.transformers.plugin.GeneratedClassIndex import org.jetbrains.kotlin.fir.scopes.impl.FirDeclaredMemberScopeProvider import org.jetbrains.kotlin.fir.types.FirCorrespondingSupertypesCache @@ -58,6 +60,10 @@ fun FirSession.registerSealedClassInheritorsProvider() { register(SealedClassInheritorsProvider::class, SealedClassInheritorsProviderImpl) } +@OptIn(SessionConfiguration::class) +fun FirSession.registerFirCliPhaseManager() { + register(FirPhaseManager::class, FirPhaseCheckingPhaseManager) +} // -------------------------- Resolve components -------------------------- diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirSessionFactory.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirSessionFactory.kt index f8383fac11a..20008779721 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirSessionFactory.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirSessionFactory.kt @@ -74,6 +74,7 @@ object FirSessionFactory { ): FirJavaModuleBasedSession { return FirJavaModuleBasedSession(moduleInfo, sessionProvider).apply { registerThreadUnsafeCaches() + registerFirCliPhaseManager() registerCommonComponents(languageVersionSettings) registerResolveComponents(lookupTracker) registerJavaSpecificResolveComponents() @@ -127,6 +128,7 @@ object FirSessionFactory { ): FirLibrarySession { return FirLibrarySession(moduleInfo, sessionProvider).apply { registerThreadUnsafeCaches() + registerFirCliPhaseManager() registerCommonComponents(languageVersionSettings) registerSealedClassInheritorsProvider() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirPhaseCheckingPhaseManager.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirPhaseCheckingPhaseManager.kt new file mode 100644 index 00000000000..5ef558c86f6 --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirPhaseCheckingPhaseManager.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.resolve.transformers + +import org.jetbrains.kotlin.fir.FirRenderer +import org.jetbrains.kotlin.fir.declarations.FirDeclaration +import org.jetbrains.kotlin.fir.declarations.FirResolvePhase +import org.jetbrains.kotlin.fir.render +import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol + +object FirPhaseCheckingPhaseManager : FirPhaseManager() { + override fun ensureResolved(symbol: AbstractFirBasedSymbol<*>, requiredPhase: FirResolvePhase) { + val fir = symbol.fir as FirDeclaration + val availablePhase = fir.resolvePhase + require(availablePhase >= requiredPhase) { + "Expected at least $requiredPhase for $symbol but was $availablePhase\n{${fir.render(renderMode)}" + } + } + + private val renderMode = FirRenderer.RenderMode.WithResolvePhases.copy(renderDeclarationOrigin = true) +} \ No newline at end of file diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirPhaseManager.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirPhaseManager.kt index e7509d09a7a..0ae76e99ebe 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirPhaseManager.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirPhaseManager.kt @@ -17,4 +17,4 @@ abstract class FirPhaseManager : FirSessionComponent { ) } -internal val FirSession.phaseManager: FirPhaseManager? by FirSession.nullableSessionComponentAccessor() +internal val FirSession.phaseManager: FirPhaseManager by FirSession.sessionComponentAccessor() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/PhaseUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/PhaseUtils.kt index 37043f3a736..c1682a74585 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/PhaseUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/PhaseUtils.kt @@ -23,13 +23,9 @@ fun AbstractFirBasedSymbol<*>.ensureResolved( // TODO: Decide which one session should be used and probably get rid of the parameter if use-site session is not needed @Suppress("UNUSED_PARAMETER") useSiteSession: FirSession, ) { - val fir = fir as FirDeclaration - val availablePhase = fir.resolvePhase - if (availablePhase >= requiredPhase) return - val resolver = fir.session.phaseManager - ?: error("phaseManager should be defined when working with FIR in phased mode") - - resolver.ensureResolved(this, requiredPhase) + val session = (fir as FirDeclaration).session + val phaseManager = session.phaseManager + phaseManager.ensureResolved(this, requiredPhase) } fun FirSymbolOwner<*>.ensureResolved( diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSessionFactory.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSessionFactory.kt index 69415ee892d..3094befddcb 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSessionFactory.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSessionFactory.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.impl.FirCloneableSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.impl.FirCompositeSymbolProvider import org.jetbrains.kotlin.fir.resolve.scopes.wrapScopeWithJvmMapped +import org.jetbrains.kotlin.fir.resolve.transformers.FirPhaseCheckingPhaseManager import org.jetbrains.kotlin.fir.resolve.transformers.FirPhaseManager import org.jetbrains.kotlin.fir.scopes.KotlinScopeProvider import org.jetbrains.kotlin.fir.session.* @@ -170,6 +171,7 @@ internal object FirIdeSessionFactory { val kotlinClassFinder = VirtualFileFinderFactory.getInstance(project).create(searchScope) FirIdeLibrariesSession(moduleInfo, project, searchScope, builtinTypes).apply { registerIdeComponents() + register(FirPhaseManager::class, FirPhaseCheckingPhaseManager) registerCommonComponents(languageVersionSettings) registerJavaSpecificResolveComponents() @@ -213,6 +215,7 @@ internal object FirIdeSessionFactory { ): FirIdeBuiltinsAndCloneableSession { return FirIdeBuiltinsAndCloneableSession(project, builtinTypes).apply { registerIdeComponents() + register(FirPhaseManager::class, FirPhaseCheckingPhaseManager) registerCommonComponents(languageVersionSettings) val kotlinScopeProvider = KotlinScopeProvider(::wrapScopeWithJvmMapped)