[LL FIR] KT-57743 Build dependency symbol providers lazily
- Because `KtModule`s and thereby sessions may depend on each other cyclically, we must not create a session during the creation of another session. Otherwise, let's say session A and B depend on each other. Then we get the following nested creation: session A -> session B -> session A -> session B, and so on. - Dependency symbol providers are in part taken from dependency sessions. Hence, we have to create dependency symbol providers lazily. - For the creation of dependency symbol providers we only need to access the non-dependency symbol providers of a session dependency, so we don't need to access the dependency's dependency symbol providers. Hence, the lazy construction won't run into issues with cycles later on. ^KT-57743 fixed
This commit is contained in:
committed by
Space Team
parent
2d279c5f25
commit
abc1be2ee0
+12
-5
@@ -104,12 +104,19 @@ internal class LLFirModuleWithDependenciesSymbolProvider(
|
|||||||
|
|
||||||
internal class LLFirDependenciesSymbolProvider(
|
internal class LLFirDependenciesSymbolProvider(
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
val providers: List<FirSymbolProvider>,
|
val computeProviders: () -> List<FirSymbolProvider>,
|
||||||
) : FirSymbolProvider(session) {
|
) : FirSymbolProvider(session) {
|
||||||
init {
|
/**
|
||||||
require(providers.all { it !is LLFirModuleWithDependenciesSymbolProvider }) {
|
* Dependency symbol providers are lazy to support cyclic dependencies between modules. If a module A and a module B depend on each
|
||||||
"${LLFirDependenciesSymbolProvider::class.simpleName} may not contain ${LLFirModuleWithDependenciesSymbolProvider::class.simpleName}:" +
|
* other and session creation tries to access dependency symbol providers eagerly, the creation of session A would try to create session
|
||||||
" dependency providers must be flattened during session creation."
|
* B (to get its symbol providers), which in turn would try to create session A, and so on.
|
||||||
|
*/
|
||||||
|
val providers: List<FirSymbolProvider> by lazy {
|
||||||
|
computeProviders().also { providers ->
|
||||||
|
require(providers.all { it !is LLFirModuleWithDependenciesSymbolProvider }) {
|
||||||
|
"${LLFirDependenciesSymbolProvider::class.simpleName} may not contain ${LLFirModuleWithDependenciesSymbolProvider::class.simpleName}:" +
|
||||||
|
" dependency providers must be flattened during session creation."
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+33
-30
@@ -80,7 +80,7 @@ internal abstract class LLFirAbstractSessionFactory(protected val project: Proje
|
|||||||
builtinTypes,
|
builtinTypes,
|
||||||
scope
|
scope
|
||||||
),
|
),
|
||||||
LLFirDependenciesSymbolProvider(session, listOf(builtinSymbolProvider)),
|
LLFirDependenciesSymbolProvider(session) { listOf(builtinSymbolProvider) },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,8 +101,6 @@ internal abstract class LLFirAbstractSessionFactory(protected val project: Proje
|
|||||||
|
|
||||||
val components = LLFirModuleResolveComponents(module, globalResolveComponents, scopeProvider)
|
val components = LLFirModuleResolveComponents(module, globalResolveComponents, scopeProvider)
|
||||||
|
|
||||||
val dependencies = collectSourceModuleDependencies(module)
|
|
||||||
|
|
||||||
val session = LLFirScriptSession(module, components, builtinsSession.builtinTypes)
|
val session = LLFirScriptSession(module, components, builtinsSession.builtinTypes)
|
||||||
components.session = session
|
components.session = session
|
||||||
|
|
||||||
@@ -130,10 +128,12 @@ internal abstract class LLFirAbstractSessionFactory(protected val project: Proje
|
|||||||
register(FirProvider::class, provider)
|
register(FirProvider::class, provider)
|
||||||
register(FirLazyDeclarationResolver::class, LLFirLazyDeclarationResolver())
|
register(FirLazyDeclarationResolver::class, LLFirLazyDeclarationResolver())
|
||||||
|
|
||||||
val dependencyProvider = LLFirDependenciesSymbolProvider(this, buildList {
|
val dependencyProvider = LLFirDependenciesSymbolProvider(this) {
|
||||||
addDependencySymbolProvidersTo(session, dependencies, this)
|
buildList {
|
||||||
add(builtinsSession.symbolProvider)
|
addDependencySymbolProvidersTo(session, collectSourceModuleDependencies(module), this)
|
||||||
})
|
add(builtinsSession.symbolProvider)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val javaSymbolProvider = LLFirJavaSymbolProvider(this, moduleData, project, provider.searchScope)
|
val javaSymbolProvider = LLFirJavaSymbolProvider(this, moduleData, project, provider.searchScope)
|
||||||
register(JavaSymbolProvider::class, javaSymbolProvider)
|
register(JavaSymbolProvider::class, javaSymbolProvider)
|
||||||
@@ -212,7 +212,7 @@ internal abstract class LLFirAbstractSessionFactory(protected val project: Proje
|
|||||||
register(FirProvider::class, provider)
|
register(FirProvider::class, provider)
|
||||||
register(FirLazyDeclarationResolver::class, LLFirLazyDeclarationResolver())
|
register(FirLazyDeclarationResolver::class, LLFirLazyDeclarationResolver())
|
||||||
|
|
||||||
val dependencyProvider = LLFirDependenciesSymbolProvider(this, listOf(builtinsSession.symbolProvider))
|
val dependencyProvider = LLFirDependenciesSymbolProvider(this) { listOf(builtinsSession.symbolProvider) }
|
||||||
|
|
||||||
register(
|
register(
|
||||||
FirSymbolProvider::class,
|
FirSymbolProvider::class,
|
||||||
@@ -254,7 +254,6 @@ internal abstract class LLFirAbstractSessionFactory(protected val project: Proje
|
|||||||
|
|
||||||
val components = LLFirModuleResolveComponents(module, globalResolveComponents, scopeProvider)
|
val components = LLFirModuleResolveComponents(module, globalResolveComponents, scopeProvider)
|
||||||
|
|
||||||
val dependencies = collectSourceModuleDependencies(module)
|
|
||||||
val session = LLFirSourcesSession(module, components, builtinsSession.builtinTypes)
|
val session = LLFirSourcesSession(module, components, builtinsSession.builtinTypes)
|
||||||
components.session = session
|
components.session = session
|
||||||
|
|
||||||
@@ -284,10 +283,12 @@ internal abstract class LLFirAbstractSessionFactory(protected val project: Proje
|
|||||||
registerCompilerPluginExtensions(project, module)
|
registerCompilerPluginExtensions(project, module)
|
||||||
registerCommonComponentsAfterExtensionsAreConfigured()
|
registerCommonComponentsAfterExtensionsAreConfigured()
|
||||||
|
|
||||||
val dependencyProvider = LLFirDependenciesSymbolProvider(this, buildList {
|
val dependencyProvider = LLFirDependenciesSymbolProvider(this) {
|
||||||
addDependencySymbolProvidersTo(session, dependencies, this)
|
buildList {
|
||||||
add(builtinsSession.symbolProvider)
|
addDependencySymbolProvidersTo(session, collectSourceModuleDependencies(module), this)
|
||||||
})
|
add(builtinsSession.symbolProvider)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
register(DEPENDENCIES_SYMBOL_PROVIDER_QUALIFIED_KEY, dependencyProvider)
|
register(DEPENDENCIES_SYMBOL_PROVIDER_QUALIFIED_KEY, dependencyProvider)
|
||||||
register(LLFirFirClassByPsiClassProvider::class, LLFirFirClassByPsiClassProvider(this))
|
register(LLFirFirClassByPsiClassProvider::class, LLFirFirClassByPsiClassProvider(this))
|
||||||
@@ -372,30 +373,32 @@ internal abstract class LLFirAbstractSessionFactory(protected val project: Proje
|
|||||||
register(FirRegisteredPluginAnnotations::class, LLFirIdeRegisteredPluginAnnotations(this, annotationsResolver))
|
register(FirRegisteredPluginAnnotations::class, LLFirIdeRegisteredPluginAnnotations(this, annotationsResolver))
|
||||||
register(FirPredicateBasedProvider::class, FirEmptyPredicateBasedProvider)
|
register(FirPredicateBasedProvider::class, FirEmptyPredicateBasedProvider)
|
||||||
|
|
||||||
val dependencyProvider = LLFirDependenciesSymbolProvider(this, buildList {
|
val dependencyProvider = LLFirDependenciesSymbolProvider(this) {
|
||||||
add(builtinsSession.symbolProvider)
|
buildList {
|
||||||
|
add(builtinsSession.symbolProvider)
|
||||||
|
|
||||||
// Script dependencies are self-contained and should not depend on other libraries
|
// Script dependencies are self-contained and should not depend on other libraries
|
||||||
if (module !is KtScriptDependencyModule) {
|
if (module !is KtScriptDependencyModule) {
|
||||||
// Add all libraries excluding the current one
|
// Add all libraries excluding the current one
|
||||||
val librariesSearchScope = ProjectScope.getLibrariesScope(project)
|
val librariesSearchScope = ProjectScope.getLibrariesScope(project)
|
||||||
.intersectWith(GlobalSearchScope.notScope(libraryModule.contentScope))
|
.intersectWith(GlobalSearchScope.notScope(libraryModule.contentScope))
|
||||||
|
|
||||||
val restLibrariesProvider = createProjectLibraryProvidersForScope(
|
val restLibrariesProvider = createProjectLibraryProvidersForScope(
|
||||||
session, moduleData, scopeProvider,
|
session, moduleData, scopeProvider,
|
||||||
project, builtinTypes, librariesSearchScope
|
project, builtinTypes, librariesSearchScope
|
||||||
)
|
)
|
||||||
|
|
||||||
addAll(restLibrariesProvider)
|
addAll(restLibrariesProvider)
|
||||||
|
|
||||||
moduleAnchorSession?.let {
|
moduleAnchorSession?.let {
|
||||||
(it.symbolProvider as LLFirModuleWithDependenciesSymbolProvider).also { moduleSymbolProvider ->
|
(it.symbolProvider as LLFirModuleWithDependenciesSymbolProvider).also { moduleSymbolProvider ->
|
||||||
addAll(moduleSymbolProvider.providers)
|
addAll(moduleSymbolProvider.providers)
|
||||||
addAll(moduleSymbolProvider.dependencyProvider.providers)
|
addAll(moduleSymbolProvider.dependencyProvider.providers)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
register(DEPENDENCIES_SYMBOL_PROVIDER_QUALIFIED_KEY, dependencyProvider)
|
register(DEPENDENCIES_SYMBOL_PROVIDER_QUALIFIED_KEY, dependencyProvider)
|
||||||
register(LLFirFirClassByPsiClassProvider::class, LLFirFirClassByPsiClassProvider(this))
|
register(LLFirFirClassByPsiClassProvider::class, LLFirFirClassByPsiClassProvider(this))
|
||||||
|
|||||||
Reference in New Issue
Block a user