[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.
This commit is contained in:
Marco Pennekamp
2023-05-10 19:32:36 +02:00
committed by Space Team
parent bb7625c5b0
commit a61c6f6502
3 changed files with 21 additions and 9 deletions
@@ -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<TargetPlatform, LLFirBuiltinsAndCloneableSession>()
fun getBuiltinsSession(platform: TargetPlatform): LLFirBuiltinsAndCloneableSession {
return builtinsAndCloneableSession.getOrPut(platform) { createBuiltinsAndCloneableSession(platform) }
}
private val builtinsModules = ConcurrentHashMap<TargetPlatform, KtBuiltinsModule>()
private val builtinsAndCloneableSessions = ConcurrentHashMap<TargetPlatform, LLFirBuiltinsAndCloneableSession>()
/**
* 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) }
@@ -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)
@@ -72,8 +72,7 @@ private class KtNotUnderContentRootModuleForTest(
override val platform: TargetPlatform
) : KtNotUnderContentRootModule {
override val directRegularDependencies: List<KtModule> by lazy {
val builtinsModule = LLFirBuiltinsSessionFactory.getInstance(project).getBuiltinsSession(platform).ktModule as KtBuiltinsModule
listOf(builtinsModule)
listOf(LLFirBuiltinsSessionFactory.getInstance(project).getBuiltinsModule(platform))
}
override val directDependsOnDependencies: List<KtModule>