[FIR] Add MetadataSymbolProvider

Extract common code from K1 to MetadataUtil
This commit is contained in:
Ivan Kochurkin
2023-01-16 23:24:23 +01:00
committed by Space Team
parent c103da98dd
commit e22359cc10
9 changed files with 166 additions and 36 deletions
@@ -27,6 +27,8 @@ interface KotlinMetadataFinder {
*/
fun findMetadata(classId: ClassId): InputStream?
fun findMetadataTopLevelClassesInPackage(packageFqName: FqName): Set<String>?
/**
* @return `true` iff this finder is able to locate the package with the given [fqName], containing .kotlin_metadata files.
* Note that returning `true` makes [MetadataPackageFragmentProvider] construct the package fragment for the package,
@@ -45,6 +45,9 @@ class ReflectKotlinClassFinder(private val classLoader: ClassLoader) : KotlinCla
// TODO
override fun findMetadata(classId: ClassId): InputStream? = null
// TODO
override fun findMetadataTopLevelClassesInPackage(packageFqName: FqName): Set<String>? = null
// TODO
override fun hasMetadataPackage(fqName: FqName): Boolean = false
@@ -0,0 +1,44 @@
/*
* 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.serialization.deserialization
import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.metadata.builtins.BuiltInsBinaryVersion
import org.jetbrains.kotlin.metadata.deserialization.NameResolverImpl
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol
import java.io.InputStream
class MetadataClassDataFinder(val finder: KotlinMetadataFinder) : ClassDataFinder {
override fun findClassData(classId: ClassId): ClassData? {
val topLevelClassId = generateSequence(classId, ClassId::getOuterClassId).last()
val stream = finder.findMetadata(topLevelClassId) ?: return null
val (message, nameResolver, version) = readProto(stream)
return message.class_List.firstOrNull { classProto ->
nameResolver.getClassId(classProto.fqName) == classId
}?.let { classProto ->
ClassData(nameResolver, classProto, version, SourceElement.NO_SOURCE)
}
}
}
fun readProto(stream: InputStream): Triple<ProtoBuf.PackageFragment, NameResolverImpl, BuiltInsBinaryVersion> {
val version = BuiltInsBinaryVersion.readFrom(stream)
if (!version.isCompatibleWithCurrentCompilerVersion()) {
// TODO: report a proper diagnostic
throw UnsupportedOperationException(
"Kotlin metadata definition format version is not supported: " +
"expected ${BuiltInsBinaryVersion.INSTANCE}, actual $version. " +
"Please update Kotlin"
)
}
val message = ProtoBuf.PackageFragment.parseFrom(stream, BuiltInSerializerProtocol.extensionRegistry)
val nameResolver = NameResolverImpl(message.strings, message.qualifiedNames)
return Triple(message, nameResolver, version)
}
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.serialization.deserialization
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.NotFoundClasses
import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.descriptors.deserialization.AdditionalClassPartsProvider
import org.jetbrains.kotlin.descriptors.deserialization.PlatformDependentDeclarationFilter
import org.jetbrains.kotlin.incremental.components.LookupTracker
@@ -36,7 +35,6 @@ import org.jetbrains.kotlin.serialization.deserialization.descriptors.Deserializ
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker
import org.jetbrains.kotlin.types.extensions.TypeAttributeTranslators
import java.io.InputStream
class MetadataPackageFragmentProvider(
storageManager: StorageManager,
@@ -85,16 +83,7 @@ class MetadataPackageFragment(
private val metadataPartProvider: MetadataPartProvider,
private val finder: KotlinMetadataFinder
) : DeserializedPackageFragment(fqName, storageManager, module) {
override val classDataFinder = ClassDataFinder { classId ->
val topLevelClassId = generateSequence(classId, ClassId::getOuterClassId).last()
val stream = finder.findMetadata(topLevelClassId) ?: return@ClassDataFinder null
val (message, nameResolver, version) = readProto(stream)
message.class_List.firstOrNull { classProto ->
nameResolver.getClassId(classProto.fqName) == classId
}?.let { classProto ->
ClassData(nameResolver, classProto, version, SourceElement.NO_SOURCE)
}
}
override val classDataFinder = MetadataClassDataFinder(finder)
private lateinit var components: DeserializationComponents
@@ -152,23 +141,6 @@ class MetadataPackageFragment(
return true
}
private fun readProto(stream: InputStream): Triple<ProtoBuf.PackageFragment, NameResolverImpl, BuiltInsBinaryVersion> {
val version = BuiltInsBinaryVersion.readFrom(stream)
if (!version.isCompatibleWithCurrentCompilerVersion()) {
// TODO: report a proper diagnostic
throw UnsupportedOperationException(
"Kotlin metadata definition format version is not supported: " +
"expected ${BuiltInsBinaryVersion.INSTANCE}, actual $version. " +
"Please update Kotlin"
)
}
val message = ProtoBuf.PackageFragment.parseFrom(stream, BuiltInSerializerProtocol.extensionRegistry)
val nameResolver = NameResolverImpl(message.strings, message.qualifiedNames)
return Triple(message, nameResolver, version)
}
companion object {
const val METADATA_FILE_EXTENSION = "kotlin_metadata"
const val DOT_METADATA_FILE_EXTENSION = ".$METADATA_FILE_EXTENSION"