Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import org.jetbrains.kotlin.protobuf.GeneratedMessageLite.GeneratedExtension
import org.jetbrains.kotlin.resolve.KlibCompilerDeserializationConfiguration
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
import org.jetbrains.kotlin.serialization.deserialization.getClassId
import java.util.IdentityHashMap

abstract class MetadataLibraryBasedSymbolProvider<L : MetadataLibrary>(
session: FirSession,
Expand All @@ -53,6 +54,8 @@ abstract class MetadataLibraryBasedSymbolProvider<L : MetadataLibrary>(
protected val deserializationConfiguration: KlibCompilerDeserializationConfiguration =
KlibCompilerDeserializationConfiguration(session.languageVersionSettings)
private val cachedFragments: MutableMap<L, MutableMap<Pair<String, String>, ProtoBuf.PackageFragment>> = mutableMapOf()
private val fragmentToNameResolver = IdentityHashMap<ProtoBuf.PackageFragment, NameResolver>()
private val fragmentToKlibMetadataClassDataFinder = IdentityHashMap<ProtoBuf.PackageFragment, KlibMetadataClassDataFinder>()

private fun getPackageFragment(
resolvedLibrary: L, packageStringName: String, packageMetadataPart: String
Expand All @@ -64,6 +67,22 @@ abstract class MetadataLibraryBasedSymbolProvider<L : MetadataLibrary>(
}
}

private fun getNameResolver(fragment: ProtoBuf.PackageFragment): NameResolver {
return fragmentToNameResolver.getOrPut(fragment) {
NameResolverImpl(
fragment.strings,
fragment.qualifiedNames,
)
}
}

private fun getFinder(fragment: ProtoBuf.PackageFragment, resolver: NameResolver): KlibMetadataClassDataFinder {
return fragmentToKlibMetadataClassDataFinder.getOrPut(fragment) {
// Assumes the fact that the nameResolver depends only on the fragment.
KlibMetadataClassDataFinder(fragment, resolver)
}
}

override fun computePackagePartsInfos(packageFqName: FqName): List<PackagePartsCacheData> {
val packageStringName = if (packageFqName.isRoot) "" else packageFqName.asString()

Expand All @@ -78,10 +97,7 @@ abstract class MetadataLibraryBasedSymbolProvider<L : MetadataLibrary>(

val packageProto = fragment.`package`

val nameResolver = NameResolverImpl(
fragment.strings,
fragment.qualifiedNames,
)
val nameResolver = getNameResolver(fragment)

PackagePartsCacheData(
packageProto,
Expand Down Expand Up @@ -112,7 +128,7 @@ abstract class MetadataLibraryBasedSymbolProvider<L : MetadataLibrary>(
@OptIn(SymbolInternals::class)
override fun extractClassMetadata(classId: ClassId, parentContext: FirDeserializationContext?): ClassMetadataFindResult? {
forEachFragmentInPackage(classId.packageFqName) { resolvedLibrary, fragment, nameResolver ->
val finder = KlibMetadataClassDataFinder(fragment, nameResolver)
val finder = getFinder(fragment, nameResolver)
val classProto = finder.findClassData(classId)?.classProto ?: return@forEachFragmentInPackage

val moduleData = moduleData(resolvedLibrary) ?: return null
Expand Down Expand Up @@ -167,10 +183,7 @@ abstract class MetadataLibraryBasedSymbolProvider<L : MetadataLibrary>(

val fragment = getPackageFragment(resolvedLibrary, packageStringName, packageMetadataPart)

val nameResolver = NameResolverImpl(
fragment.strings,
fragment.qualifiedNames,
)
val nameResolver = getNameResolver(fragment)

f(resolvedLibrary, fragment, nameResolver)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.serialization.deserialization.ClassData
import org.jetbrains.kotlin.serialization.deserialization.ClassDataFinder
import org.jetbrains.kotlin.serialization.deserialization.getClassId
import java.util.HashMap

class KlibMetadataClassDataFinder(
private val fragment: PackageFragment,
Expand All @@ -22,12 +23,13 @@ class KlibMetadataClassDataFinder(
) : ClassDataFinder {
val nameList = fragment.getExtension(KlibMetadataProtoBuf.className).orEmpty()

val classIdToIndex: Map<ClassId, Int> = buildMap {
nameList.forEachIndexed { index, value -> this[nameResolver.getClassId(value)] = index }
}

override fun findClassData(classId: ClassId): ClassData? {

val index = nameList.indexOfFirst { nameResolver.getClassId(it) == classId }
if (index == -1) {
return null
}
val index = classIdToIndex[classId] ?: return null

val foundClass = fragment.getClass_(index) ?: error("Could not find data for serialized class $classId")

Expand Down