From a61c6f6502a1485a15bd3cbf2cd17dc06a6ebed0 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Wed, 10 May 2023 19:32:36 +0200 Subject: [PATCH] [LL FIR] Fix `KtNotUnderContentRootModuleForTest` requesting sessions too early - `KtNotUnderContentRootModuleForTest.directRegularDependencies` is called during project structure creation, which led to builtins session creation during that period. This in turn led to the creation of `JvmStubBasedFirDeserializedSymbolProvider`, which failed upon the initialization of `declarationProvider` because `KotlinDeclarationProviderFactory` wasn't registered yet. This is precisely why `declarationProvider` was made lazy. - However, with the new `FirSymbolNamesProvider`, keeping `declarationProvider` lazy is harder, because `symbolNamesProvider` (if also made lazy) is requested during composite symbol provider creation in `createBuiltinsAndCloneableSession`. - The solution avoids creating the builtins session entirely. Instead, `directRegularDependencies` now gets the `KtBuiltinsModule` directly, which is more straight-forward as well. --- .../structure/LLFirBuiltinsSessionFactory.kt | 24 ++++++++++++++----- ...mStubBasedFirDeserializedSymbolProvider.kt | 3 ++- ...sApiFirOutOfContentRootTestConfigurator.kt | 3 +-- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/project/structure/LLFirBuiltinsSessionFactory.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/project/structure/LLFirBuiltinsSessionFactory.kt index 26807c0df06..06f863646f9 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/project/structure/LLFirBuiltinsSessionFactory.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/project/structure/LLFirBuiltinsSessionFactory.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLFirBuiltinsAn import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirBuiltinsAndCloneableSession import org.jetbrains.kotlin.analysis.low.level.api.fir.stubBased.deserialization.JvmStubBasedFirDeserializedSymbolProvider import org.jetbrains.kotlin.analysis.project.structure.KtBuiltinsModule +import org.jetbrains.kotlin.analysis.project.structure.KtModule import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl import org.jetbrains.kotlin.fir.BuiltinTypes @@ -49,19 +50,30 @@ import java.util.concurrent.ConcurrentHashMap @OptIn(PrivateSessionConstructor::class, SessionConfiguration::class) class LLFirBuiltinsSessionFactory(private val project: Project) { private val builtInTypes = BuiltinTypes() // TODO should be platform-specific - private val builtinsAndCloneableSession = ConcurrentHashMap() - fun getBuiltinsSession(platform: TargetPlatform): LLFirBuiltinsAndCloneableSession { - return builtinsAndCloneableSession.getOrPut(platform) { createBuiltinsAndCloneableSession(platform) } - } + private val builtinsModules = ConcurrentHashMap() + + private val builtinsAndCloneableSessions = ConcurrentHashMap() + + /** + * Returns the [platform]'s [KtBuiltinsModule]. [getBuiltinsModule] should be used instead of [getBuiltinsSession] when a + * [KtBuiltinsModule] is needed as a dependency for other [KtModule]s. This is because during project structure creation, we have to + * avoid the creation of the builtins *session*, as not all services might have been registered at that point. + */ + fun getBuiltinsModule(platform: TargetPlatform): KtBuiltinsModule = + builtinsModules.getOrPut(platform) { KtBuiltinsModule(platform, platform.getAnalyzerServices(), project) } + + fun getBuiltinsSession(platform: TargetPlatform): LLFirBuiltinsAndCloneableSession = + builtinsAndCloneableSessions.getOrPut(platform) { createBuiltinsAndCloneableSession(platform) } @TestOnly fun clearForTheNextTest() { - builtinsAndCloneableSession.clear() + builtinsModules.clear() + builtinsAndCloneableSessions.clear() } private fun createBuiltinsAndCloneableSession(platform: TargetPlatform): LLFirBuiltinsAndCloneableSession { - val builtinsModule = KtBuiltinsModule(platform, platform.getAnalyzerServices(), project) + val builtinsModule = getBuiltinsModule(platform) val session = LLFirBuiltinsAndCloneableSession(builtinsModule, ModificationTracker.NEVER_CHANGED, builtInTypes) val moduleData = LLFirModuleData(builtinsModule).apply { bindSession(session) } diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/JvmStubBasedFirDeserializedSymbolProvider.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/JvmStubBasedFirDeserializedSymbolProvider.kt index 23253d57192..f4562a31a6d 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/JvmStubBasedFirDeserializedSymbolProvider.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/JvmStubBasedFirDeserializedSymbolProvider.kt @@ -52,7 +52,8 @@ internal open class JvmStubBasedFirDeserializedSymbolProvider( scope: GlobalSearchScope, private val initialOrigin: FirDeclarationOrigin ) : LLFirKotlinSymbolProvider(session) { - private val declarationProvider by lazy(LazyThreadSafetyMode.PUBLICATION) { project.createDeclarationProvider(scope, module = null) } + private val declarationProvider = project.createDeclarationProvider(scope, module = null) + private val moduleData = moduleDataProvider.getModuleData(null) override val symbolNamesProvider: FirSymbolNamesProvider = LLFirKotlinSymbolNamesProvider.cached(session, declarationProvider) diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/test/configurators/AnalysisApiFirOutOfContentRootTestConfigurator.kt b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/test/configurators/AnalysisApiFirOutOfContentRootTestConfigurator.kt index 504134b2fa8..1eabfc63e4d 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/test/configurators/AnalysisApiFirOutOfContentRootTestConfigurator.kt +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/test/configurators/AnalysisApiFirOutOfContentRootTestConfigurator.kt @@ -72,8 +72,7 @@ private class KtNotUnderContentRootModuleForTest( override val platform: TargetPlatform ) : KtNotUnderContentRootModule { override val directRegularDependencies: List by lazy { - val builtinsModule = LLFirBuiltinsSessionFactory.getInstance(project).getBuiltinsSession(platform).ktModule as KtBuiltinsModule - listOf(builtinsModule) + listOf(LLFirBuiltinsSessionFactory.getInstance(project).getBuiltinsModule(platform)) } override val directDependsOnDependencies: List