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 index 471c52ecc43..f4d28dd78ca 100644 --- 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 @@ -41,12 +41,7 @@ internal class LLFirLibrarySessionFactory( ConcurrentHashMap() } - fun getLibrarySessionsForModule(module: KtModule): List = buildList { - LLFirBuiltinsSessionFactory.getInstance(project).getBuiltinsSession(module.platform).let(::add) - return module.allDirectDependenciesOfType().mapTo(this) { getLibrarySession(it) } - } - - private fun getLibrarySession(ktBinaryModule: KtBinaryModule): LLFirLibrarySession { + fun getLibrarySession(ktBinaryModule: KtBinaryModule): LLFirLibrarySession { return librarySessionByModule.getOrPut(ktBinaryModule) { createModuleLibrariesSession(ktBinaryModule) } } diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/providers/LLFirModuleWithDependenciesSymbolProvider.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/providers/LLFirModuleWithDependenciesSymbolProvider.kt index 3664f13ba19..47187f5801f 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/providers/LLFirModuleWithDependenciesSymbolProvider.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/providers/LLFirModuleWithDependenciesSymbolProvider.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.resolve.providers.FirDependenciesSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProviderInternals +import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol @@ -78,21 +79,15 @@ internal class LLFirModuleWithDependenciesSymbolProvider( providers.firstNotNullOfOrNull { it.getPackage(fqName) } } -internal class LLFirDependentModuleProviders( +internal abstract class LLFirDependentModuleProviders( session: FirSession, - private val providers: List ) : FirDependenciesSymbolProvider(session) { - val dependenciesAsSessions: List - get() = buildList { - providers.mapTo(this) { it.session as LLFirSession } - } - - constructor(session: FirSession, createSubProviders: MutableList.() -> Unit) - : this(session, buildList { createSubProviders() }) + abstract val dependentProviders: List + abstract val dependentSessions: List override fun getClassLikeSymbolByClassId(classId: ClassId): FirClassLikeSymbol<*>? = - providers.firstNotNullOfOrNull { provider -> + dependentProviders.firstNotNullOfOrNull { provider -> when (provider) { is LLFirModuleWithDependenciesSymbolProvider -> provider.getClassLikeSymbolByFqNameWithoutDependencies(classId) else -> provider.getClassLikeSymbolByClassId(classId) @@ -102,10 +97,11 @@ internal class LLFirDependentModuleProviders( @FirSymbolProviderInternals override fun getTopLevelCallableSymbolsTo(destination: MutableList>, packageFqName: FqName, name: Name) { - providers.forEach { provider -> + dependentProviders.forEach { provider -> when (provider) { is LLFirModuleWithDependenciesSymbolProvider -> provider.getTopLevelCallableSymbolsToWithoutDependencies(destination, packageFqName, name) + else -> provider.getTopLevelCallableSymbolsTo(destination, packageFqName, name) } } @@ -113,10 +109,11 @@ internal class LLFirDependentModuleProviders( @FirSymbolProviderInternals override fun getTopLevelFunctionSymbolsTo(destination: MutableList, packageFqName: FqName, name: Name) { - providers.forEach { provider -> + dependentProviders.forEach { provider -> when (provider) { is LLFirModuleWithDependenciesSymbolProvider -> provider.getTopLevelFunctionSymbolsToWithoutDependencies(destination, packageFqName, name) + else -> provider.getTopLevelFunctionSymbolsTo(destination, packageFqName, name) } } @@ -124,20 +121,47 @@ internal class LLFirDependentModuleProviders( @FirSymbolProviderInternals override fun getTopLevelPropertySymbolsTo(destination: MutableList, packageFqName: FqName, name: Name) { - providers.forEach { provider -> + dependentProviders.forEach { provider -> when (provider) { is LLFirModuleWithDependenciesSymbolProvider -> provider.getTopLevelPropertySymbolsToWithoutDependencies(destination, packageFqName, name) + else -> provider.getTopLevelPropertySymbolsTo(destination, packageFqName, name) } } } override fun getPackage(fqName: FqName): FqName? = - providers.firstNotNullOfOrNull { provider -> + dependentProviders.firstNotNullOfOrNull { provider -> when (provider) { is LLFirModuleWithDependenciesSymbolProvider -> provider.getPackageWithoutDependencies(fqName) else -> provider.getPackage(fqName) } } } + +internal class LLFirDependentModuleProvidersBySessions( + session: FirSession, + override val dependentSessions: List +) : LLFirDependentModuleProviders(session) { + + override val dependentProviders: List by lazy(LazyThreadSafetyMode.PUBLICATION) { + dependentSessions.map { it.symbolProvider } + } + + constructor(session: FirSession, createSessions: MutableList.() -> Unit) + : this(session, buildList { createSessions() }) +} + + +internal class LLFirDependentModuleProvidersByProviders( + session: FirSession, + override val dependentProviders: List, +) : LLFirDependentModuleProviders(session) { + + override val dependentSessions: List + get() = dependentProviders.map { it.session as LLFirSession } + + constructor(session: FirSession, createProviders: MutableList.() -> Unit) + : this(session, buildList { createProviders() }) +} 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 b1e0cb1a935..07d60f4381e 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 @@ -55,6 +55,8 @@ internal object LLFirSessionFactory { ): LLFirSourcesSession { sessionsCache[module]?.let { return it as LLFirSourcesSession } val platform = module.platform + val builtinsSession = LLFirBuiltinsSessionFactory.getInstance(project).getBuiltinsSession(platform) + val languageVersionSettings = object : LanguageVersionSettings by module.languageVersionSettings { override fun getFeatureSupport(feature: LanguageFeature): LanguageFeature.State = if (feature == LanguageFeature.EnableDfaWarningsInK2) LanguageFeature.State.ENABLED @@ -71,12 +73,11 @@ internal object LLFirSessionFactory { val components = LLFirModuleResolveComponents(module, globalResolveComponents, scopeProvider) val contentScope = module.contentScope - val dependentModules = module.directRegularDependenciesOfType() val session = LLFirSourcesSession( module, project, components, - LLFirBuiltinsSessionFactory.getInstance(project).getBuiltinsSession(platform).builtinTypes + builtinsSession.builtinTypes ) sessionsCache[module] = session components.session = session @@ -109,21 +110,27 @@ internal object LLFirSessionFactory { register(FirSwitchableExtensionDeclarationsSymbolProvider::class, it) } - val dependencyProvider = LLFirDependentModuleProviders(this) { - librariesSessionFactory.getLibrarySessionsForModule(module).mapTo(this) { it.symbolProvider } - dependentModules - .mapTo(this) { dependentSourceModule -> - val dependentSourceSession = createSourcesSession( - project, - dependentSourceModule, - globalResolveComponents, - sessionInvalidator, - sessionsCache, - librariesSessionFactory = librariesSessionFactory, - configureSession = configureSession, - ) - dependentSourceSession.symbolProvider + val dependencyProvider = LLFirDependentModuleProvidersBySessions(this) { + module.directRegularDependencies.mapNotNullTo(this) { dependency -> + when (dependency) { + is KtBuiltinsModule -> null // build in is already added + is KtBinaryModule -> LLFirLibrarySessionFactory.getInstance(project).getLibrarySession(dependency) + is KtSourceModule -> { + createSourcesSession( + project, + dependency, + globalResolveComponents, + sessionInvalidator, + sessionsCache, + librariesSessionFactory = librariesSessionFactory, + configureSession = configureSession, + ) + } + is KtNotUnderContentRootModule -> error("Module $module cannot depend on ${dependency::class}: $dependency") + is KtLibrarySourceModule -> error("Module $module cannot depend on ${dependency::class}: $dependency") } + } + add(builtinsSession) } val javaSymbolProvider = createJavaSymbolProvider(this, moduleData, project, contentScope) @@ -205,7 +212,7 @@ internal object LLFirSessionFactory { register(FirRegisteredPluginAnnotations::class, LLFirIdeRegisteredPluginAnnotations(this@session, annotationsResolver)) register(FirPredicateBasedProvider::class, FirEmptyPredicateBasedProvider()) - val dependencyProvider = LLFirDependentModuleProviders(this) { + val dependencyProvider = LLFirDependentModuleProvidersByProviders(this) { // - val librariesSearchScope = ProjectScope.getLibrariesScope(project).intersectWith(GlobalSearchScope.notScope(libraryModule.contentScope)) diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionProvider.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionProvider.kt index e757929a517..691ce10d7df 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionProvider.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionProvider.kt @@ -24,7 +24,7 @@ class LLFirSessionProvider internal constructor( ) : FirSessionProvider() { private val moduleToSession = moduleToResolvableSession + moduleToResolvableSession.values.flatMap { module -> - (module.dependenciesSymbolProvider as LLFirDependentModuleProviders).dependenciesAsSessions + (module.dependenciesSymbolProvider as LLFirDependentModuleProviders).dependentSessions }.associateBy { it.ktModule } override fun getSession(moduleData: FirModuleData): LLFirSession {