[FIR] Split KotlinDeserializedJvmSymbolsProvider to common and JVM specific parts
This commit is contained in:
committed by
TeamCityServer
parent
e5b7cf23d6
commit
4ad7a4a2d1
@@ -171,7 +171,7 @@ object FirSessionFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return KotlinDeserializedJvmSymbolsProvider(
|
return KotlinDeserializedJvmSymbolsProvider(
|
||||||
this, project, packagePartProvider, javaSymbolProvider, kotlinClassFinder, javaClassFinder, kotlinScopeProvider
|
this, packagePartProvider, kotlinClassFinder, kotlinScopeProvider, javaSymbolProvider, javaClassFinder
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+214
@@ -0,0 +1,214 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 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.fir.deserialization
|
||||||
|
|
||||||
|
import com.intellij.openapi.progress.ProcessCanceledException
|
||||||
|
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.FirSymbolProvider
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProviderInternals
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.KotlinScopeProvider
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
||||||
|
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||||
|
import org.jetbrains.kotlin.metadata.deserialization.Flags
|
||||||
|
import org.jetbrains.kotlin.metadata.deserialization.NameResolver
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.name.isOneSegmentFQN
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.getName
|
||||||
|
|
||||||
|
abstract class AbstractFirDeserializedSymbolsProvider(
|
||||||
|
session: FirSession,
|
||||||
|
val packagePartProvider: PackagePartProvider,
|
||||||
|
val kotlinClassFinder: KotlinClassFinder,
|
||||||
|
val kotlinScopeProvider: KotlinScopeProvider,
|
||||||
|
) : FirSymbolProvider(session) {
|
||||||
|
|
||||||
|
// ------------------------ Caches ------------------------
|
||||||
|
|
||||||
|
private val packagePartsCache = session.firCachesFactory.createCache(::tryComputePackagePartInfos)
|
||||||
|
private val typeAliasCache = session.firCachesFactory.createCache(::findAndDeserializeTypeAlias)
|
||||||
|
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) {
|
||||||
|
postProcessDeserializedClass(result, symbol)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// ------------------------ Abstract members ------------------------
|
||||||
|
|
||||||
|
protected abstract val knownNameInPackageCache: KnownNameInPackageCache
|
||||||
|
|
||||||
|
protected abstract fun readClassFromClassFile(
|
||||||
|
classId: ClassId,
|
||||||
|
classFile: KotlinClassFinder.Result.ClassFileContent
|
||||||
|
): FirRegularClassSymbol?
|
||||||
|
|
||||||
|
protected abstract fun KotlinClassFinder.Result.KotlinClass.extractMetadata(): Pair<NameResolver, ProtoBuf.Class>?
|
||||||
|
protected abstract fun computePackagePartsInfos(packageFqName: FqName): List<PackagePartsCacheData>
|
||||||
|
protected abstract fun createAnnotationDeserializer(kotlinClass: KotlinClassFinder.Result.KotlinClass): AbstractAnnotationDeserializer
|
||||||
|
protected abstract fun createSourceElement(kotlinClass: KotlinClassFinder.Result.KotlinClass): DeserializedContainerSource
|
||||||
|
protected open fun postProcessDeserializedClass(kotlinClass: KotlinClassFinder.Result.KotlinClass, symbol: FirRegularClassSymbol) {}
|
||||||
|
|
||||||
|
// ------------------------ Deserialization methods ------------------------
|
||||||
|
|
||||||
|
private fun tryComputePackagePartInfos(packageFqName: FqName): List<PackagePartsCacheData> {
|
||||||
|
return try {
|
||||||
|
computePackagePartsInfos(packageFqName)
|
||||||
|
} catch (e: ProcessCanceledException) {
|
||||||
|
emptyList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun findAndDeserializeTypeAlias(classId: ClassId): FirTypeAliasSymbol? {
|
||||||
|
return getPackageParts(classId.packageFqName).firstNotNullOfOrNull { part ->
|
||||||
|
val ids = part.typeAliasNameIndex[classId.shortClassName]
|
||||||
|
if (ids == null || ids.isEmpty()) return@firstNotNullOfOrNull null
|
||||||
|
val aliasProto = ids.map { part.proto.getTypeAlias(it) }.single()
|
||||||
|
part.context.memberDeserializer.loadTypeAlias(aliasProto).symbol
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun findAndDeserializeClass(
|
||||||
|
classId: ClassId,
|
||||||
|
parentContext: FirDeserializationContext? = null
|
||||||
|
): Pair<FirRegularClassSymbol?, KotlinClassFinder.Result.KotlinClass?> {
|
||||||
|
if (knownNameInPackageCache.hasNoTopLevelClassOf(classId)) return null to null
|
||||||
|
val result = try {
|
||||||
|
kotlinClassFinder.findKotlinClassOrContent(classId)
|
||||||
|
} catch (e: ProcessCanceledException) {
|
||||||
|
return null to null
|
||||||
|
}
|
||||||
|
val kotlinClass = when (result) {
|
||||||
|
is KotlinClassFinder.Result.KotlinClass -> result
|
||||||
|
is KotlinClassFinder.Result.ClassFileContent -> return readClassFromClassFile(classId, result) to null
|
||||||
|
null -> return findAndDeserializeClassViaParent(classId) to null
|
||||||
|
}
|
||||||
|
if (kotlinClass.kotlinJvmBinaryClass.classHeader.kind != KotlinClassHeader.Kind.CLASS) return null to null
|
||||||
|
val (nameResolver, classProto) = kotlinClass.extractMetadata() ?: return null to null
|
||||||
|
|
||||||
|
if (parentContext == null && Flags.CLASS_KIND.get(classProto.flags) == ProtoBuf.Class.Kind.COMPANION_OBJECT) {
|
||||||
|
return findAndDeserializeClassViaParent(classId) to null
|
||||||
|
}
|
||||||
|
|
||||||
|
val symbol = FirRegularClassSymbol(classId)
|
||||||
|
deserializeClassToSymbol(
|
||||||
|
classId, classProto, symbol, nameResolver, session,
|
||||||
|
createAnnotationDeserializer(kotlinClass),
|
||||||
|
kotlinScopeProvider,
|
||||||
|
parentContext,
|
||||||
|
createSourceElement(kotlinClass),
|
||||||
|
deserializeNestedClass = this::getClass,
|
||||||
|
)
|
||||||
|
|
||||||
|
return symbol to kotlinClass
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun findAndDeserializeClassViaParent(classId: ClassId): FirRegularClassSymbol? {
|
||||||
|
val outerClassId = classId.outerClassId ?: return null
|
||||||
|
getClass(outerClassId) ?: return null
|
||||||
|
return classCache.getValueIfComputed(classId)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadFunctionsByName(part: PackagePartsCacheData, name: Name): List<FirNamedFunctionSymbol> {
|
||||||
|
val functionIds = part.topLevelFunctionNameIndex[name] ?: return emptyList()
|
||||||
|
return functionIds.map {
|
||||||
|
part.context.memberDeserializer.loadFunction(part.proto.getFunction(it)).symbol
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadPropertiesByName(part: PackagePartsCacheData, name: Name): List<FirPropertySymbol> {
|
||||||
|
val propertyIds = part.topLevelPropertyNameIndex[name] ?: return emptyList()
|
||||||
|
return propertyIds.map {
|
||||||
|
part.context.memberDeserializer.loadProperty(part.proto.getProperty(it)).symbol
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------ SymbolProvider methods ------------------------
|
||||||
|
|
||||||
|
@FirSymbolProviderInternals
|
||||||
|
override fun getTopLevelCallableSymbolsTo(destination: MutableList<FirCallableSymbol<*>>, packageFqName: FqName, name: Name) {
|
||||||
|
getPackageParts(packageFqName).flatMapTo(destination) { part ->
|
||||||
|
loadFunctionsByName(part, name) + loadPropertiesByName(part, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@FirSymbolProviderInternals
|
||||||
|
override fun getTopLevelFunctionSymbolsTo(destination: MutableList<FirNamedFunctionSymbol>, packageFqName: FqName, name: Name) {
|
||||||
|
getPackageParts(packageFqName).flatMapTo(destination) { part ->
|
||||||
|
loadFunctionsByName(part, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@FirSymbolProviderInternals
|
||||||
|
override fun getTopLevelPropertySymbolsTo(destination: MutableList<FirPropertySymbol>, packageFqName: FqName, name: Name) {
|
||||||
|
getPackageParts(packageFqName).flatMapTo(destination) { part ->
|
||||||
|
loadPropertiesByName(part, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getClassLikeSymbolByFqName(classId: ClassId): FirClassLikeSymbol<*>? {
|
||||||
|
return getClass(classId) ?: getTypeAlias(classId)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getClass(
|
||||||
|
classId: ClassId,
|
||||||
|
parentContext: FirDeserializationContext? = null
|
||||||
|
): FirRegularClassSymbol? {
|
||||||
|
return classCache.getValue(classId, parentContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getTypeAlias(
|
||||||
|
classId: ClassId,
|
||||||
|
): FirTypeAliasSymbol? {
|
||||||
|
if (!classId.relativeClassName.isOneSegmentFQN()) return null
|
||||||
|
return typeAliasCache.getValue(classId)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getPackageParts(packageFqName: FqName): Collection<PackagePartsCacheData> {
|
||||||
|
return packagePartsCache.getValue(packageFqName)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getPackage(fqName: FqName): FqName? = null
|
||||||
|
|
||||||
|
// ------------------------ Additional classes ------------------------
|
||||||
|
|
||||||
|
protected class PackagePartsCacheData(
|
||||||
|
val proto: ProtoBuf.Package,
|
||||||
|
val context: FirDeserializationContext,
|
||||||
|
) {
|
||||||
|
val topLevelFunctionNameIndex by lazy {
|
||||||
|
proto.functionList.withIndex()
|
||||||
|
.groupBy({ context.nameResolver.getName(it.value.name) }) { (index) -> index }
|
||||||
|
}
|
||||||
|
val topLevelPropertyNameIndex by lazy {
|
||||||
|
proto.propertyList.withIndex()
|
||||||
|
.groupBy({ context.nameResolver.getName(it.value.name) }) { (index) -> index }
|
||||||
|
}
|
||||||
|
val typeAliasNameIndex by lazy {
|
||||||
|
proto.typeAliasList.withIndex()
|
||||||
|
.groupBy({ context.nameResolver.getName(it.value.name) }) { (index) -> index }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract class KnownNameInPackageCache {
|
||||||
|
/**
|
||||||
|
* This function returns true if we are sure that no top-level class with this id is available
|
||||||
|
* If it returns false, it means we can say nothing about this id
|
||||||
|
*/
|
||||||
|
abstract fun hasNoTopLevelClassOf(classId: ClassId): Boolean
|
||||||
|
}
|
||||||
|
}
|
||||||
+43
-187
@@ -5,16 +5,15 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.java.deserialization
|
package org.jetbrains.kotlin.fir.java.deserialization
|
||||||
|
|
||||||
import com.intellij.openapi.progress.ProcessCanceledException
|
|
||||||
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.*
|
import org.jetbrains.kotlin.fir.caches.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.fir.deserialization.AbstractAnnotationDeserializer
|
||||||
|
import org.jetbrains.kotlin.fir.deserialization.AbstractFirDeserializedSymbolsProvider
|
||||||
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
|
||||||
import org.jetbrains.kotlin.fir.deserialization.deserializeClassToSymbol
|
|
||||||
import org.jetbrains.kotlin.fir.expressions.*
|
import org.jetbrains.kotlin.fir.expressions.*
|
||||||
import org.jetbrains.kotlin.fir.expressions.builder.*
|
import org.jetbrains.kotlin.fir.expressions.builder.*
|
||||||
import org.jetbrains.kotlin.fir.java.JavaSymbolProvider
|
import org.jetbrains.kotlin.fir.java.JavaSymbolProvider
|
||||||
@@ -24,69 +23,39 @@ import org.jetbrains.kotlin.fir.scopes.KotlinScopeProvider
|
|||||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||||
import org.jetbrains.kotlin.load.java.JavaClassFinder
|
import org.jetbrains.kotlin.load.java.JavaClassFinder
|
||||||
import org.jetbrains.kotlin.load.kotlin.*
|
import org.jetbrains.kotlin.load.kotlin.*
|
||||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
|
||||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||||
import org.jetbrains.kotlin.metadata.deserialization.Flags
|
import org.jetbrains.kotlin.metadata.deserialization.NameResolver
|
||||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion
|
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion
|
||||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmNameResolver
|
|
||||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
|
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
|
||||||
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.isOneSegmentFQN
|
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData
|
import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.getName
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
|
||||||
|
|
||||||
@ThreadSafeMutableState
|
@ThreadSafeMutableState
|
||||||
class KotlinDeserializedJvmSymbolsProvider(
|
class KotlinDeserializedJvmSymbolsProvider(
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
val project: Project,
|
packagePartProvider: PackagePartProvider,
|
||||||
private val packagePartProvider: PackagePartProvider,
|
kotlinClassFinder: KotlinClassFinder,
|
||||||
|
kotlinScopeProvider: KotlinScopeProvider,
|
||||||
private val javaSymbolProvider: JavaSymbolProvider,
|
private val javaSymbolProvider: JavaSymbolProvider,
|
||||||
private val kotlinClassFinder: KotlinClassFinder,
|
javaClassFinder: JavaClassFinder,
|
||||||
private val javaClassFinder: JavaClassFinder,
|
) : AbstractFirDeserializedSymbolsProvider(session, packagePartProvider, kotlinClassFinder, kotlinScopeProvider) {
|
||||||
private val kotlinScopeProvider: KotlinScopeProvider,
|
override val knownNameInPackageCache: KnownNameInPackageCache = JvmKnownNameInPackageCache(session, javaClassFinder)
|
||||||
) : FirSymbolProvider(session) {
|
|
||||||
private val annotationsLoader = AnnotationsLoader(session)
|
private val annotationsLoader = AnnotationsLoader(session)
|
||||||
private val typeAliasCache = session.firCachesFactory.createCache(::findAndDeserializeTypeAlias)
|
|
||||||
private val packagePartsCache = session.firCachesFactory.createCache(::tryComputePackagePartInfos)
|
|
||||||
|
|
||||||
private val classCache =
|
override fun readClassFromClassFile(classId: ClassId, classFile: KotlinClassFinder.Result.ClassFileContent): FirRegularClassSymbol? {
|
||||||
session.firCachesFactory.createCacheWithPostCompute<ClassId, FirRegularClassSymbol?, FirDeserializationContext?, KotlinClassFinder.Result.KotlinClass?>(
|
return javaSymbolProvider.getFirJavaClass(classId, classFile)
|
||||||
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 class PackagePartsCacheData(
|
|
||||||
val proto: ProtoBuf.Package,
|
|
||||||
val context: FirDeserializationContext,
|
|
||||||
) {
|
|
||||||
val topLevelFunctionNameIndex by lazy {
|
|
||||||
proto.functionList.withIndex()
|
|
||||||
.groupBy({ context.nameResolver.getName(it.value.name) }) { (index) -> index }
|
|
||||||
}
|
|
||||||
val topLevelPropertyNameIndex by lazy {
|
|
||||||
proto.propertyList.withIndex()
|
|
||||||
.groupBy({ context.nameResolver.getName(it.value.name) }) { (index) -> index }
|
|
||||||
}
|
|
||||||
val typeAliasNameIndex by lazy {
|
|
||||||
proto.typeAliasList.withIndex()
|
|
||||||
.groupBy({ context.nameResolver.getName(it.value.name) }) { (index) -> index }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun KotlinClassFinder.Result.KotlinClass.extractMetadata(): Pair<NameResolver, ProtoBuf.Class>? {
|
||||||
|
val data = kotlinJvmBinaryClass.classHeader.data ?: return null
|
||||||
|
val strings = kotlinJvmBinaryClass.classHeader.strings ?: return null
|
||||||
|
return JvmProtoBufUtil.readClassDataFrom(data, strings)
|
||||||
|
}
|
||||||
|
|
||||||
private fun computePackagePartsInfos(packageFqName: FqName): List<PackagePartsCacheData> {
|
override fun computePackagePartsInfos(packageFqName: FqName): List<PackagePartsCacheData> {
|
||||||
|
|
||||||
return packagePartProvider.findPackageParts(packageFqName.asString()).mapNotNull { partName ->
|
return packagePartProvider.findPackageParts(packageFqName.asString()).mapNotNull { partName ->
|
||||||
val classId = ClassId.topLevel(JvmClassName.byInternalName(partName).fqNameForTopLevelClassMaybeWithDollars)
|
val classId = ClassId.topLevel(JvmClassName.byInternalName(partName).fqNameForTopLevelClassMaybeWithDollars)
|
||||||
if (knownNameInPackageCache.hasNoTopLevelClassOf(classId)) return@mapNotNull null
|
if (knownNameInPackageCache.hasNoTopLevelClassOf(classId)) return@mapNotNull null
|
||||||
@@ -129,89 +98,12 @@ class KotlinDeserializedJvmSymbolsProvider(
|
|||||||
private val KotlinJvmBinaryClass.isPreReleaseInvisible: Boolean
|
private val KotlinJvmBinaryClass.isPreReleaseInvisible: Boolean
|
||||||
get() = classHeader.isPreRelease
|
get() = classHeader.isPreRelease
|
||||||
|
|
||||||
override fun getClassLikeSymbolByFqName(classId: ClassId): FirClassLikeSymbol<*>? {
|
override fun postProcessDeserializedClass(
|
||||||
return getClass(classId) ?: getTypeAlias(classId)
|
kotlinClass: KotlinClassFinder.Result.KotlinClass,
|
||||||
}
|
|
||||||
|
|
||||||
private fun getTypeAlias(
|
|
||||||
classId: ClassId,
|
|
||||||
): FirTypeAliasSymbol? {
|
|
||||||
if (!classId.relativeClassName.isOneSegmentFQN()) return null
|
|
||||||
return typeAliasCache.getValue(classId)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun findAndDeserializeTypeAlias(classId: ClassId): FirTypeAliasSymbol? {
|
|
||||||
return getPackageParts(classId.packageFqName).firstNotNullOfOrNull { part ->
|
|
||||||
val ids = part.typeAliasNameIndex[classId.shortClassName]
|
|
||||||
if (ids == null || ids.isEmpty()) return@firstNotNullOfOrNull null
|
|
||||||
val aliasProto = ids.map { part.proto.getTypeAlias(it) }.single()
|
|
||||||
part.context.memberDeserializer.loadTypeAlias(aliasProto).symbol
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun KotlinJvmBinaryClass.readClassDataFrom(): Pair<JvmNameResolver, ProtoBuf.Class>? {
|
|
||||||
val data = classHeader.data ?: return null
|
|
||||||
val strings = classHeader.strings ?: return null
|
|
||||||
return JvmProtoBufUtil.readClassDataFrom(data, strings)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private fun findAndDeserializeClassViaParent(classId: ClassId): FirRegularClassSymbol? {
|
|
||||||
val outerClassId = classId.outerClassId ?: return null
|
|
||||||
getClass(outerClassId) ?: return null
|
|
||||||
return classCache.getValueIfComputed(classId)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getClass(
|
|
||||||
classId: ClassId,
|
|
||||||
parentContext: FirDeserializationContext? = null
|
|
||||||
): FirRegularClassSymbol? {
|
|
||||||
return classCache.getValue(classId, parentContext)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun findAndDeserializeClass(
|
|
||||||
classId: ClassId,
|
|
||||||
parentContext: FirDeserializationContext? = null
|
|
||||||
): Pair<FirRegularClassSymbol?, KotlinClassFinder.Result.KotlinClass?> {
|
|
||||||
if (knownNameInPackageCache.hasNoTopLevelClassOf(classId)) return null to null
|
|
||||||
val result = try {
|
|
||||||
kotlinClassFinder.findKotlinClassOrContent(classId)
|
|
||||||
} catch (e: ProcessCanceledException) {
|
|
||||||
return null to null
|
|
||||||
}
|
|
||||||
val kotlinClass = when (result) {
|
|
||||||
is KotlinClassFinder.Result.KotlinClass -> result
|
|
||||||
is KotlinClassFinder.Result.ClassFileContent -> {
|
|
||||||
return javaSymbolProvider.getFirJavaClass(classId, result) to null
|
|
||||||
}
|
|
||||||
null -> return findAndDeserializeClassViaParent(classId) to null
|
|
||||||
}
|
|
||||||
if (kotlinClass.kotlinJvmBinaryClass.classHeader.kind != KotlinClassHeader.Kind.CLASS) return null to 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) {
|
|
||||||
return findAndDeserializeClassViaParent(classId) to null
|
|
||||||
}
|
|
||||||
|
|
||||||
val symbol = FirRegularClassSymbol(classId)
|
|
||||||
deserializeClassToSymbol(
|
|
||||||
classId, classProto, symbol, nameResolver, session,
|
|
||||||
JvmBinaryAnnotationDeserializer(session, kotlinClass.kotlinJvmBinaryClass, kotlinClassFinder, kotlinClass.byteContent),
|
|
||||||
kotlinScopeProvider,
|
|
||||||
parentContext, KotlinJvmBinarySourceElement(kotlinClass.kotlinJvmBinaryClass),
|
|
||||||
deserializeNestedClass = this::getClass,
|
|
||||||
)
|
|
||||||
|
|
||||||
return symbol to kotlinClass
|
|
||||||
}
|
|
||||||
|
|
||||||
fun postCompute(
|
|
||||||
kotlinJvmBinaryClass: KotlinJvmBinaryClass,
|
|
||||||
byteContent: ByteArray?,
|
|
||||||
symbol: FirRegularClassSymbol
|
symbol: FirRegularClassSymbol
|
||||||
) {
|
) {
|
||||||
val annotations = mutableListOf<FirAnnotationCall>()
|
val annotations = mutableListOf<FirAnnotationCall>()
|
||||||
kotlinJvmBinaryClass.loadClassAnnotations(
|
kotlinClass.kotlinJvmBinaryClass.loadClassAnnotations(
|
||||||
object : KotlinJvmBinaryClass.AnnotationVisitor {
|
object : KotlinJvmBinaryClass.AnnotationVisitor {
|
||||||
override fun visitAnnotation(classId: ClassId, source: SourceElement): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
|
override fun visitAnnotation(classId: ClassId, source: SourceElement): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
|
||||||
return annotationsLoader.loadAnnotationIfNotSpecial(classId, annotations)
|
return annotationsLoader.loadAnnotationIfNotSpecial(classId, annotations)
|
||||||
@@ -220,70 +112,34 @@ class KotlinDeserializedJvmSymbolsProvider(
|
|||||||
override fun visitEnd() {
|
override fun visitEnd() {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
byteContent,
|
kotlinClass.byteContent,
|
||||||
)
|
)
|
||||||
(symbol.fir.annotations as MutableList<FirAnnotationCall>) += annotations
|
(symbol.fir.annotations as MutableList<FirAnnotationCall>) += annotations
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadFunctionsByName(part: PackagePartsCacheData, name: Name): List<FirNamedFunctionSymbol> {
|
override fun createAnnotationDeserializer(kotlinClass: KotlinClassFinder.Result.KotlinClass): AbstractAnnotationDeserializer {
|
||||||
val functionIds = part.topLevelFunctionNameIndex[name] ?: return emptyList()
|
return JvmBinaryAnnotationDeserializer(session, kotlinClass.kotlinJvmBinaryClass, kotlinClassFinder, kotlinClass.byteContent)
|
||||||
return functionIds.map {
|
}
|
||||||
part.context.memberDeserializer.loadFunction(part.proto.getFunction(it)).symbol
|
|
||||||
|
override fun createSourceElement(kotlinClass: KotlinClassFinder.Result.KotlinClass): DeserializedContainerSource {
|
||||||
|
return KotlinJvmBinarySourceElement(kotlinClass.kotlinJvmBinaryClass)
|
||||||
|
}
|
||||||
|
|
||||||
|
private class JvmKnownNameInPackageCache(
|
||||||
|
session: FirSession,
|
||||||
|
private val javaClassFinder: JavaClassFinder
|
||||||
|
) : KnownNameInPackageCache() {
|
||||||
|
private val knownClassNamesInPackage = session.firCachesFactory.createCache(javaClassFinder::knownClassNamesInPackage)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function returns true if we are sure that no top-level class with this id is available
|
||||||
|
* If it returns false, it means we can say nothing about this id
|
||||||
|
*/
|
||||||
|
override fun hasNoTopLevelClassOf(classId: ClassId): Boolean {
|
||||||
|
val knownNames = knownClassNamesInPackage.getValue(classId.packageFqName) ?: return false
|
||||||
|
return classId.relativeClassName.topLevelName() !in knownNames
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadPropertiesByName(part: PackagePartsCacheData, name: Name): List<FirPropertySymbol> {
|
|
||||||
val propertyIds = part.topLevelPropertyNameIndex[name] ?: return emptyList()
|
|
||||||
return propertyIds.map {
|
|
||||||
part.context.memberDeserializer.loadProperty(part.proto.getProperty(it)).symbol
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@FirSymbolProviderInternals
|
|
||||||
override fun getTopLevelCallableSymbolsTo(destination: MutableList<FirCallableSymbol<*>>, packageFqName: FqName, name: Name) {
|
|
||||||
getPackageParts(packageFqName).flatMapTo(destination) { part ->
|
|
||||||
loadFunctionsByName(part, name) + loadPropertiesByName(part, name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@FirSymbolProviderInternals
|
|
||||||
override fun getTopLevelFunctionSymbolsTo(destination: MutableList<FirNamedFunctionSymbol>, packageFqName: FqName, name: Name) {
|
|
||||||
getPackageParts(packageFqName).flatMapTo(destination) { part ->
|
|
||||||
loadFunctionsByName(part, name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@FirSymbolProviderInternals
|
|
||||||
override fun getTopLevelPropertySymbolsTo(destination: MutableList<FirPropertySymbol>, packageFqName: FqName, name: Name) {
|
|
||||||
getPackageParts(packageFqName).flatMapTo(destination) { part ->
|
|
||||||
loadPropertiesByName(part, name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getPackageParts(packageFqName: FqName): Collection<PackagePartsCacheData> {
|
|
||||||
return packagePartsCache.getValue(packageFqName)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun tryComputePackagePartInfos(packageFqName: FqName): List<PackagePartsCacheData> {
|
|
||||||
return try {
|
|
||||||
computePackagePartsInfos(packageFqName)
|
|
||||||
} catch (e: ProcessCanceledException) {
|
|
||||||
emptyList()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getPackage(fqName: FqName): FqName? = null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class KnownNameInPackageCache(session: FirSession, private val javaClassFinder: JavaClassFinder) {
|
|
||||||
private val knownClassNamesInPackage = session.firCachesFactory.createCache(javaClassFinder::knownClassNamesInPackage)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function returns true if we are sure that no top-level class with this id is available
|
|
||||||
* If it returns false, it means we can say nothing about this id
|
|
||||||
*/
|
|
||||||
fun hasNoTopLevelClassOf(classId: ClassId): Boolean {
|
|
||||||
val knownNames = knownClassNamesInPackage.getValue(classId.packageFqName) ?: return false
|
|
||||||
return classId.relativeClassName.topLevelName() !in knownNames
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+3
-4
@@ -187,12 +187,11 @@ internal object FirIdeSessionFactory {
|
|||||||
FirThreadSafeSymbolProviderWrapper(
|
FirThreadSafeSymbolProviderWrapper(
|
||||||
KotlinDeserializedJvmSymbolsProvider(
|
KotlinDeserializedJvmSymbolsProvider(
|
||||||
this@apply,
|
this@apply,
|
||||||
project,
|
|
||||||
packagePartProvider,
|
packagePartProvider,
|
||||||
javaSymbolProvider,
|
|
||||||
kotlinClassFinder,
|
kotlinClassFinder,
|
||||||
javaClassFinder,
|
kotlinScopeProvider,
|
||||||
kotlinScopeProvider
|
javaSymbolProvider,
|
||||||
|
javaClassFinder
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user