FIR IDE: fix FirModuleWithDependenciesSymbolProvider recursive calls

This commit is contained in:
Ilya Kirillov
2020-12-28 15:11:26 +01:00
parent 5838357e61
commit a95f38569f
@@ -20,21 +20,27 @@ import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
internal class FirModuleWithDependenciesSymbolProvider( internal class FirModuleWithDependenciesSymbolProvider(
session: FirSession, session: FirSession,
private val providers: List<FirSymbolProvider>, private val providers: List<FirSymbolProvider>,
private val dependentProviders: List<FirSymbolProvider>, dependentProviders: List<FirSymbolProvider>,
) : FirSymbolProvider(session) { ) : FirSymbolProvider(session) {
private val dependentProviders = DependentModuleProviders(session, dependentProviders)
override fun getClassLikeSymbolByFqName(classId: ClassId): FirClassLikeSymbol<*>? = override fun getClassLikeSymbolByFqName(classId: ClassId): FirClassLikeSymbol<*>? =
getClassLikeSymbolByFqNameWithoutDependencies(classId)
?: dependentProviders.getClassLikeSymbolByFqName(classId)
fun getClassLikeSymbolByFqNameWithoutDependencies(classId: ClassId): FirClassLikeSymbol<*>? =
providers.firstNotNullResult { it.getClassLikeSymbolByFqName(classId) } providers.firstNotNullResult { it.getClassLikeSymbolByFqName(classId) }
?: withDependent(default = null) {
dependentProviders.firstNotNullResult { it.getClassLikeSymbolByFqName(classId) }
}
@FirSymbolProviderInternals @FirSymbolProviderInternals
override fun getTopLevelCallableSymbolsTo(destination: MutableList<FirCallableSymbol<*>>, packageFqName: FqName, name: Name) { override fun getTopLevelCallableSymbolsTo(destination: MutableList<FirCallableSymbol<*>>, packageFqName: FqName, name: Name) {
providers.flatMapTo(destination) { it.getTopLevelCallableSymbols(packageFqName, name) } getTopLevelCallableSymbolsToWithoutDependencies(destination, packageFqName, name)
withDependent { dependentProviders.getTopLevelCallableSymbolsTo(destination, packageFqName, name)
dependentProviders.flatMapTo(destination) { it.getTopLevelCallableSymbols(packageFqName, name) }
} }
@FirSymbolProviderInternals
fun getTopLevelCallableSymbolsToWithoutDependencies(destination: MutableList<FirCallableSymbol<*>>, packageFqName: FqName, name: Name) {
providers.forEach { it.getTopLevelCallableSymbolsTo(destination, packageFqName, name) }
} }
@FirSymbolProviderInternals @FirSymbolProviderInternals
@@ -54,28 +60,40 @@ internal class FirModuleWithDependenciesSymbolProvider(
} }
override fun getPackage(fqName: FqName): FqName? = override fun getPackage(fqName: FqName): FqName? =
getPackageWithoutDependencies(fqName)
?: dependentProviders.getPackage(fqName)
fun getPackageWithoutDependencies(fqName: FqName): FqName? =
providers.firstNotNullResult { it.getPackage(fqName) } providers.firstNotNullResult { it.getPackage(fqName) }
?: withDependent(default = null) { }
dependentProviders.firstNotNullResult { it.getPackage(fqName) }
private class DependentModuleProviders(session: FirSession, private val providers: List<FirSymbolProvider>) : FirSymbolProvider(session) {
override fun getClassLikeSymbolByFqName(classId: ClassId): FirClassLikeSymbol<*>? =
providers.firstNotNullResult { provider ->
when (provider) {
is FirModuleWithDependenciesSymbolProvider -> provider.getClassLikeSymbolByFqNameWithoutDependencies(classId)
else -> provider.getClassLikeSymbolByFqName(classId)
}
} }
companion object {
private val canUseDependent = ThreadLocal.withInitial { true }
private inline fun <R> withDependent(default: R, action: () -> R): R { @FirSymbolProviderInternals
if (canUseDependent.get()) { override fun getTopLevelCallableSymbolsTo(destination: MutableList<FirCallableSymbol<*>>, packageFqName: FqName, name: Name) {
canUseDependent.set(false) providers.forEach { provider ->
try { when (provider) {
return action() is FirModuleWithDependenciesSymbolProvider ->
} finally { provider.getTopLevelCallableSymbolsToWithoutDependencies(destination, packageFqName, name)
canUseDependent.set(true) else -> provider.getTopLevelCallableSymbolsTo(destination, packageFqName, name)
} }
} }
return default
} }
private inline fun withDependent(action: () -> Unit) { override fun getPackage(fqName: FqName): FqName? =
withDependent(Unit, action) providers.firstNotNullResult { provider ->
when (provider) {
is FirModuleWithDependenciesSymbolProvider -> provider.getPackageWithoutDependencies(fqName)
else -> provider.getPackage(fqName)
} }
} }
} }