Skip to content

Commit e90df20

Browse files
demiurg906Space Team
authored and
Space Team
committed
[FIR] Refactor symbol providers setup for source sessions
- Create only source providers instead of the full list of providers at the call-sites of `FirAbstractSessionFactory.createSourceSession` - Store providers of a session grouped by kind (source/dependency/shared). It makes creating the resulting provider for session more convenient. Also, it would be helpful during creation of deduplicating provider in the scope of KT-75268
1 parent 0e5e144 commit e90df20

File tree

6 files changed

+144
-42
lines changed

6 files changed

+144
-42
lines changed

compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/AbstractFirKlibSessionFactory.kt

+15-14
Original file line numberDiff line numberDiff line change
@@ -123,20 +123,21 @@ abstract class AbstractFirKlibSessionFactory<LIBRARY_CONTEXT, SOURCE_CONTEXT> :
123123
extensionRegistrars,
124124
configuration,
125125
init,
126-
createProviders = { session, kotlinScopeProvider, symbolProvider, generatedSymbolsProvider, dependencies ->
127-
listOfNotNull(
128-
symbolProvider,
129-
generatedSymbolsProvider,
130-
icData?.let {
131-
KlibIcCacheBasedSymbolProvider(
132-
session,
133-
SingleModuleDataProvider(moduleData),
134-
kotlinScopeProvider,
135-
it,
136-
flexibleTypeFactory = createFlexibleTypeFactory(session),
137-
)
138-
},
139-
*dependencies.toTypedArray(),
126+
createProviders = { session, kotlinScopeProvider, symbolProvider, generatedSymbolsProvider ->
127+
SourceProviders(
128+
listOfNotNull(
129+
symbolProvider,
130+
generatedSymbolsProvider,
131+
icData?.let {
132+
KlibIcCacheBasedSymbolProvider(
133+
session,
134+
SingleModuleDataProvider(moduleData),
135+
kotlinScopeProvider,
136+
it,
137+
flexibleTypeFactory = createFlexibleTypeFactory(session),
138+
)
139+
},
140+
)
140141
)
141142
}
142143
)

compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirAbstractSessionFactory.kt

+66-14
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.fir.resolve.providers.impl.*
2020
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
2121
import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
2222
import org.jetbrains.kotlin.name.Name
23+
import org.jetbrains.kotlin.utils.addToStdlib.plusIfNotNull
2324

2425
/**
2526
* This is the base class for factories, which create various sessions for compilation.
@@ -160,7 +161,16 @@ abstract class FirAbstractSessionFactory<LIBRARY_CONTEXT, SOURCE_CONTEXT> {
160161
registerCommonComponentsAfterExtensionsAreConfigured()
161162

162163
val providers = createProviders(this, kotlinScopeProvider)
163-
val providersWithShared = providers + sharedLibrarySession.symbolProvider
164+
register(
165+
StructuredProviders::class,
166+
StructuredProviders(
167+
sourceProviders = emptyList(),
168+
librariesProviders = providers,
169+
sharedProvider = sharedLibrarySession.symbolProvider,
170+
)
171+
)
172+
173+
val providersWithShared = providers + sharedLibrarySession.symbolProvider.flatten()
164174

165175
val symbolProvider = FirCachingCompositeSymbolProvider(this, providersWithShared)
166176
register(FirSymbolProvider::class, symbolProvider)
@@ -188,8 +198,7 @@ abstract class FirAbstractSessionFactory<LIBRARY_CONTEXT, SOURCE_CONTEXT> {
188198
createProviders: (
189199
FirSession, FirKotlinScopeProvider, FirSymbolProvider,
190200
FirSwitchableExtensionDeclarationsSymbolProvider?,
191-
dependencies: List<FirSymbolProvider>,
192-
) -> List<FirSymbolProvider>
201+
) -> SourceProviders
193202
): FirSession {
194203
val languageVersionSettings = configuration.languageVersionSettings
195204
return FirCliSession(sessionProvider, FirSession.Kind.Source).apply session@{
@@ -225,30 +234,52 @@ abstract class FirAbstractSessionFactory<LIBRARY_CONTEXT, SOURCE_CONTEXT> {
225234
}.configure()
226235
registerCommonComponentsAfterExtensionsAreConfigured()
227236

228-
val dependencyProviders = computeDependencyProviderList(moduleData)
237+
val structuredDependencyProvidersWithoutSource = computeDependencyProviderList(moduleData)
229238
val generatedSymbolsProvider = FirSwitchableExtensionDeclarationsSymbolProvider.createIfNeeded(this)
230239

231-
val providers = createProviders(
240+
val (sourceProviders, additionalOptionalAnnotationsProvider) = createProviders(
232241
this,
233242
kotlinScopeProvider,
234243
firProvider.symbolProvider,
235244
generatedSymbolsProvider,
236-
dependencyProviders,
237245
)
238246

247+
val structuredProvidersForModule = StructuredProviders(
248+
sourceProviders = sourceProviders,
249+
librariesProviders = structuredDependencyProvidersWithoutSource.librariesProviders.plusIfNotNull(additionalOptionalAnnotationsProvider),
250+
sharedProvider = structuredDependencyProvidersWithoutSource.sharedProvider,
251+
).also {
252+
register(StructuredProviders::class, it)
253+
}
254+
255+
val providersListWithoutSources = buildList {
256+
structuredProvidersForModule.librariesProviders.flatMapTo(this) { it.flatten() }
257+
addAll(structuredProvidersForModule.sharedProvider.flatten())
258+
}.distinct()
259+
260+
val providersList = structuredProvidersForModule.sourceProviders + providersListWithoutSources
261+
239262
register(
240263
FirSymbolProvider::class,
241264
FirCachingCompositeSymbolProvider(
242-
this, providers,
265+
this, providersList,
243266
expectedCachesToBeCleanedOnce = generatedSymbolsProvider != null
244267
)
245268
)
246269

247270
generatedSymbolsProvider?.let { register(FirSwitchableExtensionDeclarationsSymbolProvider::class, it) }
248-
register(DEPENDENCIES_SYMBOL_PROVIDER_QUALIFIED_KEY, FirCachingCompositeSymbolProvider(this, dependencyProviders))
271+
register(
272+
DEPENDENCIES_SYMBOL_PROVIDER_QUALIFIED_KEY,
273+
FirCachingCompositeSymbolProvider(this, providersListWithoutSources)
274+
)
249275
}
250276
}
251277

278+
protected data class SourceProviders(
279+
val sourceProviders: List<FirSymbolProvider>,
280+
val additionalOptionalAnnotationsProvider: FirSymbolProvider? = null,
281+
)
282+
252283
protected abstract fun createKotlinScopeProviderForSourceSession(
253284
moduleData: FirModuleData, languageVersionSettings: LanguageVersionSettings
254285
): FirKotlinScopeProvider
@@ -261,21 +292,42 @@ abstract class FirAbstractSessionFactory<LIBRARY_CONTEXT, SOURCE_CONTEXT> {
261292

262293
// ==================================== Utilities ====================================
263294

264-
private fun FirSession.computeDependencyProviderList(moduleData: FirModuleData): List<FirSymbolProvider> {
295+
private fun computeDependencyProviderList(moduleData: FirModuleData): StructuredProviders {
265296
// dependsOnDependencies can actualize declarations from their dependencies. Because actual declarations can be more specific
266297
// (e.g. have additional supertypes), the modules must be ordered from most specific (i.e. actual) to most generic (i.e. expect)
267298
// to prevent false positive resolution errors (see KT-57369 for an example).
268-
return (moduleData.dependencies + moduleData.friendDependencies + moduleData.allDependsOnDependencies)
269-
.mapNotNull { sessionProvider?.getSession(it) }
270-
.flatMap { it.symbolProvider.flatten() }
271-
.distinct()
299+
300+
val providersFromDependencies = (moduleData.dependencies + moduleData.friendDependencies + moduleData.allDependsOnDependencies)
272301
.sortedBy { it.session.kind }
302+
.map { it to it.session.structuredProviders }
303+
304+
val dependencyProviders = providersFromDependencies.flatMap { (dependencyModuleData, providers) ->
305+
when (dependencyModuleData.session.kind) {
306+
FirSession.Kind.Library -> providers.librariesProviders.also { check(providers.sourceProviders.isEmpty()) }
307+
308+
// Dependency providers for common and platform modules are basically the same, so there is no need in duplicating them.
309+
FirSession.Kind.Source -> providers.sourceProviders
310+
}
311+
}
312+
313+
// Here we are looking for the first binary dependency to support source-source dependency between
314+
// regular modules.
315+
// TODO(KT-75896): Such dependencies might occur only in old tests, which are not migrated to CLI facades yet.
316+
val sharedProvider = providersFromDependencies
317+
.first { (moduleData, _) -> moduleData.session.kind == FirSession.Kind.Library }
318+
.second.sharedProvider
319+
320+
return StructuredProviders(
321+
sourceProviders = emptyList(),
322+
dependencyProviders,
323+
sharedProvider
324+
)
273325
}
274326

275327
/* It eliminates dependency and composite providers since the current dependency provider is composite in fact.
276328
* To prevent duplications and resolving errors, library or source providers from other modules should be filtered out during flattening.
277329
* It depends on the session's kind of the top-level provider */
278-
private fun FirSymbolProvider.flatten(): List<FirSymbolProvider> {
330+
protected fun FirSymbolProvider.flatten(): List<FirSymbolProvider> {
279331
val originalSession = session.takeIf { it.kind == FirSession.Kind.Source }
280332
val result = mutableListOf<FirSymbolProvider>()
281333

compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirJvmSessionFactory.kt

+13-7
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.fir.java.deserialization.OptionalAnnotationClassesPr
2626
import org.jetbrains.kotlin.fir.resolve.FirJvmActualizingBuiltinSymbolProvider
2727
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
2828
import org.jetbrains.kotlin.fir.resolve.providers.impl.*
29+
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
2930
import org.jetbrains.kotlin.fir.resolve.scopes.wrapScopeWithJvmMapped
3031
import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
3132
import org.jetbrains.kotlin.fir.session.environment.AbstractProjectEnvironment
@@ -159,22 +160,24 @@ object FirJvmSessionFactory : FirAbstractSessionFactory<FirJvmSessionFactory.Lib
159160
extensionRegistrars,
160161
configuration,
161162
init,
162-
createProviders = { session, kotlinScopeProvider, symbolProvider, generatedSymbolsProvider, dependencies ->
163+
createProviders = { session, kotlinScopeProvider, symbolProvider, generatedSymbolsProvider ->
163164
val javaSymbolProvider =
164165
JavaSymbolProvider(session, projectEnvironment.getFirJavaFacade(session, moduleData, javaSourcesScope))
165166
session.register(JavaSymbolProvider::class, javaSymbolProvider)
166167

167168
val incrementalCompilationSymbolProviders = createIncrementalCompilationSymbolProviders(session)
168169

169-
listOfNotNull(
170+
val providers = listOfNotNull(
170171
symbolProvider,
171172
generatedSymbolsProvider,
172173
*(incrementalCompilationSymbolProviders?.previousFirSessionsSymbolProviders?.toTypedArray() ?: emptyArray()),
173174
incrementalCompilationSymbolProviders?.symbolProviderForBinariesFromIncrementalCompilation,
174175
javaSymbolProvider,
175-
initializeForStdlibIfNeeded(projectEnvironment, session, kotlinScopeProvider, dependencies),
176-
*dependencies.toTypedArray(),
177-
incrementalCompilationSymbolProviders?.optionalAnnotationClassesProviderForBinariesFromIncrementalCompilation,
176+
initializeForStdlibIfNeeded(projectEnvironment, session, kotlinScopeProvider),
177+
)
178+
SourceProviders(
179+
providers,
180+
incrementalCompilationSymbolProviders?.optionalAnnotationClassesProviderForBinariesFromIncrementalCompilation
178181
)
179182
}
180183
).also {
@@ -236,14 +239,17 @@ object FirJvmSessionFactory : FirAbstractSessionFactory<FirJvmSessionFactory.Lib
236239
projectEnvironment: AbstractProjectEnvironment,
237240
session: FirSession,
238241
kotlinScopeProvider: FirKotlinScopeProvider,
239-
dependencies: List<FirSymbolProvider>,
240242
): FirSymbolProvider? {
241243
return runIf(session.languageVersionSettings.getFlag(AnalysisFlags.stdlibCompilation) && !session.moduleData.isCommon) {
242244
val kotlinClassFinder = projectEnvironment.getKotlinClassFinder(projectEnvironment.getSearchScopeForProjectLibraries())
243245
val builtinsSymbolProvider = initializeBuiltinsProvider(session, session.moduleData, kotlinScopeProvider, kotlinClassFinder)
244246
if (session.moduleData.dependsOnDependencies.isNotEmpty()) {
245247
runIf(!session.languageVersionSettings.getFlag(JvmAnalysisFlags.expectBuiltinsAsPartOfStdlib)) {
246-
val refinedSourceSymbolProviders = dependencies.filter { it.session.kind == FirSession.Kind.Source }
248+
val refinedSourceSymbolProviders = session.moduleData.dependsOnDependencies
249+
.map { it.session }
250+
.flatMap { it.symbolProvider.flatten() }
251+
.filter { it.session.kind == FirSession.Kind.Source }
252+
.distinct()
247253
FirJvmActualizingBuiltinSymbolProvider(builtinsSymbolProvider, refinedSourceSymbolProviders)
248254
}
249255
} else {

compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirMetadataSessionFactory.kt

+8-7
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ object FirMetadataSessionFactory : FirAbstractSessionFactory<Nothing?, Nothing?>
135135
extensionRegistrars,
136136
configuration,
137137
init,
138-
createProviders = { session, kotlinScopeProvider, symbolProvider, generatedSymbolsProvider, dependencies ->
138+
createProviders = { session, kotlinScopeProvider, symbolProvider, generatedSymbolsProvider ->
139139
var symbolProviderForBinariesFromIncrementalCompilation: MetadataSymbolProvider? = null
140140
incrementalCompilationContext?.let {
141141
val precompiledBinariesPackagePartProvider = it.precompiledBinariesPackagePartProvider
@@ -153,12 +153,13 @@ object FirMetadataSessionFactory : FirAbstractSessionFactory<Nothing?, Nothing?>
153153
}
154154
}
155155

156-
listOfNotNull(
157-
symbolProvider,
158-
*(incrementalCompilationContext?.previousFirSessionsSymbolProviders?.toTypedArray() ?: emptyArray()),
159-
symbolProviderForBinariesFromIncrementalCompilation,
160-
generatedSymbolsProvider,
161-
*dependencies.toTypedArray(),
156+
SourceProviders(
157+
listOfNotNull(
158+
symbolProvider,
159+
*(incrementalCompilationContext?.previousFirSessionsSymbolProviders?.toTypedArray() ?: emptyArray()),
160+
symbolProviderForBinariesFromIncrementalCompilation,
161+
generatedSymbolsProvider,
162+
)
162163
)
163164
}
164165
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright 2010-2025 JetBrains s.r.o. and Kotlin Programming Language contributors.
3+
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
4+
*/
5+
6+
package org.jetbrains.kotlin.fir.session
7+
8+
import org.jetbrains.kotlin.fir.FirSession
9+
import org.jetbrains.kotlin.fir.FirSessionComponent
10+
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
11+
12+
class StructuredProviders(
13+
// source, generated, IC
14+
val sourceProviders: List<FirSymbolProvider>,
15+
// klib/jar deserialized providers
16+
val librariesProviders: List<FirSymbolProvider>,
17+
// buitlins, etc
18+
val sharedProvider: FirSymbolProvider
19+
) : FirSessionComponent {
20+
fun withSourceProviders(sourceProviders: List<FirSymbolProvider>): StructuredProviders = StructuredProviders(
21+
this.sourceProviders + sourceProviders,
22+
librariesProviders,
23+
sharedProvider,
24+
)
25+
26+
operator fun plus(other: StructuredProviders): StructuredProviders = StructuredProviders(
27+
sourceProviders + other.sourceProviders,
28+
librariesProviders + other.librariesProviders,
29+
sharedProvider,
30+
).also {
31+
check(sharedProvider == other.sharedProvider) {
32+
"Shared providers should be the same"
33+
}
34+
}
35+
}
36+
37+
val FirSession.structuredProviders: StructuredProviders by FirSession.sessionComponentAccessor()

core/util.runtime/src/org/jetbrains/kotlin/utils/addToStdlib.kt

+5
Original file line numberDiff line numberDiff line change
@@ -408,3 +408,8 @@ inline fun <T, S> MutableList<T>.assignFrom(other: Iterable<S>, transform: (S) -
408408
fun <T> MutableList<T>.assignFrom(other: Iterable<T>) {
409409
assignFrom(other) { it }
410410
}
411+
412+
fun <T : Any> List<T>.plusIfNotNull(element: T?): List<T> = when (element) {
413+
null -> this
414+
else -> this + element
415+
}

0 commit comments

Comments
 (0)