[LL FIR] do not fail on cycle in module dependencies
This commit is contained in:
+1
-6
@@ -41,12 +41,7 @@ internal class LLFirLibrarySessionFactory(
|
|||||||
ConcurrentHashMap<KtBinaryModule, LLFirLibrarySession>()
|
ConcurrentHashMap<KtBinaryModule, LLFirLibrarySession>()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getLibrarySessionsForModule(module: KtModule): List<LLFirLibraryLikeSession> = buildList {
|
fun getLibrarySession(ktBinaryModule: KtBinaryModule): LLFirLibrarySession {
|
||||||
LLFirBuiltinsSessionFactory.getInstance(project).getBuiltinsSession(module.platform).let(::add)
|
|
||||||
return module.allDirectDependenciesOfType<KtBinaryModule>().mapTo(this) { getLibrarySession(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getLibrarySession(ktBinaryModule: KtBinaryModule): LLFirLibrarySession {
|
|
||||||
return librarySessionByModule.getOrPut(ktBinaryModule) { createModuleLibrariesSession(ktBinaryModule) }
|
return librarySessionByModule.getOrPut(ktBinaryModule) { createModuleLibrariesSession(ktBinaryModule) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+38
-14
@@ -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.FirDependenciesSymbolProvider
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProviderInternals
|
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.FirCallableSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||||
@@ -78,21 +79,15 @@ internal class LLFirModuleWithDependenciesSymbolProvider(
|
|||||||
providers.firstNotNullOfOrNull { it.getPackage(fqName) }
|
providers.firstNotNullOfOrNull { it.getPackage(fqName) }
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class LLFirDependentModuleProviders(
|
internal abstract class LLFirDependentModuleProviders(
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
private val providers: List<FirSymbolProvider>
|
|
||||||
) : FirDependenciesSymbolProvider(session) {
|
) : FirDependenciesSymbolProvider(session) {
|
||||||
|
|
||||||
val dependenciesAsSessions: List<LLFirSession>
|
abstract val dependentProviders: List<FirSymbolProvider>
|
||||||
get() = buildList {
|
abstract val dependentSessions: List<LLFirSession>
|
||||||
providers.mapTo(this) { it.session as LLFirSession }
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(session: FirSession, createSubProviders: MutableList<FirSymbolProvider>.() -> Unit)
|
|
||||||
: this(session, buildList { createSubProviders() })
|
|
||||||
|
|
||||||
override fun getClassLikeSymbolByClassId(classId: ClassId): FirClassLikeSymbol<*>? =
|
override fun getClassLikeSymbolByClassId(classId: ClassId): FirClassLikeSymbol<*>? =
|
||||||
providers.firstNotNullOfOrNull { provider ->
|
dependentProviders.firstNotNullOfOrNull { provider ->
|
||||||
when (provider) {
|
when (provider) {
|
||||||
is LLFirModuleWithDependenciesSymbolProvider -> provider.getClassLikeSymbolByFqNameWithoutDependencies(classId)
|
is LLFirModuleWithDependenciesSymbolProvider -> provider.getClassLikeSymbolByFqNameWithoutDependencies(classId)
|
||||||
else -> provider.getClassLikeSymbolByClassId(classId)
|
else -> provider.getClassLikeSymbolByClassId(classId)
|
||||||
@@ -102,10 +97,11 @@ internal class LLFirDependentModuleProviders(
|
|||||||
|
|
||||||
@FirSymbolProviderInternals
|
@FirSymbolProviderInternals
|
||||||
override fun getTopLevelCallableSymbolsTo(destination: MutableList<FirCallableSymbol<*>>, packageFqName: FqName, name: Name) {
|
override fun getTopLevelCallableSymbolsTo(destination: MutableList<FirCallableSymbol<*>>, packageFqName: FqName, name: Name) {
|
||||||
providers.forEach { provider ->
|
dependentProviders.forEach { provider ->
|
||||||
when (provider) {
|
when (provider) {
|
||||||
is LLFirModuleWithDependenciesSymbolProvider ->
|
is LLFirModuleWithDependenciesSymbolProvider ->
|
||||||
provider.getTopLevelCallableSymbolsToWithoutDependencies(destination, packageFqName, name)
|
provider.getTopLevelCallableSymbolsToWithoutDependencies(destination, packageFqName, name)
|
||||||
|
|
||||||
else -> provider.getTopLevelCallableSymbolsTo(destination, packageFqName, name)
|
else -> provider.getTopLevelCallableSymbolsTo(destination, packageFqName, name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -113,10 +109,11 @@ internal class LLFirDependentModuleProviders(
|
|||||||
|
|
||||||
@FirSymbolProviderInternals
|
@FirSymbolProviderInternals
|
||||||
override fun getTopLevelFunctionSymbolsTo(destination: MutableList<FirNamedFunctionSymbol>, packageFqName: FqName, name: Name) {
|
override fun getTopLevelFunctionSymbolsTo(destination: MutableList<FirNamedFunctionSymbol>, packageFqName: FqName, name: Name) {
|
||||||
providers.forEach { provider ->
|
dependentProviders.forEach { provider ->
|
||||||
when (provider) {
|
when (provider) {
|
||||||
is LLFirModuleWithDependenciesSymbolProvider ->
|
is LLFirModuleWithDependenciesSymbolProvider ->
|
||||||
provider.getTopLevelFunctionSymbolsToWithoutDependencies(destination, packageFqName, name)
|
provider.getTopLevelFunctionSymbolsToWithoutDependencies(destination, packageFqName, name)
|
||||||
|
|
||||||
else -> provider.getTopLevelFunctionSymbolsTo(destination, packageFqName, name)
|
else -> provider.getTopLevelFunctionSymbolsTo(destination, packageFqName, name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -124,20 +121,47 @@ internal class LLFirDependentModuleProviders(
|
|||||||
|
|
||||||
@FirSymbolProviderInternals
|
@FirSymbolProviderInternals
|
||||||
override fun getTopLevelPropertySymbolsTo(destination: MutableList<FirPropertySymbol>, packageFqName: FqName, name: Name) {
|
override fun getTopLevelPropertySymbolsTo(destination: MutableList<FirPropertySymbol>, packageFqName: FqName, name: Name) {
|
||||||
providers.forEach { provider ->
|
dependentProviders.forEach { provider ->
|
||||||
when (provider) {
|
when (provider) {
|
||||||
is LLFirModuleWithDependenciesSymbolProvider ->
|
is LLFirModuleWithDependenciesSymbolProvider ->
|
||||||
provider.getTopLevelPropertySymbolsToWithoutDependencies(destination, packageFqName, name)
|
provider.getTopLevelPropertySymbolsToWithoutDependencies(destination, packageFqName, name)
|
||||||
|
|
||||||
else -> provider.getTopLevelPropertySymbolsTo(destination, packageFqName, name)
|
else -> provider.getTopLevelPropertySymbolsTo(destination, packageFqName, name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getPackage(fqName: FqName): FqName? =
|
override fun getPackage(fqName: FqName): FqName? =
|
||||||
providers.firstNotNullOfOrNull { provider ->
|
dependentProviders.firstNotNullOfOrNull { provider ->
|
||||||
when (provider) {
|
when (provider) {
|
||||||
is LLFirModuleWithDependenciesSymbolProvider -> provider.getPackageWithoutDependencies(fqName)
|
is LLFirModuleWithDependenciesSymbolProvider -> provider.getPackageWithoutDependencies(fqName)
|
||||||
else -> provider.getPackage(fqName)
|
else -> provider.getPackage(fqName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class LLFirDependentModuleProvidersBySessions(
|
||||||
|
session: FirSession,
|
||||||
|
override val dependentSessions: List<LLFirSession>
|
||||||
|
) : LLFirDependentModuleProviders(session) {
|
||||||
|
|
||||||
|
override val dependentProviders: List<FirSymbolProvider> by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||||
|
dependentSessions.map { it.symbolProvider }
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(session: FirSession, createSessions: MutableList<LLFirSession>.() -> Unit)
|
||||||
|
: this(session, buildList { createSessions() })
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal class LLFirDependentModuleProvidersByProviders(
|
||||||
|
session: FirSession,
|
||||||
|
override val dependentProviders: List<FirSymbolProvider>,
|
||||||
|
) : LLFirDependentModuleProviders(session) {
|
||||||
|
|
||||||
|
override val dependentSessions: List<LLFirSession>
|
||||||
|
get() = dependentProviders.map { it.session as LLFirSession }
|
||||||
|
|
||||||
|
constructor(session: FirSession, createProviders: MutableList<FirSymbolProvider>.() -> Unit)
|
||||||
|
: this(session, buildList { createProviders() })
|
||||||
|
}
|
||||||
|
|||||||
+24
-17
@@ -55,6 +55,8 @@ internal object LLFirSessionFactory {
|
|||||||
): LLFirSourcesSession {
|
): LLFirSourcesSession {
|
||||||
sessionsCache[module]?.let { return it as LLFirSourcesSession }
|
sessionsCache[module]?.let { return it as LLFirSourcesSession }
|
||||||
val platform = module.platform
|
val platform = module.platform
|
||||||
|
val builtinsSession = LLFirBuiltinsSessionFactory.getInstance(project).getBuiltinsSession(platform)
|
||||||
|
|
||||||
val languageVersionSettings = object : LanguageVersionSettings by module.languageVersionSettings {
|
val languageVersionSettings = object : LanguageVersionSettings by module.languageVersionSettings {
|
||||||
override fun getFeatureSupport(feature: LanguageFeature): LanguageFeature.State =
|
override fun getFeatureSupport(feature: LanguageFeature): LanguageFeature.State =
|
||||||
if (feature == LanguageFeature.EnableDfaWarningsInK2) LanguageFeature.State.ENABLED
|
if (feature == LanguageFeature.EnableDfaWarningsInK2) LanguageFeature.State.ENABLED
|
||||||
@@ -71,12 +73,11 @@ internal object LLFirSessionFactory {
|
|||||||
val components = LLFirModuleResolveComponents(module, globalResolveComponents, scopeProvider)
|
val components = LLFirModuleResolveComponents(module, globalResolveComponents, scopeProvider)
|
||||||
|
|
||||||
val contentScope = module.contentScope
|
val contentScope = module.contentScope
|
||||||
val dependentModules = module.directRegularDependenciesOfType<KtSourceModule>()
|
|
||||||
val session = LLFirSourcesSession(
|
val session = LLFirSourcesSession(
|
||||||
module,
|
module,
|
||||||
project,
|
project,
|
||||||
components,
|
components,
|
||||||
LLFirBuiltinsSessionFactory.getInstance(project).getBuiltinsSession(platform).builtinTypes
|
builtinsSession.builtinTypes
|
||||||
)
|
)
|
||||||
sessionsCache[module] = session
|
sessionsCache[module] = session
|
||||||
components.session = session
|
components.session = session
|
||||||
@@ -109,21 +110,27 @@ internal object LLFirSessionFactory {
|
|||||||
register(FirSwitchableExtensionDeclarationsSymbolProvider::class, it)
|
register(FirSwitchableExtensionDeclarationsSymbolProvider::class, it)
|
||||||
}
|
}
|
||||||
|
|
||||||
val dependencyProvider = LLFirDependentModuleProviders(this) {
|
val dependencyProvider = LLFirDependentModuleProvidersBySessions(this) {
|
||||||
librariesSessionFactory.getLibrarySessionsForModule(module).mapTo(this) { it.symbolProvider }
|
module.directRegularDependencies.mapNotNullTo(this) { dependency ->
|
||||||
dependentModules
|
when (dependency) {
|
||||||
.mapTo(this) { dependentSourceModule ->
|
is KtBuiltinsModule -> null // build in is already added
|
||||||
val dependentSourceSession = createSourcesSession(
|
is KtBinaryModule -> LLFirLibrarySessionFactory.getInstance(project).getLibrarySession(dependency)
|
||||||
project,
|
is KtSourceModule -> {
|
||||||
dependentSourceModule,
|
createSourcesSession(
|
||||||
globalResolveComponents,
|
project,
|
||||||
sessionInvalidator,
|
dependency,
|
||||||
sessionsCache,
|
globalResolveComponents,
|
||||||
librariesSessionFactory = librariesSessionFactory,
|
sessionInvalidator,
|
||||||
configureSession = configureSession,
|
sessionsCache,
|
||||||
)
|
librariesSessionFactory = librariesSessionFactory,
|
||||||
dependentSourceSession.symbolProvider
|
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)
|
val javaSymbolProvider = createJavaSymbolProvider(this, moduleData, project, contentScope)
|
||||||
@@ -205,7 +212,7 @@ internal object LLFirSessionFactory {
|
|||||||
register(FirRegisteredPluginAnnotations::class, LLFirIdeRegisteredPluginAnnotations(this@session, annotationsResolver))
|
register(FirRegisteredPluginAnnotations::class, LLFirIdeRegisteredPluginAnnotations(this@session, annotationsResolver))
|
||||||
register(FirPredicateBasedProvider::class, FirEmptyPredicateBasedProvider())
|
register(FirPredicateBasedProvider::class, FirEmptyPredicateBasedProvider())
|
||||||
|
|
||||||
val dependencyProvider = LLFirDependentModuleProviders(this) {
|
val dependencyProvider = LLFirDependentModuleProvidersByProviders(this) {
|
||||||
// <all libraries scope> - <current library scope>
|
// <all libraries scope> - <current library scope>
|
||||||
val librariesSearchScope =
|
val librariesSearchScope =
|
||||||
ProjectScope.getLibrariesScope(project).intersectWith(GlobalSearchScope.notScope(libraryModule.contentScope))
|
ProjectScope.getLibrariesScope(project).intersectWith(GlobalSearchScope.notScope(libraryModule.contentScope))
|
||||||
|
|||||||
+1
-1
@@ -24,7 +24,7 @@ class LLFirSessionProvider internal constructor(
|
|||||||
) : FirSessionProvider() {
|
) : FirSessionProvider() {
|
||||||
|
|
||||||
private val moduleToSession = moduleToResolvableSession + moduleToResolvableSession.values.flatMap { module ->
|
private val moduleToSession = moduleToResolvableSession + moduleToResolvableSession.values.flatMap { module ->
|
||||||
(module.dependenciesSymbolProvider as LLFirDependentModuleProviders).dependenciesAsSessions
|
(module.dependenciesSymbolProvider as LLFirDependentModuleProviders).dependentSessions
|
||||||
}.associateBy { it.ktModule }
|
}.associateBy { it.ktModule }
|
||||||
|
|
||||||
override fun getSession(moduleData: FirModuleData): LLFirSession {
|
override fun getSession(moduleData: FirModuleData): LLFirSession {
|
||||||
|
|||||||
Reference in New Issue
Block a user