From 4825de3ed878edd7983c2c4aaae8c4b78f2bdede Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Tue, 3 May 2022 23:44:09 +0200 Subject: [PATCH] [fir low level] extract library session caching to a separate class --- .../structure/LLFirLibraryProviderFactory.kt | 83 ++++++++ .../structure/LLFirLibrarySessionFactory.kt | 111 ++++++++++ .../structure/sessionFactoryHelpers.kt | 31 +++ .../api/fir/sessions/LLFirSessionFactory.kt | 193 ++---------------- .../sessions/LLFirSessionProviderStorage.kt | 42 ++-- .../level/api/fir/sessions/LibrariesCache.kt | 20 -- 6 files changed, 267 insertions(+), 213 deletions(-) create mode 100644 analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/project/structure/LLFirLibraryProviderFactory.kt create mode 100644 analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/project/structure/LLFirLibrarySessionFactory.kt create mode 100644 analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/project/structure/sessionFactoryHelpers.kt delete mode 100644 analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LibrariesCache.kt diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/project/structure/LLFirLibraryProviderFactory.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/project/structure/LLFirLibraryProviderFactory.kt new file mode 100644 index 00000000000..b51b8ba3678 --- /dev/null +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/project/structure/LLFirLibraryProviderFactory.kt @@ -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) -> GlobalSearchScope + ): List = buildList { + module + .allDirectDependenciesOfType() + .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, + 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 = + moduleDatas.associateWith { moduleData -> + checkIsInstance(moduleData) + val ktBinaryModule = moduleData.ktModule as KtBinaryModule + val moduleBinaryRoots = ktBinaryModule.getBinaryRoots().mapTo(mutableSetOf()) { it.toAbsolutePath() } + LibraryPathFilter.LibraryList(moduleBinaryRoots) + } + + return MultipleModuleDataProvider(moduleDataWithFilters) + } +} \ No newline at end of file diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/project/structure/LLFirLibrarySessionFactory.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/project/structure/LLFirLibrarySessionFactory.kt new file mode 100644 index 00000000000..c43df1c5f38 --- /dev/null +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/project/structure/LLFirLibrarySessionFactory.kt @@ -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() + + 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)) + } + } +} \ No newline at end of file diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/project/structure/sessionFactoryHelpers.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/project/structure/sessionFactoryHelpers.kt new file mode 100644 index 00000000000..827cb79c6c3 --- /dev/null +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/project/structure/sessionFactoryHelpers.kt @@ -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.() -> Unit +): FirCompositeSymbolProvider = + FirCompositeSymbolProvider(session, buildList(builderAction)) diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionFactory.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionFactory.kt index f63adfea9f8..7b4ffb8bdfd 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionFactory.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionFactory.kt @@ -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, 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() - 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) -> GlobalSearchScope - ): List = buildList { - module - .allDirectDependenciesOfType() - .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, - 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 = - moduleDatas.associateWith { moduleData -> - checkIsInstance(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)) // - 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.extractLibraryPaths(): List = diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionProviderStorage.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionProviderStorage.kt index 51ab2a66e89..3021a25b653 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionProviderStorage.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionProviderStorage.kt @@ -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() - private val librariesCache by softCachedValue(project, project.createLibrariesModificationTracker()) { LibrariesCache() } + private val librariesFactoryByUseSiteModule by softCachedValue(project, project.createLibrariesModificationTracker()) { + ConcurrentHashMap() + } 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().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}") } } diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LibrariesCache.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LibrariesCache.kt deleted file mode 100644 index d79da05de4a..00000000000 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LibrariesCache.kt +++ /dev/null @@ -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 = ConcurrentHashMap() -) { - fun cached( - module: KtModule, - create: (KtModule) -> LLFirLibrariesSession - ): LLFirLibrariesSession = - cache.computeIfAbsent(module, create) -}