Add BinaryVersion to DeserializationContext
This will be useful to implement version-dependent deserialization, which is needed for gradual fixes of issues in metadata #KT-25120 In Progress
This commit is contained in:
+2
@@ -7,10 +7,12 @@ package org.jetbrains.kotlin.serialization.deserialization
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
|
||||
import org.jetbrains.kotlin.metadata.deserialization.NameResolver
|
||||
|
||||
data class ClassData(
|
||||
val nameResolver: NameResolver,
|
||||
val classProto: ProtoBuf.Class,
|
||||
val metadataVersion: BinaryVersion,
|
||||
val sourceElement: SourceElement
|
||||
)
|
||||
|
||||
+3
-2
@@ -39,7 +39,7 @@ class ClassDeserializer(private val components: DeserializationComponents) {
|
||||
}
|
||||
if (classId in BLACK_LIST) return null
|
||||
|
||||
val (nameResolver, classProto, sourceElement) = key.classData
|
||||
val (nameResolver, classProto, metadataVersion, sourceElement) = key.classData
|
||||
?: components.classDataFinder.findClassData(classId)
|
||||
?: return null
|
||||
|
||||
@@ -60,11 +60,12 @@ class ClassDeserializer(private val components: DeserializationComponents) {
|
||||
fragment, nameResolver,
|
||||
TypeTable(classProto.typeTable),
|
||||
VersionRequirementTable.create(classProto.versionRequirementTable),
|
||||
metadataVersion,
|
||||
containerSource = null
|
||||
)
|
||||
}
|
||||
|
||||
return DeserializedClassDescriptor(outerContext, classProto, nameResolver, sourceElement)
|
||||
return DeserializedClassDescriptor(outerContext, classProto, nameResolver, metadataVersion, sourceElement)
|
||||
}
|
||||
|
||||
private class ClassKey(val classId: ClassId, val classData: ClassData?) {
|
||||
|
||||
+5
-2
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.serialization.deserialization
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
|
||||
import org.jetbrains.kotlin.metadata.deserialization.NameResolverImpl
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
@@ -31,11 +32,13 @@ abstract class DeserializedPackageFragmentImpl(
|
||||
storageManager: StorageManager,
|
||||
module: ModuleDescriptor,
|
||||
proto: ProtoBuf.PackageFragment,
|
||||
private val metadataVersion: BinaryVersion,
|
||||
private val containerSource: DeserializedContainerSource?
|
||||
) : DeserializedPackageFragment(fqName, storageManager, module) {
|
||||
protected val nameResolver = NameResolverImpl(proto.strings, proto.qualifiedNames)
|
||||
|
||||
override val classDataFinder = ProtoBasedClassDataFinder(proto, nameResolver) { containerSource ?: SourceElement.NO_SOURCE }
|
||||
override val classDataFinder =
|
||||
ProtoBasedClassDataFinder(proto, nameResolver, metadataVersion) { containerSource ?: SourceElement.NO_SOURCE }
|
||||
|
||||
// Temporary storage: until `initialize` is called
|
||||
private var _proto: ProtoBuf.PackageFragment? = proto
|
||||
@@ -45,7 +48,7 @@ abstract class DeserializedPackageFragmentImpl(
|
||||
val proto = _proto ?: error("Repeated call to DeserializedPackageFragmentImpl::initialize")
|
||||
_proto = null
|
||||
_memberScope = DeserializedPackageMemberScope(
|
||||
this, proto.`package`, nameResolver, containerSource, components,
|
||||
this, proto.`package`, nameResolver, metadataVersion, containerSource, components,
|
||||
classNames = {
|
||||
classDataFinder.allClassIds.filter { classId ->
|
||||
!classId.isNestedClass && classId !in ClassDeserializer.BLACK_LIST
|
||||
|
||||
+1
@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
class MemberDeserializer(private val c: DeserializationContext) {
|
||||
private val annotationDeserializer = AnnotationDeserializer(c.components.moduleDescriptor, c.components.notFoundClasses)
|
||||
|
||||
fun loadProperty(proto: ProtoBuf.Property): PropertyDescriptor {
|
||||
val flags = if (proto.hasFlags()) proto.flags else loadOldFlags(proto.oldFlags)
|
||||
|
||||
|
||||
+8
-6
@@ -78,11 +78,11 @@ class MetadataPackageFragment(
|
||||
override val classDataFinder = ClassDataFinder { classId ->
|
||||
val topLevelClassId = generateSequence(classId, ClassId::getOuterClassId).last()
|
||||
val stream = finder.findMetadata(topLevelClassId) ?: return@ClassDataFinder null
|
||||
val (message, nameResolver) = readProto(stream)
|
||||
val (message, nameResolver, version) = readProto(stream)
|
||||
message.class_List.firstOrNull { classProto ->
|
||||
nameResolver.getClassId(classProto.fqName) == classId
|
||||
}?.let { classProto ->
|
||||
ClassData(nameResolver, classProto, SourceElement.NO_SOURCE)
|
||||
ClassData(nameResolver, classProto, version, SourceElement.NO_SOURCE)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,10 +101,11 @@ class MetadataPackageFragment(
|
||||
val scopes = arrayListOf<DeserializedPackageMemberScope>()
|
||||
for (partName in packageParts) {
|
||||
val stream = finder.findMetadata(ClassId(fqName, Name.identifier(partName))) ?: continue
|
||||
val (proto, nameResolver) = readProto(stream)
|
||||
val (proto, nameResolver, version) = readProto(stream)
|
||||
|
||||
scopes.add(DeserializedPackageMemberScope(
|
||||
this, proto.`package`, nameResolver, containerSource = null, components = components, classNames = { emptyList() }
|
||||
this, proto.`package`, nameResolver, version, containerSource = null, components = components,
|
||||
classNames = { emptyList() }
|
||||
))
|
||||
}
|
||||
|
||||
@@ -112,6 +113,7 @@ class MetadataPackageFragment(
|
||||
scopes.add(object : DeserializedPackageMemberScope(
|
||||
this, ProtoBuf.Package.getDefaultInstance(),
|
||||
NameResolverImpl(ProtoBuf.StringTable.getDefaultInstance(), ProtoBuf.QualifiedNameTable.getDefaultInstance()),
|
||||
BuiltInsBinaryVersion.INSTANCE, // Exact version does not matter here
|
||||
containerSource = null, components = components, classNames = { emptyList() }
|
||||
) {
|
||||
override fun hasClass(name: Name): Boolean = hasTopLevelClass(name)
|
||||
@@ -129,7 +131,7 @@ class MetadataPackageFragment(
|
||||
return true
|
||||
}
|
||||
|
||||
private fun readProto(stream: InputStream): Pair<ProtoBuf.PackageFragment, NameResolverImpl> {
|
||||
private fun readProto(stream: InputStream): Triple<ProtoBuf.PackageFragment, NameResolverImpl, BuiltInsBinaryVersion> {
|
||||
val version = BuiltInsBinaryVersion.readFrom(stream)
|
||||
|
||||
if (!version.isCompatible()) {
|
||||
@@ -143,7 +145,7 @@ class MetadataPackageFragment(
|
||||
|
||||
val message = ProtoBuf.PackageFragment.parseFrom(stream, BuiltInSerializerProtocol.extensionRegistry)
|
||||
val nameResolver = NameResolverImpl(message.strings, message.qualifiedNames)
|
||||
return Pair(message, nameResolver)
|
||||
return Triple(message, nameResolver, version)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
+3
-1
@@ -18,12 +18,14 @@ package org.jetbrains.kotlin.serialization.deserialization
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
|
||||
import org.jetbrains.kotlin.metadata.deserialization.NameResolver
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
|
||||
class ProtoBasedClassDataFinder(
|
||||
proto: ProtoBuf.PackageFragment,
|
||||
private val nameResolver: NameResolver,
|
||||
private val metadataVersion: BinaryVersion,
|
||||
private val classSource: (ClassId) -> SourceElement = { SourceElement.NO_SOURCE }
|
||||
) : ClassDataFinder {
|
||||
private val classIdToProto =
|
||||
@@ -35,6 +37,6 @@ class ProtoBasedClassDataFinder(
|
||||
|
||||
override fun findClassData(classId: ClassId): ClassData? {
|
||||
val classProto = classIdToProto[classId] ?: return null
|
||||
return ClassData(nameResolver, classProto, classSource(classId))
|
||||
return ClassData(nameResolver, classProto, metadataVersion, classSource(classId))
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -53,7 +53,7 @@ class BuiltInsLoaderImpl : BuiltInsLoader {
|
||||
val packageFragments = packageFqNames.map { fqName ->
|
||||
val resourcePath = BuiltInSerializerProtocol.getBuiltInsFilePath(fqName)
|
||||
val inputStream = loadResource(resourcePath) ?: throw IllegalStateException("Resource not found in classpath: $resourcePath")
|
||||
BuiltInsPackageFragmentImpl(fqName, storageManager, module, inputStream)
|
||||
BuiltInsPackageFragmentImpl.create(fqName, storageManager, module, inputStream)
|
||||
}
|
||||
val provider = PackageFragmentProviderImpl(packageFragments)
|
||||
|
||||
|
||||
+32
-14
@@ -14,22 +14,40 @@ import org.jetbrains.kotlin.serialization.deserialization.DeserializedPackageFra
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import java.io.InputStream
|
||||
|
||||
class BuiltInsPackageFragmentImpl(
|
||||
class BuiltInsPackageFragmentImpl private constructor(
|
||||
fqName: FqName,
|
||||
storageManager: StorageManager,
|
||||
module: ModuleDescriptor,
|
||||
inputStream: InputStream
|
||||
) : BuiltInsPackageFragment, DeserializedPackageFragmentImpl(fqName, storageManager, module, inputStream.use { stream ->
|
||||
val version = BuiltInsBinaryVersion.readFrom(stream)
|
||||
proto: ProtoBuf.PackageFragment,
|
||||
metadataVersion: BuiltInsBinaryVersion
|
||||
) : BuiltInsPackageFragment, DeserializedPackageFragmentImpl(
|
||||
fqName, storageManager, module, proto, metadataVersion, containerSource = null
|
||||
) {
|
||||
companion object {
|
||||
fun create(
|
||||
fqName: FqName,
|
||||
storageManager: StorageManager,
|
||||
module: ModuleDescriptor,
|
||||
inputStream: InputStream
|
||||
): BuiltInsPackageFragmentImpl {
|
||||
lateinit var version: BuiltInsBinaryVersion
|
||||
|
||||
if (!version.isCompatible()) {
|
||||
// TODO: report a proper diagnostic
|
||||
throw UnsupportedOperationException(
|
||||
"Kotlin built-in definition format version is not supported: " +
|
||||
"expected ${BuiltInsBinaryVersion.INSTANCE}, actual $version. " +
|
||||
"Please update Kotlin"
|
||||
)
|
||||
val proto = inputStream.use { stream ->
|
||||
version = BuiltInsBinaryVersion.readFrom(stream)
|
||||
|
||||
if (!version.isCompatible()) {
|
||||
// TODO: report a proper diagnostic
|
||||
throw UnsupportedOperationException(
|
||||
"Kotlin built-in definition format version is not supported: " +
|
||||
"expected ${BuiltInsBinaryVersion.INSTANCE}, actual $version. " +
|
||||
"Please update Kotlin"
|
||||
)
|
||||
}
|
||||
|
||||
ProtoBuf.PackageFragment.parseFrom(stream, BuiltInSerializerProtocol.extensionRegistry)
|
||||
}
|
||||
|
||||
return BuiltInsPackageFragmentImpl(fqName, storageManager, module, proto, version)
|
||||
}
|
||||
}
|
||||
|
||||
ProtoBuf.PackageFragment.parseFrom(stream, BuiltInSerializerProtocol.extensionRegistry)
|
||||
}, containerSource = null)
|
||||
}
|
||||
|
||||
+7
-3
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.descriptors.deserialization.ClassDescriptorFactory
|
||||
import org.jetbrains.kotlin.descriptors.deserialization.PlatformDependentDeclarationFilter
|
||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
|
||||
import org.jetbrains.kotlin.metadata.deserialization.NameResolver
|
||||
import org.jetbrains.kotlin.metadata.deserialization.TypeTable
|
||||
import org.jetbrains.kotlin.metadata.deserialization.VersionRequirementTable
|
||||
@@ -60,10 +61,11 @@ class DeserializationComponents(
|
||||
nameResolver: NameResolver,
|
||||
typeTable: TypeTable,
|
||||
versionRequirementTable: VersionRequirementTable,
|
||||
metadataVersion: BinaryVersion,
|
||||
containerSource: DeserializedContainerSource?
|
||||
): DeserializationContext =
|
||||
DeserializationContext(
|
||||
this, nameResolver, descriptor, typeTable, versionRequirementTable, containerSource,
|
||||
this, nameResolver, descriptor, typeTable, versionRequirementTable, metadataVersion, containerSource,
|
||||
parentTypeDeserializer = null, typeParameters = listOf()
|
||||
)
|
||||
}
|
||||
@@ -75,6 +77,7 @@ class DeserializationContext(
|
||||
val containingDeclaration: DeclarationDescriptor,
|
||||
val typeTable: TypeTable,
|
||||
val versionRequirementTable: VersionRequirementTable,
|
||||
val metadataVersion: BinaryVersion,
|
||||
val containerSource: DeserializedContainerSource?,
|
||||
parentTypeDeserializer: TypeDeserializer?,
|
||||
typeParameters: List<ProtoBuf.TypeParameter>
|
||||
@@ -92,9 +95,10 @@ class DeserializationContext(
|
||||
descriptor: DeclarationDescriptor,
|
||||
typeParameterProtos: List<ProtoBuf.TypeParameter>,
|
||||
nameResolver: NameResolver = this.nameResolver,
|
||||
typeTable: TypeTable = this.typeTable
|
||||
typeTable: TypeTable = this.typeTable,
|
||||
metadataVersion: BinaryVersion = this.metadataVersion
|
||||
): DeserializationContext = DeserializationContext(
|
||||
components, nameResolver, descriptor, typeTable, versionRequirementTable, this.containerSource,
|
||||
components, nameResolver, descriptor, typeTable, versionRequirementTable, metadataVersion, this.containerSource,
|
||||
parentTypeDeserializer = this.typeDeserializer, typeParameters = typeParameterProtos
|
||||
)
|
||||
}
|
||||
|
||||
+2
-1
@@ -33,6 +33,7 @@ class DeserializedClassDescriptor(
|
||||
outerContext: DeserializationContext,
|
||||
val classProto: ProtoBuf.Class,
|
||||
nameResolver: NameResolver,
|
||||
val metadataVersion: BinaryVersion,
|
||||
private val sourceElement: SourceElement
|
||||
) : AbstractClassDescriptor(
|
||||
outerContext.storageManager,
|
||||
@@ -44,7 +45,7 @@ class DeserializedClassDescriptor(
|
||||
private val visibility = ProtoEnumFlags.visibility(Flags.VISIBILITY.get(classProto.flags))
|
||||
private val kind = ProtoEnumFlags.classKind(Flags.CLASS_KIND.get(classProto.flags))
|
||||
|
||||
val c = outerContext.childContext(this, classProto.typeParameterList, nameResolver, TypeTable(classProto.typeTable))
|
||||
val c = outerContext.childContext(this, classProto.typeParameterList, nameResolver, TypeTable(classProto.typeTable), metadataVersion)
|
||||
|
||||
private val staticScope = if (kind == ClassKind.ENUM_CLASS) StaticScopeForKotlinEnum(c.storageManager, this) else MemberScope.Empty
|
||||
private val typeConstructor = DeserializedClassTypeConstructor()
|
||||
|
||||
+3
-1
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.incremental.components.LookupLocation
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.incremental.record
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
|
||||
import org.jetbrains.kotlin.metadata.deserialization.NameResolver
|
||||
import org.jetbrains.kotlin.metadata.deserialization.TypeTable
|
||||
import org.jetbrains.kotlin.metadata.deserialization.VersionRequirementTable
|
||||
@@ -35,13 +36,14 @@ open class DeserializedPackageMemberScope(
|
||||
private val packageDescriptor: PackageFragmentDescriptor,
|
||||
proto: ProtoBuf.Package,
|
||||
nameResolver: NameResolver,
|
||||
metadataVersion: BinaryVersion,
|
||||
containerSource: DeserializedContainerSource?,
|
||||
components: DeserializationComponents,
|
||||
classNames: () -> Collection<Name>
|
||||
) : DeserializedMemberScope(
|
||||
components.createContext(
|
||||
packageDescriptor, nameResolver, TypeTable(proto.typeTable),
|
||||
VersionRequirementTable.create(proto.versionRequirementTable), containerSource
|
||||
VersionRequirementTable.create(proto.versionRequirementTable), metadataVersion, containerSource
|
||||
),
|
||||
proto.functionList, proto.propertyList, proto.typeAliasList, classNames
|
||||
) {
|
||||
|
||||
Reference in New Issue
Block a user