[LL] [cls] don't access index to retrieve fir for given ktElement

also don't check name pattern, because
given ktElement proves that corresponding package contains something
This commit is contained in:
Anna Kozlova
2023-05-04 23:45:56 +02:00
committed by teamcity
parent e47561e70b
commit cf6a06fd14
5 changed files with 93 additions and 26 deletions
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.providers 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.analysis.utils.collections.buildSmartList
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
@@ -14,12 +15,14 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.load.kotlin.FacadeClassSource import org.jetbrains.kotlin.load.kotlin.FacadeClassSource
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtCallableDeclaration
import org.jetbrains.kotlin.psi.KtClassLikeDeclaration
import org.jetbrains.kotlin.resolve.jvm.JvmClassName import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import org.jetbrains.kotlin.utils.SmartSet import org.jetbrains.kotlin.utils.SmartSet
import org.jetbrains.kotlin.utils.addIfNotNull
internal class LLFirModuleWithDependenciesSymbolProvider( internal class LLFirModuleWithDependenciesSymbolProvider(
session: FirSession, session: FirSession,
@@ -33,20 +36,29 @@ internal class LLFirModuleWithDependenciesSymbolProvider(
fun getClassLikeSymbolByFqNameWithoutDependencies(classId: ClassId): FirClassLikeSymbol<*>? = fun getClassLikeSymbolByFqNameWithoutDependencies(classId: ClassId): FirClassLikeSymbol<*>? =
providers.firstNotNullOfOrNull { it.getClassLikeSymbolByClassId(classId) } providers.firstNotNullOfOrNull { it.getClassLikeSymbolByClassId(classId) }
fun getClassLikeSymbolByFqNameWithoutDependencies(
classLikeDeclaration: KtClassLikeDeclaration,
classId: ClassId
): FirClassLikeSymbol<*>? {
return providers.filterIsInstance(JvmStubBasedFirDeserializedSymbolProvider::class.java)
.firstNotNullOfOrNull { it.getClassLikeSymbolByClassId(classLikeDeclaration, classId) }
}
@FirSymbolProviderInternals @FirSymbolProviderInternals
override fun getTopLevelCallableSymbolsTo(destination: MutableList<FirCallableSymbol<*>>, packageFqName: FqName, name: Name) { override fun getTopLevelCallableSymbolsTo(destination: MutableList<FirCallableSymbol<*>>, packageFqName: FqName, name: Name) {
getTopLevelCallableSymbolsToWithoutDependencies(destination, packageFqName, name) providers.forEach { it.getTopLevelCallableSymbolsTo(destination, packageFqName, name) }
dependencyProvider.getTopLevelCallableSymbolsTo(destination, packageFqName, name) dependencyProvider.getTopLevelCallableSymbolsTo(destination, packageFqName, name)
} }
@FirSymbolProviderInternals @FirSymbolProviderInternals
fun getTopLevelCallableSymbolsWithoutDependencies(packageFqName: FqName, name: Name): List<FirCallableSymbol<*>> { fun getTopLevelDeserializedCallableSymbolsToWithoutDependencies(
return buildList { getTopLevelCallableSymbolsToWithoutDependencies(this, packageFqName, name) } destination: MutableList<FirCallableSymbol<*>>,
} callableDeclaration: KtCallableDeclaration,
packageFqName: FqName,
@FirSymbolProviderInternals shortName: Name
fun getTopLevelCallableSymbolsToWithoutDependencies(destination: MutableList<FirCallableSymbol<*>>, packageFqName: FqName, name: Name) { ) {
providers.forEach { it.getTopLevelCallableSymbolsTo(destination, packageFqName, name) } providers.filterIsInstance(JvmStubBasedFirDeserializedSymbolProvider::class.java)
.forEach { destination.addIfNotNull(it.getTopLevelCallableSymbol(callableDeclaration, packageFqName, shortName)) }
} }
@FirSymbolProviderInternals @FirSymbolProviderInternals
@@ -18,15 +18,13 @@ import org.jetbrains.kotlin.fir.caches.getValue
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.deserialization.SingleModuleDataProvider import org.jetbrains.kotlin.fir.deserialization.SingleModuleDataProvider
import org.jetbrains.kotlin.fir.java.deserialization.KotlinBuiltins import org.jetbrains.kotlin.fir.java.deserialization.KotlinBuiltins
import org.jetbrains.kotlin.fir.realPsi
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.scopes.FirKotlinScopeProvider import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.name.* import org.jetbrains.kotlin.name.*
import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.KtTypeAlias
import org.jetbrains.kotlin.resolve.jvm.JvmClassName import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import org.jetbrains.kotlin.serialization.deserialization.MetadataPackageFragment import org.jetbrains.kotlin.serialization.deserialization.MetadataPackageFragment
@@ -67,7 +65,7 @@ internal open class JvmStubBasedFirDeserializedSymbolProvider(
private val typeAliasCache: FirCache<ClassId, FirTypeAliasSymbol?, StubBasedFirDeserializationContext?> = private val typeAliasCache: FirCache<ClassId, FirTypeAliasSymbol?, StubBasedFirDeserializationContext?> =
session.firCachesFactory.createCacheWithPostCompute( session.firCachesFactory.createCacheWithPostCompute(
createValue = { classId, _ -> findAndDeserializeTypeAlias(classId) }, createValue = { classId, context -> findAndDeserializeTypeAlias(classId, context) },
postCompute = { _, symbol, postProcessor -> postCompute = { _, symbol, postProcessor ->
if (postProcessor != null && symbol != null) { if (postProcessor != null && symbol != null) {
postProcessor.invoke(symbol) postProcessor.invoke(symbol)
@@ -93,12 +91,16 @@ internal open class JvmStubBasedFirDeserializedSymbolProvider(
return namesByPackageCache.getTopLevelClassifierNamesInPackage(packageFqName) return namesByPackageCache.getTopLevelClassifierNamesInPackage(packageFqName)
} }
private fun findAndDeserializeTypeAlias(classId: ClassId): Pair<FirTypeAliasSymbol?, DeserializedTypeAliasPostProcessor?> { private fun findAndDeserializeTypeAlias(
val classLikeDeclaration = declarationProvider.getClassLikeDeclarationByClassId(classId)?.originalElement classId: ClassId,
context: StubBasedFirDeserializationContext?
): Pair<FirTypeAliasSymbol?, DeserializedTypeAliasPostProcessor?> {
val classLikeDeclaration =
context?.classLikeDeclaration ?: declarationProvider.getClassLikeDeclarationByClassId(classId)?.originalElement
if (classLikeDeclaration is KtTypeAlias) { if (classLikeDeclaration is KtTypeAlias) {
val symbol = FirTypeAliasSymbol(classId) val symbol = FirTypeAliasSymbol(classId)
val postProcessor: DeserializedTypeAliasPostProcessor = { val postProcessor: DeserializedTypeAliasPostProcessor = {
val rootContext = StubBasedFirDeserializationContext.createRootContext( val rootContext = context ?: StubBasedFirDeserializationContext.createRootContext(
moduleData, moduleData,
StubBasedAnnotationDeserializer(session), StubBasedAnnotationDeserializer(session),
classId.packageFqName, classId.packageFqName,
@@ -117,7 +119,12 @@ internal open class JvmStubBasedFirDeserializedSymbolProvider(
classId: ClassId, classId: ClassId,
parentContext: StubBasedFirDeserializationContext? = null parentContext: StubBasedFirDeserializationContext? = null
): FirRegularClassSymbol? { ): FirRegularClassSymbol? {
val classLikeDeclaration = declarationProvider.getClassLikeDeclarationByClassId(classId)?.originalElement ?: return null val (classLikeDeclaration, context) =
if (parentContext?.classLikeDeclaration != null) {
parentContext.classLikeDeclaration to null
} else {
(declarationProvider.getClassLikeDeclarationByClassId(classId)?.originalElement ?: return null) to parentContext
}
val symbol = FirRegularClassSymbol(classId) val symbol = FirRegularClassSymbol(classId)
if (classLikeDeclaration is KtClassOrObject) { if (classLikeDeclaration is KtClassOrObject) {
deserializeClassToSymbol( deserializeClassToSymbol(
@@ -128,14 +135,14 @@ internal open class JvmStubBasedFirDeserializedSymbolProvider(
moduleData, moduleData,
StubBasedAnnotationDeserializer(session), StubBasedAnnotationDeserializer(session),
kotlinScopeProvider, kotlinScopeProvider,
parentContext, parentContext = context,
containerSource = if (initialOrigin == FirDeclarationOrigin.BuiltIns) null else JvmFromStubDecompilerSource( containerSource = if (initialOrigin == FirDeclarationOrigin.BuiltIns) null else JvmFromStubDecompilerSource(
JvmClassName.byClassId( JvmClassName.byClassId(
classId classId
) )
), ),
deserializeNestedClass = this::getClass, deserializeNestedClass = this::getClass,
initialOrigin initialOrigin = initialOrigin
) )
return symbol return symbol
} }
@@ -223,4 +230,51 @@ internal open class JvmStubBasedFirDeserializedSymbolProvider(
if (!namesByPackageCache.mayHaveTopLevelClassifier(classId, mayHaveFunctionClass = false)) return null if (!namesByPackageCache.mayHaveTopLevelClassifier(classId, mayHaveFunctionClass = false)) return null
return getClass(classId) ?: getTypeAlias(classId) return getClass(classId) ?: getTypeAlias(classId)
} }
fun getClassLikeSymbolByClassId(classLikeDeclaration: KtClassLikeDeclaration, classId: ClassId): FirClassLikeSymbol<*>? {
val annotationDeserializer = StubBasedAnnotationDeserializer(session)
val deserializationContext = StubBasedFirDeserializationContext(
moduleData,
classId.packageFqName,
classId.relativeClassName,
StubBasedFirTypeDeserializer(
moduleData,
annotationDeserializer,
parent = null,
containingSymbol = null,
owner = null,
initialOrigin
),
annotationDeserializer,
containerSource = null,
outerClassSymbol = null,
outerTypeParameters = emptyList(),
initialOrigin,
classLikeDeclaration
)
if (classLikeDeclaration is KtClassOrObject) {
return classCache.getValue(
classId,
deserializationContext
)
}
return typeAliasCache.getValue(classId, deserializationContext)
}
fun getTopLevelCallableSymbol(
callableDeclaration: KtCallableDeclaration,
packageFqName: FqName,
shortName: Name
): FirCallableSymbol<*>? {
//possible overloads spoils here
//we can't use only this callable instead of index access to fill the cache
//names check is redundant though as we already have existing callable in scope
val callableId = CallableId(packageFqName, shortName)
val callableSymbols = when (callableDeclaration) {
is KtNamedFunction -> functionCache.getValue(callableId)
is KtProperty -> propertyCache.getValue(callableId)
else -> null
}
return callableSymbols?.singleOrNull { it.fir.realPsi == callableDeclaration }
}
} }
@@ -45,7 +45,8 @@ internal class StubBasedFirDeserializationContext(
val containerSource: DeserializedContainerSource?, val containerSource: DeserializedContainerSource?,
val outerClassSymbol: FirRegularClassSymbol?, val outerClassSymbol: FirRegularClassSymbol?,
val outerTypeParameters: List<FirTypeParameterSymbol>, val outerTypeParameters: List<FirTypeParameterSymbol>,
private val initialOrigin: FirDeclarationOrigin private val initialOrigin: FirDeclarationOrigin,
val classLikeDeclaration: KtClassLikeDeclaration? = null
) { ) {
val session: FirSession = moduleData.session val session: FirSession = moduleData.session
@@ -42,7 +42,7 @@ internal class StubBasedFirTypeDeserializer(
private val annotationDeserializer: StubBasedAnnotationDeserializer, private val annotationDeserializer: StubBasedAnnotationDeserializer,
private val parent: StubBasedFirTypeDeserializer?, private val parent: StubBasedFirTypeDeserializer?,
private val containingSymbol: FirBasedSymbol<*>?, private val containingSymbol: FirBasedSymbol<*>?,
owner: KtTypeParameterListOwner, owner: KtTypeParameterListOwner?,
initialOrigin: FirDeclarationOrigin initialOrigin: FirDeclarationOrigin
) { ) {
private val typeParametersByName: Map<String, FirTypeParameterSymbol> private val typeParametersByName: Map<String, FirTypeParameterSymbol>
@@ -51,8 +51,8 @@ internal class StubBasedFirTypeDeserializer(
get() = typeParametersByName.values.toList() get() = typeParametersByName.values.toList()
init { init {
val typeParameters = owner.typeParameters val typeParameters = owner?.typeParameters
if (typeParameters.isNotEmpty()) { if (!typeParameters.isNullOrEmpty()) {
typeParametersByName = mutableMapOf() typeParametersByName = mutableMapOf()
val builders = mutableListOf<FirTypeParameterBuilder>() val builders = mutableListOf<FirTypeParameterBuilder>()
for (typeParameter in typeParameters) { for (typeParameter in typeParameters) {
@@ -70,7 +70,7 @@ internal class FirDeclarationForCompiledElementSearcher(private val symbolProvid
val classCandidate = when (symbolProvider) { val classCandidate = when (symbolProvider) {
is LLFirModuleWithDependenciesSymbolProvider -> { is LLFirModuleWithDependenciesSymbolProvider -> {
symbolProvider.getClassLikeSymbolByFqNameWithoutDependencies(classId) symbolProvider.getClassLikeSymbolByFqNameWithoutDependencies(declaration, classId)
?: symbolProvider.friendBuiltinsProvider?.getClassLikeSymbolByClassId(classId) ?: symbolProvider.friendBuiltinsProvider?.getClassLikeSymbolByClassId(classId)
} }
else -> { else -> {
@@ -162,7 +162,7 @@ private fun FirSymbolProvider.findCallableCandidates(
@OptIn(FirSymbolProviderInternals::class) @OptIn(FirSymbolProviderInternals::class)
return when (this) { return when (this) {
is LLFirModuleWithDependenciesSymbolProvider -> buildList { is LLFirModuleWithDependenciesSymbolProvider -> buildList {
getTopLevelCallableSymbolsToWithoutDependencies(this, packageFqName, shortName) getTopLevelDeserializedCallableSymbolsToWithoutDependencies(this, declaration, packageFqName, shortName)
friendBuiltinsProvider?.getTopLevelCallableSymbolsTo(this, packageFqName, shortName) friendBuiltinsProvider?.getTopLevelCallableSymbolsTo(this, packageFqName, shortName)
} }
else -> getTopLevelCallableSymbols(packageFqName, shortName) else -> getTopLevelCallableSymbols(packageFqName, shortName)