Deserialization/class reading: pass chosen JvmMetadataVersion whenever possible
This commit is contained in:
+5
-1
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.storage.getValue
|
||||
import org.jetbrains.kotlin.utils.jvmMetadataVersionOrDefault
|
||||
|
||||
class LazyJavaPackageFragment(
|
||||
outerContext: LazyJavaResolverContext,
|
||||
@@ -39,10 +40,13 @@ class LazyJavaPackageFragment(
|
||||
) : PackageFragmentDescriptorImpl(outerContext.module, jPackage.fqName) {
|
||||
private val c = outerContext.childForClassOrPackage(this)
|
||||
|
||||
private val jvmMetadataVersion =
|
||||
outerContext.components.deserializedDescriptorResolver.components.configuration.jvmMetadataVersionOrDefault()
|
||||
|
||||
internal val binaryClasses by c.storageManager.createLazyValue {
|
||||
c.components.packagePartProvider.findPackageParts(fqName.asString()).mapNotNull { partName ->
|
||||
val classId = ClassId.topLevel(JvmClassName.byInternalName(partName).fqNameForTopLevelClassMaybeWithDollars)
|
||||
c.components.kotlinClassFinder.findKotlinClass(classId)?.let { partName to it }
|
||||
c.components.kotlinClassFinder.findKotlinClass(classId, jvmMetadataVersion)?.let { partName to it }
|
||||
}.toMap()
|
||||
}
|
||||
|
||||
|
||||
+10
-4
@@ -30,12 +30,14 @@ import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass
|
||||
import org.jetbrains.kotlin.load.kotlin.findKotlinClass
|
||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.kotlin.storage.NullableLazyValue
|
||||
import org.jetbrains.kotlin.utils.alwaysTrue
|
||||
import org.jetbrains.kotlin.utils.jvmMetadataVersionOrDefault
|
||||
import java.util.*
|
||||
|
||||
class LazyJavaPackageScope(
|
||||
@@ -49,6 +51,10 @@ class LazyJavaPackageScope(
|
||||
c.components.finder.knownClassNamesInPackage(ownerDescriptor.fqName)
|
||||
}
|
||||
|
||||
private val jvmMetadataVersion: JvmMetadataVersion
|
||||
get() = c.components.deserializedDescriptorResolver.components.configuration.jvmMetadataVersionOrDefault()
|
||||
|
||||
|
||||
private val classes =
|
||||
c.storageManager.createMemoizedFunctionWithNullableValues<FindClassRequest, ClassDescriptor> classByRequest@{ request ->
|
||||
val requestClassId = ClassId(ownerDescriptor.fqName, request.name)
|
||||
@@ -56,9 +62,9 @@ class LazyJavaPackageScope(
|
||||
val kotlinClassOrClassFileContent =
|
||||
// These branches should be semantically equal, but the first one could be faster
|
||||
if (request.javaClass != null)
|
||||
c.components.kotlinClassFinder.findKotlinClassOrContent(request.javaClass)
|
||||
c.components.kotlinClassFinder.findKotlinClassOrContent(request.javaClass, jvmMetadataVersion)
|
||||
else
|
||||
c.components.kotlinClassFinder.findKotlinClassOrContent(requestClassId)
|
||||
c.components.kotlinClassFinder.findKotlinClassOrContent(requestClassId, jvmMetadataVersion)
|
||||
|
||||
val kotlinBinaryClass = kotlinClassOrClassFileContent?.toKotlinJvmBinaryClass()
|
||||
|
||||
@@ -84,8 +90,8 @@ class LazyJavaPackageScope(
|
||||
"Couldn't find kotlin binary class for light class created by kotlin binary file\n" +
|
||||
"JavaClass: $javaClass\n" +
|
||||
"ClassId: $requestClassId\n" +
|
||||
"findKotlinClass(JavaClass) = ${c.components.kotlinClassFinder.findKotlinClass(javaClass)}\n" +
|
||||
"findKotlinClass(ClassId) = ${c.components.kotlinClassFinder.findKotlinClass(requestClassId)}\n"
|
||||
"findKotlinClass(JavaClass) = ${c.components.kotlinClassFinder.findKotlinClass(javaClass, jvmMetadataVersion)}\n" +
|
||||
"findKotlinClass(ClassId) = ${c.components.kotlinClassFinder.findKotlinClass(requestClassId, jvmMetadataVersion)}\n"
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+18
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.load.java.components.DescriptorResolverUtils
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass.AnnotationArrayArgumentVisitor
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.deserialization.NameResolver
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
@@ -33,6 +34,8 @@ class BinaryClassAnnotationAndConstantLoaderImpl(
|
||||
) {
|
||||
private val annotationDeserializer = AnnotationDeserializer(module, notFoundClasses)
|
||||
|
||||
override var jvmMetadataVersion: JvmMetadataVersion = JvmMetadataVersion.INSTANCE
|
||||
|
||||
override fun loadTypeAnnotation(proto: ProtoBuf.Annotation, nameResolver: NameResolver): AnnotationDescriptor =
|
||||
annotationDeserializer.deserializeAnnotation(proto, nameResolver)
|
||||
|
||||
@@ -224,3 +227,18 @@ class BinaryClassAnnotationAndConstantLoaderImpl(
|
||||
return module.findNonGenericClassAcrossDependencies(classId, notFoundClasses)
|
||||
}
|
||||
}
|
||||
|
||||
// Note: this function is needed because we cannot pass JvmMetadataVersion
|
||||
// directly to the BinaryClassAnnotationAndConstantLoaderImpl constructor.
|
||||
// This constructor is used by dependency injection.
|
||||
fun createBinaryClassAnnotationAndConstantLoader(
|
||||
module: ModuleDescriptor,
|
||||
notFoundClasses: NotFoundClasses,
|
||||
storageManager: StorageManager,
|
||||
kotlinClassFinder: KotlinClassFinder,
|
||||
jvmMetadataVersion: JvmMetadataVersion
|
||||
): BinaryClassAnnotationAndConstantLoaderImpl = BinaryClassAnnotationAndConstantLoaderImpl(
|
||||
module, notFoundClasses, storageManager, kotlinClassFinder
|
||||
).apply {
|
||||
this.jvmMetadataVersion = jvmMetadataVersion
|
||||
}
|
||||
|
||||
+6
-4
@@ -40,6 +40,7 @@ import org.jetbrains.kotlin.load.java.sources.JavaSourceElementFactory
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
|
||||
import org.jetbrains.kotlin.load.java.typeEnhancement.JavaTypeEnhancement
|
||||
import org.jetbrains.kotlin.load.java.typeEnhancement.SignatureEnhancement
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -122,7 +123,7 @@ class DeserializationComponentsForJava(
|
||||
val deserializationComponentsForJava =
|
||||
makeDeserializationComponentsForJava(
|
||||
module, storageManager, notFoundClasses, lazyJavaPackageFragmentProvider,
|
||||
kotlinClassFinder, deserializedDescriptorResolver, errorReporter
|
||||
kotlinClassFinder, deserializedDescriptorResolver, errorReporter, JvmMetadataVersion.INSTANCE
|
||||
)
|
||||
|
||||
deserializedDescriptorResolver.setComponents(deserializationComponentsForJava)
|
||||
@@ -183,11 +184,12 @@ fun makeDeserializationComponentsForJava(
|
||||
lazyJavaPackageFragmentProvider: LazyJavaPackageFragmentProvider,
|
||||
reflectKotlinClassFinder: KotlinClassFinder,
|
||||
deserializedDescriptorResolver: DeserializedDescriptorResolver,
|
||||
errorReporter: ErrorReporter
|
||||
errorReporter: ErrorReporter,
|
||||
jvmMetadataVersion: JvmMetadataVersion
|
||||
): DeserializationComponentsForJava {
|
||||
val javaClassDataFinder = JavaClassDataFinder(reflectKotlinClassFinder, deserializedDescriptorResolver)
|
||||
val binaryClassAnnotationAndConstantLoader = BinaryClassAnnotationAndConstantLoaderImpl(
|
||||
module, notFoundClasses, storageManager, reflectKotlinClassFinder
|
||||
val binaryClassAnnotationAndConstantLoader = createBinaryClassAnnotationAndConstantLoader(
|
||||
module, notFoundClasses, storageManager, reflectKotlinClassFinder, jvmMetadataVersion
|
||||
)
|
||||
return DeserializationComponentsForJava(
|
||||
storageManager, module, DeserializationConfiguration.Default, javaClassDataFinder,
|
||||
|
||||
+8
-3
@@ -28,11 +28,14 @@ import org.jetbrains.kotlin.serialization.deserialization.DeserializationCompone
|
||||
import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerAbiStability
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope
|
||||
import org.jetbrains.kotlin.utils.jvmMetadataVersionOrDefault
|
||||
import javax.inject.Inject
|
||||
|
||||
class DeserializedDescriptorResolver {
|
||||
lateinit var components: DeserializationComponents
|
||||
|
||||
private val ownMetadataVersion: JvmMetadataVersion get() = components.configuration.jvmMetadataVersionOrDefault()
|
||||
|
||||
// component dependency cycle
|
||||
@Inject
|
||||
fun setComponents(components: DeserializationComponentsForJava) {
|
||||
@@ -80,8 +83,10 @@ class DeserializedDescriptorResolver {
|
||||
|
||||
private val KotlinJvmBinaryClass.incompatibility: IncompatibleVersionErrorData<JvmMetadataVersion>?
|
||||
get() {
|
||||
if (skipMetadataVersionCheck || classHeader.metadataVersion.isCompatible()) return null
|
||||
return IncompatibleVersionErrorData(classHeader.metadataVersion, JvmMetadataVersion.INSTANCE, location, classId)
|
||||
if (skipMetadataVersionCheck || classHeader.metadataVersion.isCompatible(ownMetadataVersion)) return null
|
||||
return IncompatibleVersionErrorData(
|
||||
classHeader.metadataVersion, maxOf(ownMetadataVersion.prev(), JvmMetadataVersion.INSTANCE), location, classId
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -120,7 +125,7 @@ class DeserializedDescriptorResolver {
|
||||
throw IllegalStateException("Could not read data from ${klass.location}", e)
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
if (skipMetadataVersionCheck || klass.classHeader.metadataVersion.isCompatible()) {
|
||||
if (skipMetadataVersionCheck || klass.classHeader.metadataVersion.isCompatible(ownMetadataVersion)) {
|
||||
throw e
|
||||
}
|
||||
|
||||
|
||||
@@ -19,13 +19,16 @@ package org.jetbrains.kotlin.load.kotlin
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ClassData
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ClassDataFinder
|
||||
import org.jetbrains.kotlin.utils.jvmMetadataVersionOrDefault
|
||||
|
||||
class JavaClassDataFinder(
|
||||
internal val kotlinClassFinder: KotlinClassFinder,
|
||||
private val deserializedDescriptorResolver: DeserializedDescriptorResolver
|
||||
) : ClassDataFinder {
|
||||
override fun findClassData(classId: ClassId): ClassData? {
|
||||
val kotlinClass = kotlinClassFinder.findKotlinClass(classId) ?: return null
|
||||
val kotlinClass = kotlinClassFinder.findKotlinClass(
|
||||
classId, deserializedDescriptorResolver.components.configuration.jvmMetadataVersionOrDefault()
|
||||
) ?: return null
|
||||
assert(kotlinClass.classId == classId) {
|
||||
"Class with incorrect id found: expected $classId, actual ${kotlinClass.classId}"
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.load.kotlin
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.ModuleMapping
|
||||
import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration
|
||||
import org.jetbrains.kotlin.utils.jvmMetadataVersionOrDefault
|
||||
|
||||
fun ModuleMapping.Companion.loadModuleMapping(
|
||||
bytes: ByteArray?,
|
||||
@@ -20,5 +21,6 @@ fun ModuleMapping.Companion.loadModuleMapping(
|
||||
debugName,
|
||||
configuration.skipMetadataVersionCheck,
|
||||
configuration.isJvmPackageNameSupported,
|
||||
configuration.jvmMetadataVersionOrDefault(),
|
||||
reportIncompatibleVersionError
|
||||
)
|
||||
|
||||
+7
-2
@@ -61,7 +61,12 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
||||
private String[] serializedIrFields = null;
|
||||
|
||||
@Nullable
|
||||
public KotlinClassHeader createHeader() {
|
||||
public KotlinClassHeader createHeaderWithDefaultMetadataVersion() {
|
||||
return createHeader(JvmMetadataVersion.INSTANCE);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public KotlinClassHeader createHeader(JvmMetadataVersion metadataVersionFromLanguageVersion) {
|
||||
if (headerKind == null || metadataVersionArray == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -69,7 +74,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
||||
JvmMetadataVersion metadataVersion =
|
||||
new JvmMetadataVersion(metadataVersionArray, (extraInt & JvmAnnotationNames.METADATA_STRICT_VERSION_SEMANTICS_FLAG) != 0);
|
||||
|
||||
if (!metadataVersion.isCompatible()) {
|
||||
if (!metadataVersion.isCompatible(metadataVersionFromLanguageVersion)) {
|
||||
incompatibleData = data;
|
||||
data = null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright 2010-2022 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.utils
|
||||
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion
|
||||
import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration
|
||||
|
||||
fun DeserializationConfiguration.jvmMetadataVersionOrDefault(): JvmMetadataVersion =
|
||||
binaryVersion as? JvmMetadataVersion ?: JvmMetadataVersion.INSTANCE
|
||||
Reference in New Issue
Block a user