@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.fir.resolve.providers.impl.*
20
20
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
21
21
import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
22
22
import org.jetbrains.kotlin.name.Name
23
+ import org.jetbrains.kotlin.utils.addToStdlib.plusIfNotNull
23
24
24
25
/* *
25
26
* This is the base class for factories, which create various sessions for compilation.
@@ -160,7 +161,16 @@ abstract class FirAbstractSessionFactory<LIBRARY_CONTEXT, SOURCE_CONTEXT> {
160
161
registerCommonComponentsAfterExtensionsAreConfigured()
161
162
162
163
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()
164
174
165
175
val symbolProvider = FirCachingCompositeSymbolProvider (this , providersWithShared)
166
176
register(FirSymbolProvider ::class , symbolProvider)
@@ -188,8 +198,7 @@ abstract class FirAbstractSessionFactory<LIBRARY_CONTEXT, SOURCE_CONTEXT> {
188
198
createProviders : (
189
199
FirSession , FirKotlinScopeProvider , FirSymbolProvider ,
190
200
FirSwitchableExtensionDeclarationsSymbolProvider ? ,
191
- dependencies: List <FirSymbolProvider >,
192
- ) -> List <FirSymbolProvider >
201
+ ) -> SourceProviders
193
202
): FirSession {
194
203
val languageVersionSettings = configuration.languageVersionSettings
195
204
return FirCliSession (sessionProvider, FirSession .Kind .Source ).apply session@{
@@ -225,30 +234,52 @@ abstract class FirAbstractSessionFactory<LIBRARY_CONTEXT, SOURCE_CONTEXT> {
225
234
}.configure()
226
235
registerCommonComponentsAfterExtensionsAreConfigured()
227
236
228
- val dependencyProviders = computeDependencyProviderList(moduleData)
237
+ val structuredDependencyProvidersWithoutSource = computeDependencyProviderList(moduleData)
229
238
val generatedSymbolsProvider = FirSwitchableExtensionDeclarationsSymbolProvider .createIfNeeded(this )
230
239
231
- val providers = createProviders(
240
+ val (sourceProviders, additionalOptionalAnnotationsProvider) = createProviders(
232
241
this ,
233
242
kotlinScopeProvider,
234
243
firProvider.symbolProvider,
235
244
generatedSymbolsProvider,
236
- dependencyProviders,
237
245
)
238
246
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
+
239
262
register(
240
263
FirSymbolProvider ::class ,
241
264
FirCachingCompositeSymbolProvider (
242
- this , providers ,
265
+ this , providersList ,
243
266
expectedCachesToBeCleanedOnce = generatedSymbolsProvider != null
244
267
)
245
268
)
246
269
247
270
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
+ )
249
275
}
250
276
}
251
277
278
+ protected data class SourceProviders (
279
+ val sourceProviders : List <FirSymbolProvider >,
280
+ val additionalOptionalAnnotationsProvider : FirSymbolProvider ? = null ,
281
+ )
282
+
252
283
protected abstract fun createKotlinScopeProviderForSourceSession (
253
284
moduleData : FirModuleData , languageVersionSettings : LanguageVersionSettings
254
285
): FirKotlinScopeProvider
@@ -261,21 +292,42 @@ abstract class FirAbstractSessionFactory<LIBRARY_CONTEXT, SOURCE_CONTEXT> {
261
292
262
293
// ==================================== Utilities ====================================
263
294
264
- private fun FirSession. computeDependencyProviderList (moduleData : FirModuleData ): List < FirSymbolProvider > {
295
+ private fun computeDependencyProviderList (moduleData : FirModuleData ): StructuredProviders {
265
296
// dependsOnDependencies can actualize declarations from their dependencies. Because actual declarations can be more specific
266
297
// (e.g. have additional supertypes), the modules must be ordered from most specific (i.e. actual) to most generic (i.e. expect)
267
298
// 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)
272
301
.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
+ )
273
325
}
274
326
275
327
/* It eliminates dependency and composite providers since the current dependency provider is composite in fact.
276
328
* To prevent duplications and resolving errors, library or source providers from other modules should be filtered out during flattening.
277
329
* 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 > {
279
331
val originalSession = session.takeIf { it.kind == FirSession .Kind .Source }
280
332
val result = mutableListOf<FirSymbolProvider >()
281
333
0 commit comments