FIR: use FirCachesFactory for
class cache in KotlinDeserializedJvmSymbolsProvider
This commit is contained in:
+42
-30
@@ -10,7 +10,7 @@ import com.intellij.openapi.project.Project
|
|||||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.ThreadSafeMutableState
|
import org.jetbrains.kotlin.fir.ThreadSafeMutableState
|
||||||
import org.jetbrains.kotlin.fir.caches.firCachesFactory
|
import org.jetbrains.kotlin.fir.caches.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.deserialization.FirConstDeserializer
|
import org.jetbrains.kotlin.fir.deserialization.FirConstDeserializer
|
||||||
import org.jetbrains.kotlin.fir.deserialization.FirDeserializationContext
|
import org.jetbrains.kotlin.fir.deserialization.FirDeserializationContext
|
||||||
@@ -50,14 +50,22 @@ class KotlinDeserializedJvmSymbolsProvider(
|
|||||||
private val kotlinScopeProvider: KotlinScopeProvider,
|
private val kotlinScopeProvider: KotlinScopeProvider,
|
||||||
) : FirSymbolProvider(session) {
|
) : FirSymbolProvider(session) {
|
||||||
private val annotationsLoader = AnnotationsLoader(session)
|
private val annotationsLoader = AnnotationsLoader(session)
|
||||||
private val classCache = SymbolProviderCache<ClassId, FirRegularClassSymbol>()
|
|
||||||
private val typeAliasCache = SymbolProviderCache<ClassId, FirTypeAliasSymbol>()
|
private val typeAliasCache = SymbolProviderCache<ClassId, FirTypeAliasSymbol>()
|
||||||
private val packagePartsCache = SymbolProviderCache<FqName, Collection<PackagePartsCacheData>>()
|
private val packagePartsCache = SymbolProviderCache<FqName, Collection<PackagePartsCacheData>>()
|
||||||
|
|
||||||
|
private val classCache =
|
||||||
|
session.firCachesFactory.createCacheWithPostCompute<ClassId, FirRegularClassSymbol?, FirDeserializationContext?, KotlinClassFinder.Result.KotlinClass?>(
|
||||||
|
createValue = { classId, context -> findAndDeserializeClass(classId, context) },
|
||||||
|
postCompute = { _, symbol, result ->
|
||||||
|
if (result != null && symbol != null) {
|
||||||
|
postCompute(result.kotlinJvmBinaryClass, result.byteContent, symbol)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
private val knownNameInPackageCache = KnownNameInPackageCache(session, javaClassFinder)
|
private val knownNameInPackageCache = KnownNameInPackageCache(session, javaClassFinder)
|
||||||
|
|
||||||
// TODO: implement thread safety for this property
|
|
||||||
private val handledByJava = HashSet<ClassId>()
|
|
||||||
|
|
||||||
private class PackagePartsCacheData(
|
private class PackagePartsCacheData(
|
||||||
val proto: ProtoBuf.Package,
|
val proto: ProtoBuf.Package,
|
||||||
@@ -123,7 +131,7 @@ class KotlinDeserializedJvmSymbolsProvider(
|
|||||||
get() = classHeader.isPreRelease
|
get() = classHeader.isPreRelease
|
||||||
|
|
||||||
override fun getClassLikeSymbolByFqName(classId: ClassId): FirClassLikeSymbol<*>? {
|
override fun getClassLikeSymbolByFqName(classId: ClassId): FirClassLikeSymbol<*>? {
|
||||||
return findAndDeserializeClass(classId) ?: findAndDeserializeTypeAlias(classId)
|
return getClass(classId) ?: findAndDeserializeTypeAlias(classId)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findAndDeserializeTypeAlias(
|
private fun findAndDeserializeTypeAlias(
|
||||||
@@ -149,53 +157,58 @@ class KotlinDeserializedJvmSymbolsProvider(
|
|||||||
|
|
||||||
private fun findAndDeserializeClassViaParent(classId: ClassId): FirRegularClassSymbol? {
|
private fun findAndDeserializeClassViaParent(classId: ClassId): FirRegularClassSymbol? {
|
||||||
val outerClassId = classId.outerClassId ?: return null
|
val outerClassId = classId.outerClassId ?: return null
|
||||||
findAndDeserializeClass(outerClassId) ?: return null
|
getClass(outerClassId) ?: return null
|
||||||
return classCache[classId]
|
return classCache.getValueIfComputed(classId)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getClass(
|
||||||
|
classId: ClassId,
|
||||||
|
parentContext: FirDeserializationContext? = null
|
||||||
|
): FirRegularClassSymbol? {
|
||||||
|
return classCache.getValue(classId, parentContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findAndDeserializeClass(
|
private fun findAndDeserializeClass(
|
||||||
classId: ClassId,
|
classId: ClassId,
|
||||||
parentContext: FirDeserializationContext? = null
|
parentContext: FirDeserializationContext? = null
|
||||||
): FirRegularClassSymbol? {
|
): Pair<FirRegularClassSymbol?, KotlinClassFinder.Result.KotlinClass?> {
|
||||||
if (knownNameInPackageCache.hasNoTopLevelClassOf(classId)) return null
|
if (knownNameInPackageCache.hasNoTopLevelClassOf(classId)) return null to null
|
||||||
if (classId in classCache) return classCache[classId]
|
|
||||||
|
|
||||||
if (classId in handledByJava) return null
|
|
||||||
|
|
||||||
val result = try {
|
val result = try {
|
||||||
kotlinClassFinder.findKotlinClassOrContent(classId)
|
kotlinClassFinder.findKotlinClassOrContent(classId)
|
||||||
} catch (e: ProcessCanceledException) {
|
} catch (e: ProcessCanceledException) {
|
||||||
return null
|
return null to null
|
||||||
}
|
}
|
||||||
val (kotlinJvmBinaryClass, byteContent) = when (result) {
|
val kotlinClass = when (result) {
|
||||||
is KotlinClassFinder.Result.KotlinClass -> result
|
is KotlinClassFinder.Result.KotlinClass -> result
|
||||||
is KotlinClassFinder.Result.ClassFileContent -> {
|
is KotlinClassFinder.Result.ClassFileContent -> {
|
||||||
handledByJava.add(classId)
|
return javaSymbolProvider.getFirJavaClass(classId, result) to null
|
||||||
return try {
|
|
||||||
javaSymbolProvider.getFirJavaClass(classId, result)
|
|
||||||
} catch (e: ProcessCanceledException) {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
null -> return findAndDeserializeClassViaParent(classId)
|
null -> return findAndDeserializeClassViaParent(classId) to null
|
||||||
}
|
}
|
||||||
if (kotlinJvmBinaryClass.classHeader.kind != KotlinClassHeader.Kind.CLASS) return null
|
if (kotlinClass.kotlinJvmBinaryClass.classHeader.kind != KotlinClassHeader.Kind.CLASS) return null to null
|
||||||
val (nameResolver, classProto) = kotlinJvmBinaryClass.readClassDataFrom() ?: return null
|
val (nameResolver, classProto) = kotlinClass.kotlinJvmBinaryClass.readClassDataFrom() ?: return null to null
|
||||||
|
|
||||||
if (parentContext == null && Flags.CLASS_KIND.get(classProto.flags) == ProtoBuf.Class.Kind.COMPANION_OBJECT) {
|
if (parentContext == null && Flags.CLASS_KIND.get(classProto.flags) == ProtoBuf.Class.Kind.COMPANION_OBJECT) {
|
||||||
return findAndDeserializeClassViaParent(classId)
|
return findAndDeserializeClassViaParent(classId) to null
|
||||||
}
|
}
|
||||||
|
|
||||||
val symbol = FirRegularClassSymbol(classId)
|
val symbol = FirRegularClassSymbol(classId)
|
||||||
deserializeClassToSymbol(
|
deserializeClassToSymbol(
|
||||||
classId, classProto, symbol, nameResolver, session,
|
classId, classProto, symbol, nameResolver, session,
|
||||||
JvmBinaryAnnotationDeserializer(session, kotlinJvmBinaryClass, byteContent),
|
JvmBinaryAnnotationDeserializer(session, kotlinClass.kotlinJvmBinaryClass, kotlinClass.byteContent),
|
||||||
kotlinScopeProvider,
|
kotlinScopeProvider,
|
||||||
parentContext, KotlinJvmBinarySourceElement(kotlinJvmBinaryClass),
|
parentContext, KotlinJvmBinarySourceElement(kotlinClass.kotlinJvmBinaryClass),
|
||||||
this::findAndDeserializeClass
|
this::getClass
|
||||||
)
|
)
|
||||||
|
|
||||||
classCache[classId] = symbol
|
return symbol to kotlinClass
|
||||||
|
}
|
||||||
|
|
||||||
|
fun postCompute(
|
||||||
|
kotlinJvmBinaryClass: KotlinJvmBinaryClass,
|
||||||
|
byteContent: ByteArray?,
|
||||||
|
symbol: FirRegularClassSymbol
|
||||||
|
) {
|
||||||
val annotations = mutableListOf<FirAnnotationCall>()
|
val annotations = mutableListOf<FirAnnotationCall>()
|
||||||
kotlinJvmBinaryClass.loadClassAnnotations(
|
kotlinJvmBinaryClass.loadClassAnnotations(
|
||||||
object : KotlinJvmBinaryClass.AnnotationVisitor {
|
object : KotlinJvmBinaryClass.AnnotationVisitor {
|
||||||
@@ -209,7 +222,6 @@ class KotlinDeserializedJvmSymbolsProvider(
|
|||||||
byteContent,
|
byteContent,
|
||||||
)
|
)
|
||||||
(symbol.fir.annotations as MutableList<FirAnnotationCall>) += annotations
|
(symbol.fir.annotations as MutableList<FirAnnotationCall>) += annotations
|
||||||
return symbol
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadFunctionsByName(part: PackagePartsCacheData, name: Name): List<FirNamedFunctionSymbol> {
|
private fun loadFunctionsByName(part: PackagePartsCacheData, name: Name): List<FirNamedFunctionSymbol> {
|
||||||
|
|||||||
-1
@@ -38,7 +38,6 @@ import org.jetbrains.kotlin.idea.fir.low.level.api.fir.caches.FirThreadSafeCache
|
|||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.lazy.resolve.FirLazyDeclarationResolver
|
import org.jetbrains.kotlin.idea.fir.low.level.api.lazy.resolve.FirLazyDeclarationResolver
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.providers.FirModuleWithDependenciesSymbolProvider
|
import org.jetbrains.kotlin.idea.fir.low.level.api.providers.FirModuleWithDependenciesSymbolProvider
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.providers.FirIdeProvider
|
import org.jetbrains.kotlin.idea.fir.low.level.api.providers.FirIdeProvider
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.sessions.FirIdeSessionFactory.registerIdeComponents
|
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.providers.FirThreadSafeSymbolProviderWrapper
|
import org.jetbrains.kotlin.idea.fir.low.level.api.providers.FirThreadSafeSymbolProviderWrapper
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.util.ModuleLibrariesSearchScope
|
import org.jetbrains.kotlin.idea.fir.low.level.api.util.ModuleLibrariesSearchScope
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.util.checkCanceled
|
import org.jetbrains.kotlin.idea.fir.low.level.api.util.checkCanceled
|
||||||
|
|||||||
Reference in New Issue
Block a user