[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:
committed by
Space Team
parent
bb7625c5b0
commit
a61c6f6502
+18
-6
@@ -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) }
|
||||
|
||||
+2
-1
@@ -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)
|
||||
|
||||
+1
-2
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user