[FIR/LL FIR] Introduce FirSymbolNamesProvider
- In LL FIR, we have increasingly formalized symbol name caches as
palpable objects. The main reasons for this formalization were the
need to share implementations of caching between different (LL FIR)
symbol providers, the need to build composite name caches from
individual name caches, and the introduction of resolve extensions
which may provide additional declarations and thus complicate the name
set construction for Kotlin symbol providers in LL FIR.
- `LLFirSymbolProviderNameCache` also shared a lot of similarities with
cache handling in FIR providers like
`FirCachingCompositeSymbolProvider` and
`AbstractFirDeserializedSymbolProvider`.
- This commit introduces a `FirSymbolNamesProvider` as a component of
`FirSymbolProvider`. This symbol names provider's task is to provide
the sets of names which `FirSymbolProvider` previously provided. It
also allows sharing implementations of `mayHaveTopLevel*` once and for
all, which is an improvement over the previously scattered
implementations (the same ideas replicated many times throughout
different symbol providers).
- `FirSymbolNamesProvider` by design doesn't cache, as many symbol
providers may not need such a cache. `FirCachedSymbolNamesProvider`
can be used to cache symbol names if needed. The symbol name provider
architecture also makes it easier to switch between caching and
non-caching, without the need to reimplement caches every time.
- Synthetic function types complicate the picture, but this complication
is now exposed with the rest of the API, instead of being hidden in a
few implementations here and there. This allows symbol providers to
more explicitly state whether they can provide generated function
types, which is an advantage for the correctness of composite symbol
providers.
Some specific notes:
- In `FirSyntheticFunctionInterfaceProviderBase`, the class ID check has
been replaced with a full `mayHaveTopLevelClassifier` check so that
the cache doesn't get filled with `null` entries.
- `LLFirKotlinSymbolProviderNameCache` is turned into a non-caching
`LLFirKotlinSymbolNamesProvider` so that this symbol names provider
and those of resolve extensions can be composed into one caching
symbol provider in `LLFirProviderHelper` without creating layers of
caches. If the Kotlin symbol names provider was caching out of the
box, `LLFirProviderHelper.symbolNameCache` would cache the
names (1) in the combined symbol names cache and (2) in the Kotlin
symbol names cache.
- A caching Kotlin symbol names cache can still be created easily with
the `LLFirKotlinSymbolNamesProvider.cached` constructor function.
This commit is contained in:
committed by
Space Team
parent
b82a589e56
commit
accc9b0eb3
+7
-4
@@ -12,6 +12,8 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.llFirMo
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.java.JavaSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolNamesProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolNamesProviderWithoutCallables
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProviderInternals
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
@@ -48,6 +50,11 @@ internal class LLFirCombinedJavaSymbolProvider private constructor(
|
||||
*/
|
||||
private val classCache: NullableCaffeineCache<ClassId, FirRegularClassSymbol> = NullableCaffeineCache { it.maximumSize(2500) }
|
||||
|
||||
override val symbolNamesProvider: FirSymbolNamesProvider = object : FirSymbolNamesProviderWithoutCallables() {
|
||||
override fun getTopLevelClassifierNamesInPackage(packageFqName: FqName): Set<String>? = null
|
||||
override fun mayHaveTopLevelClassifier(classId: ClassId): Boolean = true
|
||||
}
|
||||
|
||||
override fun getClassLikeSymbolByClassId(classId: ClassId): FirClassLikeSymbol<*>? =
|
||||
classCache.get(classId) { computeClassLikeSymbolByClassId(it) }
|
||||
|
||||
@@ -82,10 +89,6 @@ internal class LLFirCombinedJavaSymbolProvider private constructor(
|
||||
|
||||
override fun getPackage(fqName: FqName): FqName? = providers.firstNotNullOfOrNull { it.getPackage(fqName) }
|
||||
|
||||
override fun computePackageSetWithTopLevelCallables(): Set<String>? = null
|
||||
override fun knownTopLevelClassifiersInPackage(packageFqName: FqName): Set<String>? = null
|
||||
override fun computeCallableNamesInPackage(packageFqName: FqName): Set<Name>? = null
|
||||
|
||||
companion object {
|
||||
fun merge(session: FirSession, project: Project, providers: List<JavaSymbolProvider>): FirSymbolProvider? =
|
||||
if (providers.size > 1) {
|
||||
|
||||
+5
-22
@@ -10,14 +10,14 @@ import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.caches.NullableCaffeineCache
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.llFirModuleData
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSession
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.LLFirSymbolProviderNameCacheBase
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||
import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProvider
|
||||
import org.jetbrains.kotlin.analysis.providers.createDeclarationProvider
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirCompositeCachedSymbolNamesProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolNamesProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProviderInternals
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.flatMapToNullableSet
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||
@@ -47,21 +47,12 @@ internal class LLFirCombinedKotlinSymbolProvider private constructor(
|
||||
providers: List<LLFirKotlinSymbolProvider>,
|
||||
private val declarationProvider: KotlinDeclarationProvider,
|
||||
) : LLFirSelectingCombinedSymbolProvider<LLFirKotlinSymbolProvider>(session, project, providers) {
|
||||
private val symbolNameCache = object : LLFirSymbolProviderNameCacheBase(session) {
|
||||
override fun computeClassifierNames(packageFqName: FqName): Set<String>? =
|
||||
providers.flatMapToNullableSet { it.knownTopLevelClassifiersInPackage(packageFqName) }
|
||||
|
||||
override fun computeCallableNames(packageFqName: FqName): Set<Name>? =
|
||||
providers.flatMapToNullableSet { it.computeCallableNamesInPackage(packageFqName) }
|
||||
|
||||
override fun computePackageNamesWithTopLevelCallables(): Set<String>? =
|
||||
providers.flatMapToNullableSet { it.computePackageSetWithTopLevelCallables() }
|
||||
}
|
||||
override val symbolNamesProvider: FirSymbolNamesProvider = FirCompositeCachedSymbolNamesProvider.fromSymbolProviders(session, providers)
|
||||
|
||||
private val classifierCache = NullableCaffeineCache<ClassId, FirClassLikeSymbol<*>> { it.maximumSize(500) }
|
||||
|
||||
override fun getClassLikeSymbolByClassId(classId: ClassId): FirClassLikeSymbol<*>? {
|
||||
if (!symbolNameCache.mayHaveTopLevelClassifier(classId, mayHaveFunctionClass = false)) return null
|
||||
if (!symbolNamesProvider.mayHaveTopLevelClassifier(classId)) return null
|
||||
|
||||
return classifierCache.get(classId) { computeClassLikeSymbolByClassId(it) }
|
||||
}
|
||||
@@ -107,7 +98,7 @@ internal class LLFirCombinedKotlinSymbolProvider private constructor(
|
||||
getCallables: (CallableId) -> Collection<A>,
|
||||
provide: LLFirKotlinSymbolProvider.(CallableId, Collection<A>) -> Unit,
|
||||
) {
|
||||
if (!symbolNameCache.mayHaveTopLevelCallable(packageFqName, name)) return
|
||||
if (!symbolNamesProvider.mayHaveTopLevelCallable(packageFqName, name)) return
|
||||
|
||||
val callableId = CallableId(packageFqName, name)
|
||||
|
||||
@@ -124,14 +115,6 @@ internal class LLFirCombinedKotlinSymbolProvider private constructor(
|
||||
|
||||
override fun getPackage(fqName: FqName): FqName? = providers.firstNotNullOfOrNull { it.getPackage(fqName) }
|
||||
|
||||
override fun computePackageSetWithTopLevelCallables(): Set<String>? = null
|
||||
|
||||
override fun knownTopLevelClassifiersInPackage(packageFqName: FqName): Set<String>? =
|
||||
symbolNameCache.getTopLevelClassifierNamesInPackage(packageFqName)
|
||||
|
||||
override fun computeCallableNamesInPackage(packageFqName: FqName): Set<Name>? =
|
||||
symbolNameCache.getTopLevelCallableNamesInPackage(packageFqName)
|
||||
|
||||
companion object {
|
||||
fun merge(session: LLFirSession, project: Project, providers: List<LLFirKotlinSymbolProvider>): FirSymbolProvider? =
|
||||
if (providers.size > 1) {
|
||||
|
||||
+12
-5
@@ -6,6 +6,8 @@
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.providers
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirCompositeSymbolNamesProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolNamesProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProviderInternals
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirSyntheticFunctionInterfaceProviderBase
|
||||
@@ -29,11 +31,20 @@ internal class LLFirCombinedSyntheticFunctionSymbolProvider private constructor(
|
||||
) : FirSymbolProvider(session) {
|
||||
private val combinedPackageNames: Set<FqName> = providers.flatMapTo(mutableSetOf()) { it.getFunctionKindPackageNames() }
|
||||
|
||||
override val symbolNamesProvider: FirSymbolNamesProvider =
|
||||
// `FirCompositeSymbolNamesProvider` defines `mayHaveSyntheticFunctionTypes` and `mayHaveSyntheticFunctionType` correctly, which is
|
||||
// needed for consistency should this symbol provider be part of another composite symbol provider.
|
||||
object : FirCompositeSymbolNamesProvider(providers.map { it.symbolNamesProvider }) {
|
||||
override fun getTopLevelClassifierNamesInPackage(packageFqName: FqName): Set<String> = emptySet()
|
||||
override fun getPackageNamesWithTopLevelCallables(): Set<String> = emptySet()
|
||||
override fun getTopLevelCallableNamesInPackage(packageFqName: FqName): Set<Name> = emptySet()
|
||||
}
|
||||
|
||||
override fun getClassLikeSymbolByClassId(classId: ClassId): FirClassLikeSymbol<*>? {
|
||||
if (!classId.mayBeSyntheticFunctionClassName()) return null
|
||||
if (classId.packageFqName !in combinedPackageNames) return null
|
||||
|
||||
return providers.firstNotNullOfOrNull { it.getClassLikeSymbolByClassIdWithoutClassIdChecks(classId) }
|
||||
return providers.firstNotNullOfOrNull { it.getClassLikeSymbolByClassId(classId) }
|
||||
}
|
||||
|
||||
@FirSymbolProviderInternals
|
||||
@@ -50,10 +61,6 @@ internal class LLFirCombinedSyntheticFunctionSymbolProvider private constructor(
|
||||
|
||||
override fun getPackage(fqName: FqName): FqName? = fqName.takeIf { it in combinedPackageNames }
|
||||
|
||||
override fun computePackageSetWithTopLevelCallables(): Set<String>? = null
|
||||
override fun knownTopLevelClassifiersInPackage(packageFqName: FqName): Set<String>? = null
|
||||
override fun computeCallableNamesInPackage(packageFqName: FqName): Set<Name>? = null
|
||||
|
||||
companion object {
|
||||
fun merge(session: FirSession, providers: List<FirSyntheticFunctionInterfaceProviderBase>): FirSymbolProvider? =
|
||||
if (providers.size > 1) LLFirCombinedSyntheticFunctionSymbolProvider(session, providers)
|
||||
|
||||
-15
@@ -5,7 +5,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.providers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.LLFirSymbolProviderNameCache
|
||||
import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProvider
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
||||
@@ -16,8 +15,6 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||
import org.jetbrains.kotlin.name.CallableId
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtCallableDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtClassLikeDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
@@ -65,15 +62,3 @@ internal abstract class LLFirKotlinSymbolProvider(session: FirSession) : FirSymb
|
||||
properties: Collection<KtProperty>,
|
||||
)
|
||||
}
|
||||
|
||||
internal abstract class LLFirKotlinSymbolProviderWithNameCache(session: FirSession) : LLFirKotlinSymbolProvider(session) {
|
||||
protected abstract val symbolNameCache: LLFirSymbolProviderNameCache
|
||||
|
||||
final override fun knownTopLevelClassifiersInPackage(packageFqName: FqName): Set<String>? =
|
||||
symbolNameCache.getTopLevelClassifierNamesInPackage(packageFqName)
|
||||
|
||||
final override fun computeCallableNamesInPackage(packageFqName: FqName): Set<Name>? =
|
||||
symbolNameCache.getTopLevelCallableNamesInPackage(packageFqName)
|
||||
|
||||
final override fun computePackageSetWithTopLevelCallables(): Set<String>? = symbolNameCache.getPackageNamesWithTopLevelCallables()
|
||||
}
|
||||
|
||||
+6
-8
@@ -8,6 +8,8 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.providers
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.stubBased.deserialization.JvmStubBasedFirDeserializedSymbolProvider
|
||||
import org.jetbrains.kotlin.analysis.utils.collections.buildSmartList
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirNullSymbolNamesProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolNamesProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProviderInternals
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
@@ -29,6 +31,8 @@ internal class LLFirModuleWithDependenciesSymbolProvider(
|
||||
val providers: List<FirSymbolProvider>,
|
||||
val dependencyProvider: LLFirDependenciesSymbolProvider,
|
||||
) : FirSymbolProvider(session) {
|
||||
override val symbolNamesProvider: FirSymbolNamesProvider = FirNullSymbolNamesProvider
|
||||
|
||||
override fun getClassLikeSymbolByClassId(classId: ClassId): FirClassLikeSymbol<*>? =
|
||||
getClassLikeSymbolByClassIdWithoutDependencies(classId)
|
||||
?: dependencyProvider.getClassLikeSymbolByClassId(classId)
|
||||
@@ -96,10 +100,6 @@ internal class LLFirModuleWithDependenciesSymbolProvider(
|
||||
|
||||
fun getPackageWithoutDependencies(fqName: FqName): FqName? =
|
||||
providers.firstNotNullOfOrNull { it.getPackage(fqName) }
|
||||
|
||||
override fun computePackageSetWithTopLevelCallables(): Set<String>? = null
|
||||
override fun knownTopLevelClassifiersInPackage(packageFqName: FqName): Set<String>? = null
|
||||
override fun computeCallableNamesInPackage(packageFqName: FqName): Set<Name>? = null
|
||||
}
|
||||
|
||||
internal class LLFirDependenciesSymbolProvider(
|
||||
@@ -113,6 +113,8 @@ internal class LLFirDependenciesSymbolProvider(
|
||||
}
|
||||
}
|
||||
|
||||
override val symbolNamesProvider: FirSymbolNamesProvider = FirNullSymbolNamesProvider
|
||||
|
||||
override fun getClassLikeSymbolByClassId(classId: ClassId): FirClassLikeSymbol<*>? =
|
||||
providers.firstNotNullOfOrNull { it.getClassLikeSymbolByClassId(classId) }
|
||||
|
||||
@@ -151,10 +153,6 @@ internal class LLFirDependenciesSymbolProvider(
|
||||
|
||||
override fun getPackage(fqName: FqName): FqName? = providers.firstNotNullOfOrNull { it.getPackage(fqName) }
|
||||
|
||||
override fun computePackageSetWithTopLevelCallables(): Set<String>? = null
|
||||
override fun knownTopLevelClassifiersInPackage(packageFqName: FqName): Set<String>? = null
|
||||
override fun computeCallableNamesInPackage(packageFqName: FqName): Set<Name>? = null
|
||||
|
||||
private fun <S : FirCallableSymbol<*>> addNewSymbolsConsideringJvmFacades(
|
||||
destination: MutableList<S>,
|
||||
newSymbols: List<S>,
|
||||
|
||||
+4
-9
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.providers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.SyntheticFirClassProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.LLFirSymbolProviderNameCache
|
||||
import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProvider
|
||||
import org.jetbrains.kotlin.analysis.providers.KotlinPackageProvider
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
@@ -17,10 +16,7 @@ import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
|
||||
import org.jetbrains.kotlin.fir.originalForSubstitutionOverride
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProviderInternals
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.*
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.name.CallableId
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
@@ -112,12 +108,11 @@ internal class LLFirProvider(
|
||||
declarationProvider.getTopLevelKotlinClassLikeDeclarationNamesInPackage(fqName)
|
||||
|
||||
@NoMutableState
|
||||
internal inner class SymbolProvider : LLFirKotlinSymbolProviderWithNameCache(session) {
|
||||
override val symbolNameCache: LLFirSymbolProviderNameCache
|
||||
get() = providerHelper.symbolNameCache
|
||||
internal inner class SymbolProvider : LLFirKotlinSymbolProvider(session) {
|
||||
override val symbolNamesProvider: FirSymbolNamesProvider get() = providerHelper.symbolNameCache
|
||||
|
||||
override fun getClassLikeSymbolByClassId(classId: ClassId): FirClassLikeSymbol<*>? {
|
||||
if (!providerHelper.symbolNameCache.mayHaveTopLevelClassifier(classId, mayHaveFunctionClass = false)) return null
|
||||
if (!providerHelper.symbolNameCache.mayHaveTopLevelClassifier(classId)) return null
|
||||
return getFirClassifierByFqName(classId)?.symbol
|
||||
}
|
||||
|
||||
|
||||
+6
-5
@@ -10,8 +10,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.Composi
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.resolve.extensions.LLFirResolveExtensionTool
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.resolve.extensions.llResolveExtensionTool
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.FirElementFinder
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.LLFirCompositeSymbolProviderNameCache
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.LLFirKotlinSymbolProviderNameCache
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.LLFirKotlinSymbolNamesProvider
|
||||
import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProvider
|
||||
import org.jetbrains.kotlin.analysis.providers.KotlinPackageProvider
|
||||
import org.jetbrains.kotlin.analysis.providers.impl.CompositeKotlinDeclarationProvider
|
||||
@@ -24,6 +23,7 @@ import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirCompositeCachedSymbolNamesProvider
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||
@@ -80,10 +80,11 @@ internal class LLFirProviderHelper(
|
||||
}
|
||||
}
|
||||
|
||||
val symbolNameCache = LLFirCompositeSymbolProviderNameCache.create(
|
||||
val symbolNameCache = FirCompositeCachedSymbolNamesProvider.create(
|
||||
firSession,
|
||||
listOfNotNull(
|
||||
LLFirKotlinSymbolProviderNameCache(firSession, declarationProvider),
|
||||
extensionTool?.symbolNameCache,
|
||||
LLFirKotlinSymbolNamesProvider(declarationProvider),
|
||||
extensionTool?.symbolNamesProvider,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
+8
-7
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.analysis.api.resolve.extensions.KtResolveExtensionFi
|
||||
import org.jetbrains.kotlin.analysis.api.resolve.extensions.KtResolveExtensionProvider
|
||||
import org.jetbrains.kotlin.analysis.api.resolve.extensions.KtResolveExtensionReferencePsiTargetsProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSession
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.LLFirSymbolProviderNameCache
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModuleStructureInternals
|
||||
import org.jetbrains.kotlin.analysis.project.structure.analysisExtensionFileContextModule
|
||||
@@ -23,6 +22,7 @@ import org.jetbrains.kotlin.analysis.providers.KotlinPackageProvider
|
||||
import org.jetbrains.kotlin.analysis.providers.impl.FileBasedKotlinDeclarationProvider
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.FirSessionComponent
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolNamesProvider
|
||||
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils
|
||||
import org.jetbrains.kotlin.name.*
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
@@ -32,14 +32,15 @@ import java.util.concurrent.ConcurrentHashMap
|
||||
/**
|
||||
* Encapsulate all the work with the [KtResolveExtension] for the LL API.
|
||||
*
|
||||
* Caches generated [KtResolveExtensionFile]s, creates [KotlinDeclarationProvider], [KotlinPackageProvider], [LLFirSymbolProviderNameCache] needed for the [org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider].
|
||||
* Caches generated [KtResolveExtensionFile]s, creates [KotlinDeclarationProvider], [KotlinPackageProvider], [FirSymbolNamesProvider] needed
|
||||
* for the [org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider].
|
||||
*/
|
||||
abstract class LLFirResolveExtensionTool : FirSessionComponent {
|
||||
abstract val modificationTrackers: List<ModificationTracker>
|
||||
abstract val declarationProvider: LLFirResolveExtensionToolDeclarationProvider
|
||||
abstract val packageProvider: KotlinPackageProvider
|
||||
abstract val packageFilter: LLFirResolveExtensionToolPackageFilter
|
||||
internal abstract val symbolNameCache: LLFirSymbolProviderNameCache
|
||||
internal abstract val symbolNamesProvider: FirSymbolNamesProvider
|
||||
}
|
||||
|
||||
val FirSession.llResolveExtensionTool: LLFirResolveExtensionTool? by FirSession.nullableSessionComponentAccessor()
|
||||
@@ -63,13 +64,13 @@ internal class LLFirNonEmptyResolveExtensionTool(
|
||||
|
||||
override val packageProvider: KotlinPackageProvider = LLFirResolveExtensionToolPackageProvider(packageFilter)
|
||||
|
||||
override val symbolNameCache: LLFirSymbolProviderNameCache = LLFirResolveExtensionToolNameCache(packageFilter, fileProvider)
|
||||
override val symbolNamesProvider: FirSymbolNamesProvider = LLFirResolveExtensionToolSymbolNamesProvider(packageFilter, fileProvider)
|
||||
}
|
||||
|
||||
private class LLFirResolveExtensionToolNameCache(
|
||||
private class LLFirResolveExtensionToolSymbolNamesProvider(
|
||||
private val packageFilter: LLFirResolveExtensionToolPackageFilter,
|
||||
private val fileProvider: LLFirResolveExtensionsFileProvider,
|
||||
) : LLFirSymbolProviderNameCache() {
|
||||
) : FirSymbolNamesProvider() {
|
||||
override fun getTopLevelClassifierNamesInPackage(packageFqName: FqName): Set<String> = forbidAnalysis {
|
||||
if (!packageFilter.packageExists(packageFqName)) return emptySet()
|
||||
fileProvider.getFilesByPackage(packageFqName)
|
||||
@@ -87,7 +88,7 @@ private class LLFirResolveExtensionToolNameCache(
|
||||
.flatMapTo(mutableSetOf()) { it.getTopLevelCallableNames() }
|
||||
}
|
||||
|
||||
override fun mayHaveTopLevelClassifier(classId: ClassId, mayHaveFunctionClass: Boolean): Boolean = forbidAnalysis {
|
||||
override fun mayHaveTopLevelClassifier(classId: ClassId): Boolean = forbidAnalysis {
|
||||
if (!packageFilter.packageExists(classId.packageFqName)) return false
|
||||
|
||||
fileProvider.getFilesByPackage(classId.packageFqName)
|
||||
|
||||
+9
-8
@@ -5,10 +5,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.stubBased.deserialization
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLFirKotlinSymbolProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.LLFirKotlinSymbolNamesProvider
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLFirKotlinSymbolProviderWithNameCache
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.LLFirKotlinSymbolProviderNameCache
|
||||
import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProvider
|
||||
import org.jetbrains.kotlin.analysis.providers.createDeclarationProvider
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
||||
import org.jetbrains.kotlin.fir.deserialization.SingleModuleDataProvider
|
||||
import org.jetbrains.kotlin.fir.java.deserialization.JvmClassFileBasedSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.java.deserialization.KotlinBuiltins
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolNamesProvider
|
||||
import org.jetbrains.kotlin.fir.realPsi
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProviderInternals
|
||||
import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
|
||||
@@ -50,11 +51,11 @@ internal open class JvmStubBasedFirDeserializedSymbolProvider(
|
||||
project: Project,
|
||||
scope: GlobalSearchScope,
|
||||
private val initialOrigin: FirDeclarationOrigin
|
||||
) : LLFirKotlinSymbolProviderWithNameCache(session) {
|
||||
) : LLFirKotlinSymbolProvider(session) {
|
||||
private val declarationProvider by lazy(LazyThreadSafetyMode.PUBLICATION) { project.createDeclarationProvider(scope, module = null) }
|
||||
private val moduleData = moduleDataProvider.getModuleData(null)
|
||||
|
||||
override val symbolNameCache: LLFirKotlinSymbolProviderNameCache = LLFirKotlinSymbolProviderNameCache(session, declarationProvider)
|
||||
override val symbolNamesProvider: FirSymbolNamesProvider = LLFirKotlinSymbolNamesProvider.cached(session, declarationProvider)
|
||||
|
||||
private val typeAliasCache: FirCache<ClassId, FirTypeAliasSymbol?, StubBasedFirDeserializationContext?> =
|
||||
session.firCachesFactory.createCacheWithPostCompute(
|
||||
@@ -192,7 +193,7 @@ internal open class JvmStubBasedFirDeserializedSymbolProvider(
|
||||
private fun <C : FirCallableSymbol<*>, CONTEXT> FirCache<CallableId, List<C>, CONTEXT?>.getCallablesWithoutContext(
|
||||
id: CallableId,
|
||||
): List<C> {
|
||||
if (!symbolNameCache.mayHaveTopLevelCallable(id.packageName, id.callableName)) return emptyList()
|
||||
if (!symbolNamesProvider.mayHaveTopLevelCallable(id.packageName, id.callableName)) return emptyList()
|
||||
return getValue(id, null)
|
||||
}
|
||||
|
||||
@@ -241,12 +242,12 @@ internal open class JvmStubBasedFirDeserializedSymbolProvider(
|
||||
|
||||
override fun getPackage(fqName: FqName): FqName? =
|
||||
fqName.takeIf {
|
||||
symbolNameCache.getTopLevelClassifierNamesInPackage(fqName)?.isNotEmpty() == true ||
|
||||
symbolNameCache.getPackageNamesWithTopLevelCallables()?.contains(fqName.asString()) == true
|
||||
symbolNamesProvider.getTopLevelClassifierNamesInPackage(fqName)?.isNotEmpty() == true ||
|
||||
symbolNamesProvider.getPackageNamesWithTopLevelCallables()?.contains(fqName.asString()) == true
|
||||
}
|
||||
|
||||
override fun getClassLikeSymbolByClassId(classId: ClassId): FirClassLikeSymbol<*>? {
|
||||
if (!symbolNameCache.mayHaveTopLevelClassifier(classId, mayHaveFunctionClass = false)) return null
|
||||
if (!symbolNamesProvider.mayHaveTopLevelClassifier(classId)) return null
|
||||
return getClass(classId) ?: getTypeAlias(classId)
|
||||
}
|
||||
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.util
|
||||
|
||||
import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProvider
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolNamesProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirDelegatingCachedSymbolNamesProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirCachedSymbolNamesProvider
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
/**
|
||||
* A [FirSymbolNamesProvider] that fetches top-level names from a Kotlin [declarationProvider].
|
||||
*/
|
||||
internal class LLFirKotlinSymbolNamesProvider(
|
||||
private val declarationProvider: KotlinDeclarationProvider,
|
||||
) : FirSymbolNamesProvider() {
|
||||
override fun getTopLevelClassifierNamesInPackage(packageFqName: FqName): Set<String> =
|
||||
declarationProvider
|
||||
.getTopLevelKotlinClassLikeDeclarationNamesInPackage(packageFqName)
|
||||
.mapTo(mutableSetOf()) { it.asString() }
|
||||
|
||||
override fun getPackageNamesWithTopLevelCallables(): Set<String> =
|
||||
declarationProvider.computePackageSetWithTopLevelCallableDeclarations()
|
||||
|
||||
override fun getTopLevelCallableNamesInPackage(packageFqName: FqName): Set<Name> =
|
||||
declarationProvider.getTopLevelCallableNamesInPackage(packageFqName)
|
||||
|
||||
companion object {
|
||||
fun cached(session: FirSession, declarationProvider: KotlinDeclarationProvider): FirCachedSymbolNamesProvider =
|
||||
FirDelegatingCachedSymbolNamesProvider(session, LLFirKotlinSymbolNamesProvider(declarationProvider))
|
||||
}
|
||||
}
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.util
|
||||
|
||||
import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProvider
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
/**
|
||||
* An [LLFirSymbolProviderNameCache] that fetches top-level names from a Kotlin [declarationProvider].
|
||||
*/
|
||||
internal class LLFirKotlinSymbolProviderNameCache(
|
||||
firSession: FirSession,
|
||||
private val declarationProvider: KotlinDeclarationProvider,
|
||||
) : LLFirSymbolProviderNameCacheBase(firSession) {
|
||||
override fun computeClassifierNames(packageFqName: FqName): Set<String> =
|
||||
declarationProvider
|
||||
.getTopLevelKotlinClassLikeDeclarationNamesInPackage(packageFqName)
|
||||
.mapTo(mutableSetOf()) { it.asString() }
|
||||
|
||||
override fun computePackageNamesWithTopLevelCallables(): Set<String> =
|
||||
declarationProvider.computePackageSetWithTopLevelCallableDeclarations()
|
||||
|
||||
override fun computeCallableNames(packageFqName: FqName): Set<Name> =
|
||||
declarationProvider.getTopLevelCallableNamesInPackage(packageFqName)
|
||||
}
|
||||
-149
@@ -1,149 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.util
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.caches.createCache
|
||||
import org.jetbrains.kotlin.fir.caches.firCachesFactory
|
||||
import org.jetbrains.kotlin.fir.caches.getValue
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.flatMapToNullableSet
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.mayHaveTopLevelClassifier
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
/**
|
||||
* Caches the names of classifiers and callables contained in a package. [LLFirSymbolProviderNameCache] is used by symbol providers to abort
|
||||
* symbol finding early if the symbol name isn't contained in the symbol provider's domain.
|
||||
*
|
||||
* For [getTopLevelClassifierNamesInPackage], [getTopLevelCallableNamesInPackage], and [getPackageNamesWithTopLevelCallables], the result
|
||||
* may have false-positive entries but cannot have false-negative entries.
|
||||
* It should contain all the names in the package/all package names but may have some additional names that are not there.
|
||||
* Also, `null` might be returned when it's too expensive to calculate the sets.
|
||||
*
|
||||
* For [mayHaveTopLevelClassifier] and [mayHaveTopLevelCallable], the result may be a false-positive result but cannot be a false-negative.
|
||||
*/
|
||||
internal abstract class LLFirSymbolProviderNameCache {
|
||||
/**
|
||||
* Returns the set of top-level classifier names (classes, interfaces, objects, and type aliases) inside the [packageFqName] package
|
||||
* within the cache's scope.
|
||||
*
|
||||
* @see LLFirSymbolProviderNameCache
|
||||
*/
|
||||
abstract fun getTopLevelClassifierNamesInPackage(packageFqName: FqName): Set<String>?
|
||||
|
||||
/**
|
||||
* Returns the set of package names which contain a top-level callable declaration within the cache's scope.
|
||||
*
|
||||
* @see LLFirSymbolProviderNameCache
|
||||
*/
|
||||
abstract fun getPackageNamesWithTopLevelCallables(): Set<String>?
|
||||
|
||||
/**
|
||||
* Returns the set of top-level callable names (functions and properties) inside the [packageFqName] package within the cache's scope.
|
||||
*
|
||||
* @see LLFirSymbolProviderNameCache
|
||||
*/
|
||||
abstract fun getTopLevelCallableNamesInPackage(packageFqName: FqName): Set<Name>?
|
||||
|
||||
/**
|
||||
* Checks if the cache's scope may contain a top-level classifier (class, interface, object, or type alias) with the given [classId].
|
||||
*
|
||||
* @see LLFirSymbolProviderNameCache
|
||||
*/
|
||||
abstract fun mayHaveTopLevelClassifier(classId: ClassId, mayHaveFunctionClass: Boolean): Boolean
|
||||
|
||||
/**
|
||||
* Checks if the cache's scope may contain a top-level callable (function or property) called [name] inside the [packageFqName] package.
|
||||
*
|
||||
* @see LLFirSymbolProviderNameCache
|
||||
*/
|
||||
abstract fun mayHaveTopLevelCallable(packageFqName: FqName, name: Name): Boolean
|
||||
}
|
||||
|
||||
internal abstract class LLFirSymbolProviderNameCacheBase(
|
||||
private val firSession: FirSession
|
||||
) : LLFirSymbolProviderNameCache() {
|
||||
abstract fun computeClassifierNames(packageFqName: FqName): Set<String>?
|
||||
abstract fun computePackageNamesWithTopLevelCallables(): Set<String>?
|
||||
abstract fun computeCallableNames(packageFqName: FqName): Set<Name>?
|
||||
|
||||
private val topLevelClassifierNamesByPackage =
|
||||
firSession.firCachesFactory.createCache(::computeClassifierNames)
|
||||
|
||||
private val topLevelCallablePackageNames by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||
computePackageNamesWithTopLevelCallables()
|
||||
}
|
||||
|
||||
private val topLevelCallableNamesByPackage =
|
||||
firSession.firCachesFactory.createCache(::computeCallableNames)
|
||||
|
||||
final override fun getTopLevelClassifierNamesInPackage(packageFqName: FqName): Set<String>? =
|
||||
topLevelClassifierNamesByPackage.getValue(packageFqName)
|
||||
|
||||
final override fun getTopLevelCallableNamesInPackage(packageFqName: FqName): Set<Name>? {
|
||||
val packageNames = getPackageNamesWithTopLevelCallables()
|
||||
if (packageNames != null && packageFqName.asString() !in packageNames) return null
|
||||
|
||||
return topLevelCallableNamesByPackage.getValue(packageFqName)
|
||||
}
|
||||
|
||||
final override fun getPackageNamesWithTopLevelCallables(): Set<String>? = topLevelCallablePackageNames
|
||||
|
||||
final override fun mayHaveTopLevelClassifier(classId: ClassId, mayHaveFunctionClass: Boolean): Boolean {
|
||||
val names = getTopLevelClassifierNamesInPackage(classId.packageFqName) ?: return true
|
||||
return names.mayHaveTopLevelClassifier(classId, firSession, mayHaveFunctionClass)
|
||||
}
|
||||
|
||||
override fun mayHaveTopLevelCallable(packageFqName: FqName, name: Name): Boolean {
|
||||
if (name.isSpecial) return true
|
||||
val names = getTopLevelCallableNamesInPackage(packageFqName) ?: return true
|
||||
return name in names
|
||||
}
|
||||
}
|
||||
|
||||
internal object LLFirEmptySymbolProviderNameCache : LLFirSymbolProviderNameCache() {
|
||||
override fun getTopLevelClassifierNamesInPackage(packageFqName: FqName): Set<String> = emptySet()
|
||||
override fun getTopLevelCallableNamesInPackage(packageFqName: FqName): Set<Name> = emptySet()
|
||||
override fun getPackageNamesWithTopLevelCallables(): Set<String> = emptySet()
|
||||
override fun mayHaveTopLevelClassifier(classId: ClassId, mayHaveFunctionClass: Boolean): Boolean = false
|
||||
override fun mayHaveTopLevelCallable(packageFqName: FqName, name: Name): Boolean = false
|
||||
}
|
||||
|
||||
internal class LLFirCompositeSymbolProviderNameCache
|
||||
private constructor(
|
||||
private val caches: List<LLFirSymbolProviderNameCache>
|
||||
) : LLFirSymbolProviderNameCache() {
|
||||
override fun getTopLevelClassifierNamesInPackage(packageFqName: FqName): Set<String>? {
|
||||
return caches.flatMapToNullableSet { it.getTopLevelClassifierNamesInPackage(packageFqName) }
|
||||
}
|
||||
|
||||
override fun getPackageNamesWithTopLevelCallables(): Set<String>? {
|
||||
return caches.flatMapToNullableSet { it.getPackageNamesWithTopLevelCallables() }
|
||||
}
|
||||
|
||||
override fun getTopLevelCallableNamesInPackage(packageFqName: FqName): Set<Name>? {
|
||||
return caches.flatMapToNullableSet { it.getTopLevelCallableNamesInPackage(packageFqName) }
|
||||
}
|
||||
|
||||
override fun mayHaveTopLevelClassifier(classId: ClassId, mayHaveFunctionClass: Boolean): Boolean {
|
||||
return caches.any { it.mayHaveTopLevelClassifier(classId, mayHaveFunctionClass) }
|
||||
}
|
||||
|
||||
override fun mayHaveTopLevelCallable(packageFqName: FqName, name: Name): Boolean {
|
||||
return caches.any { it.mayHaveTopLevelCallable(packageFqName, name) }
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun create(caches: List<LLFirSymbolProviderNameCache>): LLFirSymbolProviderNameCache {
|
||||
return when (caches.size) {
|
||||
0 -> LLFirEmptySymbolProviderNameCache
|
||||
1 -> caches.single()
|
||||
else -> LLFirCompositeSymbolProviderNameCache(caches)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user