[fir low level] extract library session caching to a separate class

This commit is contained in:
Ilya Kirillov
2022-05-03 23:44:09 +02:00
parent 7c202948cd
commit 4825de3ed8
6 changed files with 267 additions and 213 deletions
@@ -0,0 +1,83 @@
/*
* Copyright 2010-2022 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.analysis.low.level.api.fir.project.structure
import com.intellij.openapi.project.Project
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.createPackagePartProviderForLibrary
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirJavaFacadeForBinaries
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSession
import org.jetbrains.kotlin.analysis.project.structure.KtBinaryModule
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.analysis.project.structure.allDirectDependenciesOfType
import org.jetbrains.kotlin.analysis.utils.errors.checkIsInstance
import org.jetbrains.kotlin.fir.BuiltinTypes
import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.deserialization.EmptyModuleDataProvider
import org.jetbrains.kotlin.fir.deserialization.LibraryPathFilter
import org.jetbrains.kotlin.fir.deserialization.ModuleDataProvider
import org.jetbrains.kotlin.fir.deserialization.MultipleModuleDataProvider
import org.jetbrains.kotlin.fir.java.deserialization.JvmClassFileBasedSymbolProvider
import org.jetbrains.kotlin.fir.java.deserialization.OptionalAnnotationClassesProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
import org.jetbrains.kotlin.load.java.createJavaClassFinder
import org.jetbrains.kotlin.load.kotlin.VirtualFileFinderFactory
internal object LLFirLibraryProviderFactory {
fun createProvidersByModuleLibraryDependencies(
session: LLFirSession,
module: KtModule,
kotlinScopeProvider: FirKotlinScopeProvider,
project: Project,
builtinTypes: BuiltinTypes,
createSearchScopeForModules: (List<KtBinaryModule>) -> GlobalSearchScope
): List<FirSymbolProvider> = buildList {
module
.allDirectDependenciesOfType<KtBinaryModule>()
.groupBy { it.platform }
.forEach { (_, binaryDependencies) ->
val moduleDataProvider = createModuleDataProviderWithLibraryDependencies(module, binaryDependencies, session)
val scope = createSearchScopeForModules(binaryDependencies)
val packagePartProvider = project.createPackagePartProviderForLibrary(scope)
add(
JvmClassFileBasedSymbolProvider(
session,
moduleDataProvider,
kotlinScopeProvider,
packagePartProvider,
VirtualFileFinderFactory.getInstance(project).create(scope),
LLFirJavaFacadeForBinaries(session, builtinTypes, project.createJavaClassFinder(scope), moduleDataProvider)
)
)
add(OptionalAnnotationClassesProvider(session, moduleDataProvider, kotlinScopeProvider, packagePartProvider))
}
}
private fun createModuleDataProviderWithLibraryDependencies(
sourceModule: KtModule,
binaryDependencies: List<KtBinaryModule>,
session: LLFirSession
): ModuleDataProvider {
val moduleDatas = binaryDependencies.map { LLFirKtModuleBasedModuleData(it) }
if (moduleDatas.isEmpty()) {
return EmptyModuleDataProvider(sourceModule.platform, sourceModule.analyzerServices)
}
moduleDatas.forEach { it.bindSession(session) }
val moduleDataWithFilters: Map<FirModuleData, LibraryPathFilter.LibraryList> =
moduleDatas.associateWith { moduleData ->
checkIsInstance<LLFirKtModuleBasedModuleData>(moduleData)
val ktBinaryModule = moduleData.ktModule as KtBinaryModule
val moduleBinaryRoots = ktBinaryModule.getBinaryRoots().mapTo(mutableSetOf()) { it.toAbsolutePath() }
LibraryPathFilter.LibraryList(moduleBinaryRoots)
}
return MultipleModuleDataProvider(moduleDataWithFilters)
}
}
@@ -0,0 +1,111 @@
/*
* Copyright 2010-2022 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.analysis.low.level.api.fir.project.structure
import com.intellij.openapi.project.Project
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLFirBuiltinSymbolProvider
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLFirBuiltinsAndCloneableSessionProvider
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLFirLibrariesSessionProvider
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirBuiltinsAndCloneableSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirLibrariesSession
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.fir.BuiltinTypes
import org.jetbrains.kotlin.fir.PrivateSessionConstructor
import org.jetbrains.kotlin.fir.SessionConfiguration
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmTypeMapper
import org.jetbrains.kotlin.fir.resolve.providers.FirProvider
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.providers.symbolProvider
import org.jetbrains.kotlin.fir.resolve.scopes.wrapScopeWithJvmMapped
import org.jetbrains.kotlin.fir.resolve.transformers.FirPhaseCheckingPhaseManager
import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
import org.jetbrains.kotlin.fir.session.registerCommonComponents
import org.jetbrains.kotlin.fir.session.registerCommonJavaComponents
import org.jetbrains.kotlin.fir.session.registerJavaSpecificResolveComponents
import org.jetbrains.kotlin.fir.session.registerModuleData
import org.jetbrains.kotlin.fir.symbols.FirPhaseManager
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver
import java.util.concurrent.ConcurrentHashMap
@OptIn(PrivateSessionConstructor::class, SessionConfiguration::class)
internal class LLFirLibrarySessionFactory(
private val project: Project,
private val useSiteModule: KtModule,
private val useSiteLanguageVersionSettings: LanguageVersionSettings,
) {
val builtInTypes = BuiltinTypes()
val builtinsAndCloneableSession = createBuiltinsAndCloneableSession()
private val librarySessionByModule = ConcurrentHashMap<KtModule, LLFirLibrariesSession>()
fun getLibrarySessionForSourceModule(ktModule: KtSourceModule): LLFirLibrariesSession {
return librarySessionByModule.getOrPut(ktModule) { createModuleLibrariesSession(ktModule) }
}
private fun createModuleLibrariesSession(
sourceModule: KtSourceModule,
): LLFirLibrariesSession {
return LLFirLibrariesSession(project, builtInTypes).apply session@{
registerModuleData(LLFirKtModuleBasedModuleData(sourceModule).apply { bindSession(this@session) })
registerIdeComponents(project)
register(FirPhaseManager::class, FirPhaseCheckingPhaseManager)
registerCommonComponents(sourceModule.languageVersionSettings)
registerCommonJavaComponents(JavaModuleResolver.getInstance(project))
registerJavaSpecificResolveComponents()
val kotlinScopeProvider = FirKotlinScopeProvider(::wrapScopeWithJvmMapped)
register(FirKotlinScopeProvider::class, kotlinScopeProvider)
val providers = LLFirLibraryProviderFactory.createProvidersByModuleLibraryDependencies(
this,
sourceModule,
kotlinScopeProvider,
project,
builtinTypes
) { binaryDependencies ->
GlobalSearchScope.union(binaryDependencies.map { it.contentScope })
}
val symbolProvider = createCompositeSymbolProvider(this) {
addAll(providers)
add(builtinsAndCloneableSession.symbolProvider)
}
register(FirProvider::class, LLFirLibrariesSessionProvider(symbolProvider))
register(FirSymbolProvider::class, symbolProvider)
register(FirJvmTypeMapper::class, FirJvmTypeMapper(this))
}
}
private fun createBuiltinsAndCloneableSession(): LLFirBuiltinsAndCloneableSession {
return LLFirBuiltinsAndCloneableSession(project, builtInTypes).apply session@{
val moduleData = LLFirBuiltinsModuleData(useSiteModule).apply {
bindSession(this@session)
}
registerIdeComponents(project)
register(FirPhaseManager::class, FirPhaseCheckingPhaseManager)
registerCommonComponents(useSiteLanguageVersionSettings)
registerModuleData(moduleData)
val kotlinScopeProvider = FirKotlinScopeProvider(::wrapScopeWithJvmMapped)
register(FirKotlinScopeProvider::class, kotlinScopeProvider)
val symbolProvider = createCompositeSymbolProvider(this) {
add(LLFirBuiltinSymbolProvider(this@session, moduleData, kotlinScopeProvider))
add(FirCloneableSymbolProvider(this@session, moduleData, kotlinScopeProvider))
}
register(FirSymbolProvider::class, symbolProvider)
register(FirProvider::class, LLFirBuiltinsAndCloneableSessionProvider(symbolProvider))
register(FirJvmTypeMapper::class, FirJvmTypeMapper(this))
}
}
}
@@ -0,0 +1,31 @@
/*
* Copyright 2010-2022 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.analysis.low.level.api.fir.project.structure
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.analysis.low.level.api.fir.IdeSessionComponents
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.createSealedInheritorsProvider
import org.jetbrains.kotlin.analysis.low.level.api.fir.fir.caches.FirThreadSafeCachesFactory
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSession
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.SessionConfiguration
import org.jetbrains.kotlin.fir.caches.FirCachesFactory
import org.jetbrains.kotlin.fir.declarations.SealedClassInheritorsProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirCompositeSymbolProvider
@OptIn(SessionConfiguration::class)
internal fun LLFirSession.registerIdeComponents(project: Project) {
register(IdeSessionComponents::class, IdeSessionComponents.create(this))
register(FirCachesFactory::class, FirThreadSafeCachesFactory)
register(SealedClassInheritorsProvider::class, project.createSealedInheritorsProvider())
}
internal inline fun createCompositeSymbolProvider(
session: FirSession,
builderAction: MutableList<FirSymbolProvider>.() -> Unit
): FirCompositeSymbolProvider =
FirCompositeSymbolProvider(session, buildList(builderAction))
@@ -8,56 +8,37 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions
import com.intellij.openapi.project.Project
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.ProjectScope
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirPhaseManager
import org.jetbrains.kotlin.analysis.low.level.api.fir.IdeSessionComponents
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirGlobalResolveComponents
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.createPackagePartProviderForLibrary
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.createSealedInheritorsProvider
import org.jetbrains.kotlin.analysis.low.level.api.fir.fir.caches.FirThreadSafeCachesFactory
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirPhaseManager
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirKtModuleBasedModuleData
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirBuiltinsModuleData
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirLibraryProviderFactory
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirLibrarySessionFactory
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.registerIdeComponents
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.*
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkCanceled
import org.jetbrains.kotlin.analysis.project.structure.*
import org.jetbrains.kotlin.analysis.providers.createAnnotationResolver
import org.jetbrains.kotlin.analysis.providers.createDeclarationProvider
import org.jetbrains.kotlin.analysis.providers.createPackageProvider
import org.jetbrains.kotlin.analysis.utils.errors.checkIsInstance
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmTypeMapper
import org.jetbrains.kotlin.fir.caches.FirCachesFactory
import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.SealedClassInheritorsProvider
import org.jetbrains.kotlin.fir.deserialization.EmptyModuleDataProvider
import org.jetbrains.kotlin.fir.deserialization.LibraryPathFilter
import org.jetbrains.kotlin.fir.deserialization.ModuleDataProvider
import org.jetbrains.kotlin.fir.deserialization.MultipleModuleDataProvider
import org.jetbrains.kotlin.fir.extensions.*
import org.jetbrains.kotlin.fir.extensions.predicate.DeclarationPredicate
import org.jetbrains.kotlin.fir.java.FirJavaFacadeForSource
import org.jetbrains.kotlin.fir.java.JavaSymbolProvider
import org.jetbrains.kotlin.fir.java.deserialization.JvmClassFileBasedSymbolProvider
import org.jetbrains.kotlin.fir.java.deserialization.OptionalAnnotationClassesProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirDependenciesSymbolProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirProvider
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.providers.symbolProvider
import org.jetbrains.kotlin.fir.resolve.scopes.wrapScopeWithJvmMapped
import org.jetbrains.kotlin.fir.resolve.transformers.FirPhaseCheckingPhaseManager
import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
import org.jetbrains.kotlin.fir.session.*
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.FirPhaseManager
import org.jetbrains.kotlin.load.java.createJavaClassFinder
import org.jetbrains.kotlin.load.kotlin.VirtualFileFinderFactory
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver
@@ -69,13 +50,11 @@ internal object LLFirSessionFactory {
fun createSourcesSession(
project: Project,
module: KtSourceModule,
builtinsAndCloneableSession: LLFirBuiltinsAndCloneableSession,
globalResolveComponents: LLFirGlobalResolveComponents,
sessionInvalidator: LLFirSessionInvalidator,
builtinTypes: BuiltinTypes,
sessionsCache: MutableMap<KtModule, LLFirResolvableModuleSession>,
isRootModule: Boolean,
librariesCache: LibrariesCache,
librariesSessionFactory: LLFirLibrarySessionFactory,
configureSession: (LLFirSession.() -> Unit)? = null
): LLFirSourcesSession {
sessionsCache[module]?.let { return it as LLFirSourcesSession }
@@ -96,7 +75,7 @@ internal object LLFirSessionFactory {
val contentScope = module.contentScope
val dependentModules = module.directRegularDependenciesOfType<KtSourceModule>()
val session = LLFirSourcesSession(module, project, components, builtinTypes)
val session = LLFirSourcesSession(module, project, components, librariesSessionFactory.builtInTypes)
sessionsCache[module] = session
components.session = session
@@ -126,28 +105,18 @@ internal object LLFirSessionFactory {
@OptIn(ExperimentalStdlibApi::class)
val dependentProviders = buildList {
add(
createModuleLibrariesSession(
module,
project,
builtinsAndCloneableSession,
builtinTypes,
librariesCache,
languageVersionSettings = languageVersionSettings,
configureSession = configureSession,
).symbolProvider
librariesSessionFactory.getLibrarySessionForSourceModule(module).symbolProvider
)
dependentModules
.mapTo(this) {
createSourcesSession(
project,
it,
builtinsAndCloneableSession,
globalResolveComponents,
sessionInvalidator,
builtinTypes,
sessionsCache,
isRootModule = false,
librariesCache = librariesCache,
librariesSessionFactory = librariesSessionFactory,
configureSession = configureSession,
).symbolProvider
}
@@ -210,136 +179,6 @@ internal object LLFirSessionFactory {
}
}
private fun createModuleLibrariesSession(
sourceModule: KtSourceModule,
project: Project,
builtinsAndCloneableSession: LLFirBuiltinsAndCloneableSession,
builtinTypes: BuiltinTypes,
librariesCache: LibrariesCache,
languageVersionSettings: LanguageVersionSettings = LanguageVersionSettingsImpl.DEFAULT,
configureSession: (LLFirSession.() -> Unit)?,
): LLFirLibrariesSession = librariesCache.cached(sourceModule) {
checkCanceled()
LLFirLibrariesSession(project, builtinTypes).apply session@{
registerModuleData(LLFirKtModuleBasedModuleData(sourceModule).apply { bindSession(this@session) })
registerIdeComponents(project)
register(FirPhaseManager::class, FirPhaseCheckingPhaseManager)
registerCommonComponents(languageVersionSettings)
registerCommonJavaComponents(JavaModuleResolver.getInstance(project))
registerJavaSpecificResolveComponents()
val kotlinScopeProvider = FirKotlinScopeProvider(::wrapScopeWithJvmMapped)
register(FirKotlinScopeProvider::class, kotlinScopeProvider)
val providers = createProvidersByModulePrimaryDependencies(
this,
sourceModule,
kotlinScopeProvider,
project,
builtinTypes
) { binaryDependencies ->
GlobalSearchScope.union(binaryDependencies.map { it.contentScope })
}
val symbolProvider = FirCompositeSymbolProvider(
this,
buildList {
addAll(providers)
add(builtinsAndCloneableSession.symbolProvider)
}
)
register(FirProvider::class, LLFirLibrariesSessionProvider(symbolProvider))
register(FirSymbolProvider::class, symbolProvider)
register(FirJvmTypeMapper::class, FirJvmTypeMapper(this))
configureSession?.invoke(this)
}
}
private fun createProvidersByModulePrimaryDependencies(
session: LLFirSession,
module: KtModule,
kotlinScopeProvider: FirKotlinScopeProvider,
project: Project,
builtinTypes: BuiltinTypes,
createSearchScopeForModules: (List<KtBinaryModule>) -> GlobalSearchScope
): List<FirSymbolProvider> = buildList {
module
.allDirectDependenciesOfType<KtBinaryModule>()
.groupBy { it.platform }
.forEach { (_, binaryDependencies) ->
val moduleDataProvider = createModuleDataProviderWithLibraryDependencies(module, binaryDependencies, session)
val scope = createSearchScopeForModules(binaryDependencies)
val packagePartProvider = project.createPackagePartProviderForLibrary(scope)
add(
JvmClassFileBasedSymbolProvider(
session,
moduleDataProvider,
kotlinScopeProvider,
packagePartProvider,
VirtualFileFinderFactory.getInstance(project).create(scope),
LLFirJavaFacadeForBinaries(session, builtinTypes, project.createJavaClassFinder(scope), moduleDataProvider)
)
)
add(OptionalAnnotationClassesProvider(session, moduleDataProvider, kotlinScopeProvider, packagePartProvider))
}
}
private fun createModuleDataProviderWithLibraryDependencies(
sourceModule: KtModule,
binaryDependencies: List<KtBinaryModule>,
session: LLFirSession
): ModuleDataProvider {
val moduleDatas = binaryDependencies.map { LLFirKtModuleBasedModuleData(it) }
if (moduleDatas.isEmpty()) {
return EmptyModuleDataProvider(sourceModule.platform, sourceModule.analyzerServices)
}
moduleDatas.forEach { it.bindSession(session) }
val moduleDataWithFilters: Map<FirModuleData, LibraryPathFilter.LibraryList> =
moduleDatas.associateWith { moduleData ->
checkIsInstance<LLFirKtModuleBasedModuleData>(moduleData)
val ktBinaryModule = moduleData.ktModule as KtBinaryModule
val moduleBinaryRoots = ktBinaryModule.getBinaryRoots().mapTo(mutableSetOf()) { it.toAbsolutePath() }
LibraryPathFilter.LibraryList(moduleBinaryRoots)
}
return MultipleModuleDataProvider(moduleDataWithFilters)
}
fun createBuiltinsAndCloneableSession(
project: Project,
builtinTypes: BuiltinTypes,
useSiteModule: KtModule,
languageVersionSettings: LanguageVersionSettings = LanguageVersionSettingsImpl.DEFAULT,
configureSession: (LLFirSession.() -> Unit)? = null,
): LLFirBuiltinsAndCloneableSession {
return LLFirBuiltinsAndCloneableSession(project, builtinTypes).apply session@{
val moduleData = LLFirBuiltinsModuleData(useSiteModule).apply {
bindSession(this@session)
}
registerIdeComponents(project)
register(FirPhaseManager::class, FirPhaseCheckingPhaseManager)
registerCommonComponents(languageVersionSettings)
registerModuleData(moduleData)
val kotlinScopeProvider = FirKotlinScopeProvider(::wrapScopeWithJvmMapped)
register(FirKotlinScopeProvider::class, kotlinScopeProvider)
val symbolProvider = FirCompositeSymbolProvider(
this,
listOf(
LLFirBuiltinSymbolProvider(this, moduleData, kotlinScopeProvider),
FirCloneableSymbolProvider(this, moduleData, kotlinScopeProvider),
)
)
register(FirSymbolProvider::class, symbolProvider)
register(FirProvider::class, LLFirBuiltinsAndCloneableSessionProvider(symbolProvider))
register(FirJvmTypeMapper::class, FirJvmTypeMapper(this))
configureSession?.invoke(this)
}
}
fun createLibraryOrLibrarySourceResolvableSession(
project: Project,
@@ -396,7 +235,15 @@ internal object LLFirSessionFactory {
val librariesSearchScope = ProjectScope.getLibrariesScope(project)
.intersectWith(GlobalSearchScope.notScope(libraryModule.contentScope)) // <all libraries scope> - <current library scope>
add(builtinsAndCloneableSession.symbolProvider)
addAll(createProvidersByModulePrimaryDependencies(session, module, scopeProvider, project, builtinTypes) { librariesSearchScope })
addAll(
LLFirLibraryProviderFactory.createProvidersByModuleLibraryDependencies(
session,
module,
scopeProvider,
project,
builtinTypes
) { librariesSearchScope }
)
}
// We need FirRegisteredPluginAnnotations during extensions' registration process
@@ -436,12 +283,6 @@ internal object LLFirSessionFactory {
}
}
private fun LLFirSession.registerIdeComponents(project: Project) {
register(IdeSessionComponents::class, IdeSessionComponents.create(this))
register(FirCachesFactory::class, FirThreadSafeCachesFactory)
register(SealedClassInheritorsProvider::class, project.createSealedInheritorsProvider())
}
}
private fun List<KtModule>.extractLibraryPaths(): List<Path> =
@@ -11,7 +11,7 @@ import kotlinx.collections.immutable.PersistentMap
import kotlinx.collections.immutable.persistentMapOf
import kotlinx.collections.immutable.toPersistentMap
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirGlobalResolveComponents
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirPhaseRunner
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirLibrarySessionFactory
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.firKtModuleBasedModuleData
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.addValueFor
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.executeWithoutPCE
@@ -20,56 +20,64 @@ import org.jetbrains.kotlin.analysis.providers.createLibrariesModificationTracke
import org.jetbrains.kotlin.analysis.providers.createModuleWithoutDependenciesOutOfBlockModificationTracker
import org.jetbrains.kotlin.analysis.utils.caches.getValue
import org.jetbrains.kotlin.analysis.utils.caches.softCachedValue
import org.jetbrains.kotlin.analysis.utils.errors.unexpectedElementError
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
import org.jetbrains.kotlin.fir.BuiltinTypes
import org.jetbrains.kotlin.fir.FirSessionProvider
import java.util.concurrent.ConcurrentHashMap
class LLFirSessionProviderStorage(val project: Project) {
private val sessionsCache = ConcurrentHashMap<KtModule, FromModuleViewSessionCache>()
private val librariesCache by softCachedValue(project, project.createLibrariesModificationTracker()) { LibrariesCache() }
private val librariesFactoryByUseSiteModule by softCachedValue(project, project.createLibrariesModificationTracker()) {
ConcurrentHashMap<KtModule, LLFirLibrarySessionFactory>()
}
fun getSessionProvider(
rootModule: KtModule,
useSiteKtModule: KtModule,
configureSession: (LLFirSession.() -> Unit)? = null
): LLFirSessionProvider {
val globalComponents = LLFirGlobalResolveComponents(rootModule, project)
val globalComponents = LLFirGlobalResolveComponents(useSiteKtModule, project)
val builtinTypes = BuiltinTypes()
val librariesSessionFactory = librariesFactoryByUseSiteModule.getOrPut(useSiteKtModule) {
val languageVersionSettings = when (useSiteKtModule) {
is KtSourceModule -> useSiteKtModule.languageVersionSettings
is KtLibraryModule, is KtLibrarySourceModule -> LanguageVersionSettingsImpl.DEFAULT
else -> unexpectedElementError("module", useSiteKtModule)
}
LLFirLibrarySessionFactory(project, useSiteKtModule, languageVersionSettings)
}
val builtinsAndCloneableSession = LLFirSessionFactory.createBuiltinsAndCloneableSession(project, builtinTypes, rootModule)
val cache = sessionsCache.getOrPut(rootModule) { FromModuleViewSessionCache() }
val cache = sessionsCache.getOrPut(useSiteKtModule) { FromModuleViewSessionCache() }
val (sessions, session) = cache.withMappings(project) { mappings ->
val sessions = mutableMapOf<KtModule, LLFirResolvableModuleSession>().apply { putAll(mappings) }
val session = executeWithoutPCE {
when (rootModule) {
when (useSiteKtModule) {
is KtSourceModule -> {
LLFirSessionFactory.createSourcesSession(
project,
rootModule,
builtinsAndCloneableSession,
useSiteKtModule,
globalComponents,
cache.sessionInvalidator,
builtinTypes,
sessions,
isRootModule = true,
librariesCache = librariesCache,
librariesSessionFactory = librariesSessionFactory,
configureSession = configureSession,
)
}
is KtLibraryModule, is KtLibrarySourceModule -> {
LLFirSessionFactory.createLibraryOrLibrarySourceResolvableSession(
project,
rootModule,
builtinsAndCloneableSession,
useSiteKtModule,
librariesSessionFactory.builtinsAndCloneableSession,
globalComponents,
cache.sessionInvalidator,
builtinTypes,
librariesSessionFactory.builtInTypes,
sessions,
configureSession = configureSession,
)
}
else -> error("Unexpected ${rootModule::class.simpleName}")
else -> error("Unexpected ${useSiteKtModule::class.simpleName}")
}
}
@@ -1,20 +0,0 @@
/*
* Copyright 2010-2020 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.analysis.low.level.api.fir.sessions
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import java.util.concurrent.ConcurrentHashMap
@JvmInline
internal value class LibrariesCache(
private val cache: ConcurrentHashMap<KtModule, LLFirLibrariesSession> = ConcurrentHashMap()
) {
fun cached(
module: KtModule,
create: (KtModule) -> LLFirLibrariesSession
): LLFirLibrariesSession =
cache.computeIfAbsent(module, create)
}