From 721af75f40c504237de52007e85ca8528882c13f Mon Sep 17 00:00:00 2001 From: Leonid Startsev Date: Wed, 8 Nov 2023 12:56:05 +0100 Subject: [PATCH] Provide a separate class for representing metadata version in kotlinx-metadata Separate class allows encapsulating comparison, equality, and structure of version parts. It also makes more sense from API standpoint than plain `IntArray`. --- .../jvm/api/kotlinx-metadata-jvm.api | 62 ++++++---- .../metadata/jvm/JvmMetadataVersion.kt | 116 ++++++++++++++++++ .../metadata/jvm/KotlinClassHeader.java | 2 +- .../metadata/jvm/KotlinClassMetadata.kt | 92 ++++++++------ .../metadata/jvm/KotlinModuleMetadata.kt | 6 +- .../metadata/jvm/internal/JvmReadUtils.kt | 7 -- .../metadata/test/DifferentVersionsTest.kt | 4 +- .../kotlinx/metadata/test/JavaUsageTest.java | 4 +- .../metadata/test/JvmMetadataVersionTest.kt | 36 ++++++ .../metadata/test/MetadataExceptionsTest.kt | 13 +- .../metadata/test/MetadataSmokeTest.kt | 4 +- .../metadata/test/WritersContractTest.kt | 34 +++-- .../metadata/test/testdata/FileFacade.kt | 9 ++ .../test/testdata/MultiFileClassFacade1.kt | 10 ++ .../test/testdata/MultiFileClassFacade2.kt | 10 ++ .../kotlin/jvm/abi/JvmAbiMetadataProcessor.kt | 3 +- 16 files changed, 323 insertions(+), 89 deletions(-) create mode 100644 libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/JvmMetadataVersion.kt create mode 100644 libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/JvmMetadataVersionTest.kt create mode 100644 libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/testdata/FileFacade.kt create mode 100644 libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/testdata/MultiFileClassFacade1.kt create mode 100644 libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/testdata/MultiFileClassFacade2.kt diff --git a/libraries/kotlinx-metadata/jvm/api/kotlinx-metadata-jvm.api b/libraries/kotlinx-metadata/jvm/api/kotlinx-metadata-jvm.api index 80a07efa03e..1bca86cc2a6 100644 --- a/libraries/kotlinx-metadata/jvm/api/kotlinx-metadata-jvm.api +++ b/libraries/kotlinx-metadata/jvm/api/kotlinx-metadata-jvm.api @@ -1310,6 +1310,24 @@ public final class kotlinx/metadata/jvm/JvmMetadataUtil { public static final fun toJvmInternalName (Ljava/lang/String;)Ljava/lang/String; } +public final class kotlinx/metadata/jvm/JvmMetadataVersion : java/lang/Comparable { + public static final field CURRENT Lkotlinx/metadata/jvm/JvmMetadataVersion; + public static final field Companion Lkotlinx/metadata/jvm/JvmMetadataVersion$Companion; + public fun (II)V + public fun (III)V + public synthetic fun compareTo (Ljava/lang/Object;)I + public fun compareTo (Lkotlinx/metadata/jvm/JvmMetadataVersion;)I + public fun equals (Ljava/lang/Object;)Z + public final fun getMajor ()I + public final fun getMinor ()I + public final fun getPatch ()I + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final class kotlinx/metadata/jvm/JvmMetadataVersion$Companion { +} + public final class kotlinx/metadata/jvm/JvmMethodSignature : kotlinx/metadata/jvm/JvmMemberSignature { public fun (Ljava/lang/String;Ljava/lang/String;)V public final fun component1 ()Ljava/lang/String; @@ -1441,12 +1459,12 @@ public abstract class kotlinx/metadata/jvm/KotlinClassMetadata { public static final field MULTI_FILE_CLASS_PART_KIND I public static final field SYNTHETIC_CLASS_KIND I public abstract fun getFlags ()I - public abstract fun getVersion ()[I + public abstract fun getVersion ()Lkotlinx/metadata/jvm/JvmMetadataVersion; public static final fun read (Lkotlin/Metadata;)Lkotlinx/metadata/jvm/KotlinClassMetadata; public static final fun readLenient (Lkotlin/Metadata;)Lkotlinx/metadata/jvm/KotlinClassMetadata; public static final fun readStrict (Lkotlin/Metadata;)Lkotlinx/metadata/jvm/KotlinClassMetadata; public abstract fun setFlags (I)V - public abstract fun setVersion ([I)V + public abstract fun setVersion (Lkotlinx/metadata/jvm/JvmMetadataVersion;)V public abstract fun write ()Lkotlin/Metadata; public static final fun writeClass (Lkotlinx/metadata/KmClass;)Lkotlin/Metadata; public static final fun writeClass (Lkotlinx/metadata/KmClass;[I)Lkotlin/Metadata; @@ -1469,14 +1487,14 @@ public abstract class kotlinx/metadata/jvm/KotlinClassMetadata { } public final class kotlinx/metadata/jvm/KotlinClassMetadata$Class : kotlinx/metadata/jvm/KotlinClassMetadata { - public fun (Lkotlinx/metadata/KmClass;[II)V + public fun (Lkotlinx/metadata/KmClass;Lkotlinx/metadata/jvm/JvmMetadataVersion;I)V public final fun accept (Lkotlinx/metadata/KmClassVisitor;)V public fun getFlags ()I public final fun getKmClass ()Lkotlinx/metadata/KmClass; - public fun getVersion ()[I + public fun getVersion ()Lkotlinx/metadata/jvm/JvmMetadataVersion; public fun setFlags (I)V public final fun setKmClass (Lkotlinx/metadata/KmClass;)V - public fun setVersion ([I)V + public fun setVersion (Lkotlinx/metadata/jvm/JvmMetadataVersion;)V public final fun toKmClass ()Lkotlinx/metadata/KmClass; public fun write ()Lkotlin/Metadata; } @@ -1521,14 +1539,14 @@ public final class kotlinx/metadata/jvm/KotlinClassMetadata$Companion { } public final class kotlinx/metadata/jvm/KotlinClassMetadata$FileFacade : kotlinx/metadata/jvm/KotlinClassMetadata { - public fun (Lkotlinx/metadata/KmPackage;[II)V + public fun (Lkotlinx/metadata/KmPackage;Lkotlinx/metadata/jvm/JvmMetadataVersion;I)V public final fun accept (Lkotlinx/metadata/KmPackageVisitor;)V public fun getFlags ()I public final fun getKmPackage ()Lkotlinx/metadata/KmPackage; - public fun getVersion ()[I + public fun getVersion ()Lkotlinx/metadata/jvm/JvmMetadataVersion; public fun setFlags (I)V public final fun setKmPackage (Lkotlinx/metadata/KmPackage;)V - public fun setVersion ([I)V + public fun setVersion (Lkotlinx/metadata/jvm/JvmMetadataVersion;)V public final fun toKmPackage ()Lkotlinx/metadata/KmPackage; public fun write ()Lkotlin/Metadata; } @@ -1542,13 +1560,13 @@ public final class kotlinx/metadata/jvm/KotlinClassMetadata$FileFacade$Writer : } public final class kotlinx/metadata/jvm/KotlinClassMetadata$MultiFileClassFacade : kotlinx/metadata/jvm/KotlinClassMetadata { - public fun (Ljava/util/List;[II)V + public fun (Ljava/util/List;Lkotlinx/metadata/jvm/JvmMetadataVersion;I)V public fun getFlags ()I public final fun getPartClassNames ()Ljava/util/List; - public fun getVersion ()[I + public fun getVersion ()Lkotlinx/metadata/jvm/JvmMetadataVersion; public fun setFlags (I)V public final fun setPartClassNames (Ljava/util/List;)V - public fun setVersion ([I)V + public fun setVersion (Lkotlinx/metadata/jvm/JvmMetadataVersion;)V public fun write ()Lkotlin/Metadata; } @@ -1561,16 +1579,16 @@ public final class kotlinx/metadata/jvm/KotlinClassMetadata$MultiFileClassFacade } public final class kotlinx/metadata/jvm/KotlinClassMetadata$MultiFileClassPart : kotlinx/metadata/jvm/KotlinClassMetadata { - public fun (Lkotlinx/metadata/KmPackage;Ljava/lang/String;[II)V + public fun (Lkotlinx/metadata/KmPackage;Ljava/lang/String;Lkotlinx/metadata/jvm/JvmMetadataVersion;I)V public final fun accept (Lkotlinx/metadata/KmPackageVisitor;)V public final fun getFacadeClassName ()Ljava/lang/String; public fun getFlags ()I public final fun getKmPackage ()Lkotlinx/metadata/KmPackage; - public fun getVersion ()[I + public fun getVersion ()Lkotlinx/metadata/jvm/JvmMetadataVersion; public final fun setFacadeClassName (Ljava/lang/String;)V public fun setFlags (I)V public final fun setKmPackage (Lkotlinx/metadata/KmPackage;)V - public fun setVersion ([I)V + public fun setVersion (Lkotlinx/metadata/jvm/JvmMetadataVersion;)V public final fun toKmPackage ()Lkotlinx/metadata/KmPackage; public fun write ()Lkotlin/Metadata; } @@ -1584,15 +1602,15 @@ public final class kotlinx/metadata/jvm/KotlinClassMetadata$MultiFileClassPart$W } public final class kotlinx/metadata/jvm/KotlinClassMetadata$SyntheticClass : kotlinx/metadata/jvm/KotlinClassMetadata { - public fun (Lkotlinx/metadata/KmLambda;[II)V + public fun (Lkotlinx/metadata/KmLambda;Lkotlinx/metadata/jvm/JvmMetadataVersion;I)V public final fun accept (Lkotlinx/metadata/KmLambdaVisitor;)V public fun getFlags ()I public final fun getKmLambda ()Lkotlinx/metadata/KmLambda; - public fun getVersion ()[I + public fun getVersion ()Lkotlinx/metadata/jvm/JvmMetadataVersion; public final fun isLambda ()Z public fun setFlags (I)V public final fun setKmLambda (Lkotlinx/metadata/KmLambda;)V - public fun setVersion ([I)V + public fun setVersion (Lkotlinx/metadata/jvm/JvmMetadataVersion;)V public final fun toKmLambda ()Lkotlinx/metadata/KmLambda; public fun write ()Lkotlin/Metadata; } @@ -1609,9 +1627,9 @@ public final class kotlinx/metadata/jvm/KotlinClassMetadata$Unknown : kotlinx/me public static final field Companion Lkotlinx/metadata/jvm/KotlinClassMetadata$Unknown$Companion; public static final field INSTANCE Lkotlinx/metadata/jvm/KotlinClassMetadata$Unknown; public fun getFlags ()I - public fun getVersion ()[I + public fun getVersion ()Lkotlinx/metadata/jvm/JvmMetadataVersion; public fun setFlags (I)V - public fun setVersion ([I)V + public fun setVersion (Lkotlinx/metadata/jvm/JvmMetadataVersion;)V public fun write ()Lkotlin/Metadata; } @@ -1626,14 +1644,14 @@ public final class kotlinx/metadata/jvm/KotlinModuleMetadata { public static final fun read ([B)Lkotlinx/metadata/jvm/KotlinModuleMetadata; public final fun toKmModule ()Lkotlinx/metadata/jvm/KmModule; public static final fun write (Lkotlinx/metadata/jvm/KmModule;)[B - public static final fun write (Lkotlinx/metadata/jvm/KmModule;[I)[B + public static final fun write (Lkotlinx/metadata/jvm/KmModule;Lkotlinx/metadata/jvm/JvmMetadataVersion;)[B } public final class kotlinx/metadata/jvm/KotlinModuleMetadata$Companion { public final fun read ([B)Lkotlinx/metadata/jvm/KotlinModuleMetadata; public final fun write (Lkotlinx/metadata/jvm/KmModule;)[B - public final fun write (Lkotlinx/metadata/jvm/KmModule;[I)[B - public static synthetic fun write$default (Lkotlinx/metadata/jvm/KotlinModuleMetadata$Companion;Lkotlinx/metadata/jvm/KmModule;[IILjava/lang/Object;)[B + public final fun write (Lkotlinx/metadata/jvm/KmModule;Lkotlinx/metadata/jvm/JvmMetadataVersion;)[B + public static synthetic fun write$default (Lkotlinx/metadata/jvm/KotlinModuleMetadata$Companion;Lkotlinx/metadata/jvm/KmModule;Lkotlinx/metadata/jvm/JvmMetadataVersion;ILjava/lang/Object;)[B } public final class kotlinx/metadata/jvm/KotlinModuleMetadata$Writer { diff --git a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/JvmMetadataVersion.kt b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/JvmMetadataVersion.kt new file mode 100644 index 00000000000..aa6428187bb --- /dev/null +++ b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/JvmMetadataVersion.kt @@ -0,0 +1,116 @@ +/* + * 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 kotlinx.metadata.jvm + +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion as CompilerMetadataVersion + +/** + * Version of the metadata inside JVM classfile. + * + * Starting from Kotlin 1.4, the metadata version is equal to the language version. + * It consists of major and minor versions. Patch version usually does not affect the metadata format, but it is present for completeness because + * compiler writes its full version to the `@Metadata` annotation; therefore, the patch version is accounted for in comparisons and equality. + * All components (major, minor, and patch) should be non-negative. + * + * While the metadata version is currently equal to the language version, this may be changed in the future, including adding or removing components. + * Therefore, it is recommended to rely on the [compareTo] and [equals] method instead of accessing components directly. + * + * Note that the metadata version is 1.1 for Kotlin compilers from 1.0 until 1.4, and is 1.0 or less for pre-1.0 compilers. + * Metadata with versions less than 1.1 is considered incompatible and cannot be read or written. + * + * The library can read in strict mode only compatible versions of metadata. For definition of compatible version, see documentation for [CURRENT] property. + * + * @property major Major component of version + * @property minor Minor component of version + * @property patch Patch component of version + */ +public class JvmMetadataVersion(public val major: Int, public val minor: Int, public val patch: Int) : Comparable { + + /** + * Creates a new [JvmMetadataVersion] instance with specified [major] and [minor] versions and a patch version equal to 0. + */ + public constructor(major: Int, minor: Int) : this(major, minor, 0) + + internal constructor(intArray: IntArray) : this(intArray[0], intArray[1], intArray[2]) + + @JvmName("toIntArray") + internal fun toIntArray(): IntArray = intArrayOf(major, minor, patch) + + init { + require(major >= 0) { "Major version should be not less than 0" } + require(minor >= 0) { "Minor version should be not less than 0" } + require(patch >= 0) { "Patch version should be not less than 0" } + } + + /** + * Compares this JvmMetadataVersion object with another JvmMetadataVersion object. + * + * Comparison is based on integer values of version parts with [major] being most significant one, then [minor], and finally [patch]. + * + * @return a negative integer, zero, or a positive integer if this JvmMetadataVersion object is less than, equal to, or greater than [other]. + */ + override fun compareTo(other: JvmMetadataVersion): Int { + val majors = major.compareTo(other.major) + if (majors != 0) return majors + val minors = minor.compareTo(other.minor) + return if (minors != 0) minors else patch.compareTo(other.patch) + } + + /** + * Returns a string representation of the version number. + * The string representation is in the format "major.minor.patch". + */ + override fun toString(): String = "$major.$minor.$patch" + + /** + * Calculates the hash code value for the object based on major, minor, and patch components. + */ + override fun hashCode(): Int { + var result = major + result = 31 * result + minor + result = 31 * result + patch + return result + } + + /** + * Checks if the current JvmMetadataVersion object is equal to another object. + * + * Instances of JvmMetadataVersion are equal if they have the same major, minor, and patch components. + */ + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as JvmMetadataVersion + + if (major != other.major) return false + if (minor != other.minor) return false + if (patch != other.patch) return false + + return true + } + + /** + * Companion object to hold pre-defined JvmMetadataVersion instances. + */ + public companion object { + /** + * The latest stable metadata version supported by this version of the library. + * The library can read in strict mode Kotlin metadata produced by Kotlin compilers from 1.0 up to and including this version + 1 minor. + * + * In other words, the metadata version is supported if it is greater or equal than 1.1, and less or equal than [CURRENT] + 1 minor version. + * Note that the metadata version is 1.1 for Kotlin from 1.0 until 1.4, and is equal to the language version starting from Kotlin 1.4. + * + * For example, if the latest supported stable Kotlin version is 1.7.0, kotlinx-metadata-jvm can read in strict mode binaries produced by Kotlin compilers from 1.0 + * to 1.8.* inclusively. In this case, this property will have the value `1.7.0`. + * + * @see Metadata.metadataVersion + * @see KotlinClassMetadata.readStrict + */ + @JvmField + public val CURRENT: JvmMetadataVersion = JvmMetadataVersion(CompilerMetadataVersion.INSTANCE.toArray()) + } +} diff --git a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/KotlinClassHeader.java b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/KotlinClassHeader.java index b2a5fdbb392..113ecb24e81 100644 --- a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/KotlinClassHeader.java +++ b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/KotlinClassHeader.java @@ -178,7 +178,7 @@ public final class KotlinClassHeader implements Metadata { public static final int MULTI_FILE_CLASS_PART_KIND = 5; /** - * Use {@link KotlinClassMetadata#COMPATIBLE_METADATA_VERSION} instead + * Use {@link kotlinx.metadata.jvm.JvmMetadataVersion#CURRENT} instead */ @Deprecated public static final int[] COMPATIBLE_METADATA_VERSION = Arrays.copyOf(JvmMetadataVersion.INSTANCE.toArray(), 3); diff --git a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/KotlinClassMetadata.kt b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/KotlinClassMetadata.kt index e4972485525..32d9a258637 100644 --- a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/KotlinClassMetadata.kt +++ b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/KotlinClassMetadata.kt @@ -4,6 +4,7 @@ */ @file:Suppress( "DEPRECATION_ERROR", // Deprecated .accept implementation + "DEPRECATION", // COMPATIBLE_METADATA_VERSION as default param "UNUSED_PARAMETER" // For deprecated Writer.write ) @@ -12,9 +13,8 @@ package kotlinx.metadata.jvm import kotlinx.metadata.* import kotlinx.metadata.internal.* import kotlinx.metadata.jvm.internal.* -import kotlinx.metadata.jvm.internal.JvmReadUtils.checkMetadataVersion import kotlinx.metadata.jvm.internal.JvmReadUtils.readMetadataImpl -import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion as CompilerMetadataVersion import org.jetbrains.kotlin.metadata.jvm.serialization.JvmStringTable import java.util.* @@ -61,16 +61,16 @@ public sealed class KotlinClassMetadata { * Encodes and writes this metadata to the new instance of [Metadata]. * * This method encodes all available data, including [version] and [flags]. - * Due to technical limitations, it is not possible to write the metadata when the specified version is less (lexicographically) than `[1, 4]` + * Due to technical limitations, it is not possible to write the metadata when the specified version is less than 1.4. * - * @throws IllegalArgumentException if metadata is malformed or [version] of this instance is less than 1.4 and cannot be written. + * @throws IllegalArgumentException if metadata is malformed or metadata was read in lenient mode and cannot be written back or [version] of this instance is less than 1.4. */ public abstract fun write(): Metadata /** * Version of this metadata. */ - public abstract var version: IntArray + public abstract var version: JvmMetadataVersion /** * Additional classfile-level flags of this metadata. See [Metadata.extraInt] for possible values. @@ -92,13 +92,13 @@ public sealed class KotlinClassMetadata { * Returns the same (mutable) [KmClass] instance every time. */ public var kmClass: KmClass, - public override var version: IntArray, + public override var version: JvmMetadataVersion, public override var flags: Int, ) : KotlinClassMetadata() { internal constructor(annotationData: Metadata, lenient: Boolean) : this( JvmReadUtils.readKmClass(annotationData), - annotationData.metadataVersion, + JvmMetadataVersion(annotationData.metadataVersion), annotationData.extraInt ) { isAllowedToWrite = !lenient @@ -111,7 +111,7 @@ public sealed class KotlinClassMetadata { val writer = ClassWriter(JvmStringTable()) writer.writeClass(kmClass) val (d1, d2) = writeProtoBufData(writer.t.build(), writer.c) - Metadata(CLASS_KIND, version, d1, d2, extraInt = flags) + Metadata(CLASS_KIND, version.toIntArray(), d1, d2, extraInt = flags) } } @@ -181,7 +181,7 @@ public sealed class KotlinClassMetadata { /** * Version of this metadata. */ - public override var version: IntArray, + public override var version: JvmMetadataVersion, /** * Additional classfile-level flags of this metadata. See [Metadata.extraInt] for possible values. */ @@ -190,7 +190,7 @@ public sealed class KotlinClassMetadata { internal constructor(annotationData: Metadata, lenient: Boolean) : this( JvmReadUtils.readKmPackage(annotationData), - annotationData.metadataVersion, + JvmMetadataVersion(annotationData.metadataVersion), annotationData.extraInt ) { isAllowedToWrite = !lenient @@ -203,7 +203,7 @@ public sealed class KotlinClassMetadata { val writer = PackageWriter(JvmStringTable()) writer.writePackage(kmPackage) val (d1, d2) = writeProtoBufData(writer.t.build(), writer.c) - Metadata(FILE_FACADE_KIND, version, d1, d2, extraInt = flags) + Metadata(FILE_FACADE_KIND, version.toIntArray(), d1, d2, extraInt = flags) } } @@ -269,7 +269,7 @@ public sealed class KotlinClassMetadata { /** * Version of this metadata. */ - public override var version: IntArray, + public override var version: JvmMetadataVersion, /** * Additional classfile-level flags of this metadata. See [Metadata.extraInt] for possible values. */ @@ -278,7 +278,7 @@ public sealed class KotlinClassMetadata { internal constructor(annotationData: Metadata, lenient: Boolean) : this( JvmReadUtils.readKmLambda(annotationData), - annotationData.metadataVersion, + JvmMetadataVersion(annotationData.metadataVersion), annotationData.extraInt ) { isAllowedToWrite = !lenient @@ -294,9 +294,9 @@ public sealed class KotlinClassMetadata { val (d1, d2) = if (proto != null) writeProtoBufData(proto, writer.c) else Pair(emptyArray(), emptyArray()) - Metadata(SYNTHETIC_CLASS_KIND, version, d1, d2, extraInt = flags) + Metadata(SYNTHETIC_CLASS_KIND, version.toIntArray(), d1, d2, extraInt = flags) } else { - Metadata(SYNTHETIC_CLASS_KIND, version, emptyArray(), emptyArray(), extraInt = flags) + Metadata(SYNTHETIC_CLASS_KIND, version.toIntArray(), emptyArray(), emptyArray(), extraInt = flags) } } @@ -407,7 +407,7 @@ public sealed class KotlinClassMetadata { /** * Version of this metadata. */ - public override var version: IntArray, + public override var version: JvmMetadataVersion, /** * Additional classfile-level flags of this metadata. See [Metadata.extraInt] for possible values. */ @@ -416,7 +416,7 @@ public sealed class KotlinClassMetadata { internal constructor(annotationData: Metadata, lenient: Boolean) : this( annotationData.data1.asList(), - annotationData.metadataVersion, + JvmMetadataVersion(annotationData.metadataVersion), annotationData.extraInt ) { isAllowedToWrite = !lenient @@ -426,7 +426,7 @@ public sealed class KotlinClassMetadata { throwIfNotWriteable(isAllowedToWrite, "multi-file class facade") checkMetadataVersion(version) return Metadata( - MULTI_FILE_CLASS_FACADE_KIND, version, + MULTI_FILE_CLASS_FACADE_KIND, version.toIntArray(), partClassNames.toTypedArray(), extraInt = flags ) } @@ -488,7 +488,7 @@ public sealed class KotlinClassMetadata { /** * Version of this metadata. */ - public override var version: IntArray, + public override var version: JvmMetadataVersion, /** * Additional classfile-level flags of this metadata. See [Metadata.extraInt] for possible values. */ @@ -498,7 +498,7 @@ public sealed class KotlinClassMetadata { internal constructor(annotationData: Metadata, lenient: Boolean) : this( JvmReadUtils.readKmPackage(annotationData), annotationData.extraString, - annotationData.metadataVersion, + JvmMetadataVersion(annotationData.metadataVersion), annotationData.extraInt ) { isAllowedToWrite = !lenient @@ -512,7 +512,7 @@ public sealed class KotlinClassMetadata { writer.writePackage(kmPackage) val (d1, d2) = writeProtoBufData(writer.t.build(), writer.c) Metadata( - MULTI_FILE_CLASS_PART_KIND, version, d1, d2, facadeClassName, extraInt = flags + MULTI_FILE_CLASS_PART_KIND, version.toIntArray(), d1, d2, facadeClassName, extraInt = flags ) } } @@ -577,7 +577,7 @@ public sealed class KotlinClassMetadata { /** * Version of this metadata. */ - public override var version: IntArray = original.metadataVersion + public override var version: JvmMetadataVersion = JvmMetadataVersion(original.metadataVersion) /** * Additional classfile-level flags of this metadata. See [Metadata.extraInt] for possible values. @@ -586,14 +586,23 @@ public sealed class KotlinClassMetadata { override fun write(): Metadata { throwIfNotWriteable(!lenient, "unknown kind") - return Metadata(original.kind, version, original.data1, original.data2, original.extraString, original.packageName, flags) + checkMetadataVersion(version) + return Metadata( + original.kind, + version.toIntArray(), + original.data1, + original.data2, + original.extraString, + original.packageName, + flags + ) } @PublishedApi @Deprecated("This declaration is intended for binary compatibility only", level = DeprecationLevel.HIDDEN) internal companion object { @JvmField // For binary compatibility with previous `data object Unknown` - public val INSTANCE: Unknown = Unknown(Metadata(kind = 99), true) + public val INSTANCE: Unknown = Unknown(Metadata(kind = 99, metadataVersion = JvmMetadataVersion.CURRENT.toIntArray()), true) } } @@ -635,7 +644,7 @@ public sealed class KotlinClassMetadata { kmClass: KmClass, metadataVersion: IntArray = COMPATIBLE_METADATA_VERSION, extraInt: Int = 0, - ): Metadata = Class(kmClass, metadataVersion, extraInt).write() + ): Metadata = Class(kmClass, JvmMetadataVersion(metadataVersion), extraInt).write() /** @@ -655,7 +664,7 @@ public sealed class KotlinClassMetadata { kmPackage: KmPackage, metadataVersion: IntArray = COMPATIBLE_METADATA_VERSION, extraInt: Int = 0, - ): Metadata = FileFacade(kmPackage, metadataVersion, extraInt).write() + ): Metadata = FileFacade(kmPackage, JvmMetadataVersion(metadataVersion), extraInt).write() /** * Writes [kmLambda] as the synthetic class metadata. @@ -674,7 +683,7 @@ public sealed class KotlinClassMetadata { kmLambda: KmLambda, metadataVersion: IntArray = COMPATIBLE_METADATA_VERSION, extraInt: Int = 0, - ): Metadata = SyntheticClass(kmLambda, metadataVersion, extraInt).write() + ): Metadata = SyntheticClass(kmLambda, JvmMetadataVersion(metadataVersion), extraInt).write() /** * Writes synthetic class metadata. @@ -692,7 +701,7 @@ public sealed class KotlinClassMetadata { public fun writeSyntheticClass( metadataVersion: IntArray = COMPATIBLE_METADATA_VERSION, extraInt: Int = 0, - ): Metadata = SyntheticClass(null, metadataVersion, extraInt).write() + ): Metadata = SyntheticClass(null, JvmMetadataVersion(metadataVersion), extraInt).write() /** * Writes metadata of the multi-file class facade. @@ -714,7 +723,7 @@ public sealed class KotlinClassMetadata { public fun writeMultiFileClassFacade( partClassNames: List, metadataVersion: IntArray = COMPATIBLE_METADATA_VERSION, extraInt: Int = 0, - ): Metadata = MultiFileClassFacade(partClassNames, metadataVersion, extraInt).write() + ): Metadata = MultiFileClassFacade(partClassNames, JvmMetadataVersion(metadataVersion), extraInt).write() /** * Writes the metadata of the multi-file class part. @@ -738,7 +747,7 @@ public sealed class KotlinClassMetadata { facadeClassName: String, metadataVersion: IntArray = COMPATIBLE_METADATA_VERSION, extraInt: Int = 0, - ): Metadata = MultiFileClassPart(kmPackage, facadeClassName, metadataVersion, extraInt).write() + ): Metadata = MultiFileClassPart(kmPackage, facadeClassName, JvmMetadataVersion(metadataVersion), extraInt).write() /** * Reads and parses the given annotation data of a Kotlin JVM class file and returns the correct type of [KotlinClassMetadata] encoded by @@ -771,14 +780,14 @@ public sealed class KotlinClassMetadata { * [annotationData] may be obtained reflectively, constructed manually or with helper [kotlinx.metadata.jvm.Metadata] function, * or equivalent [KotlinClassHeader] can be used. * - * This method can read only supported metadata versions (see [COMPATIBLE_METADATA_VERSION] for definition). + * This method can read only supported metadata versions (see [JvmMetadataVersion.CURRENT] for definition). * It will throw an exception if the metadata version is greater than what kotlinx-metadata-jvm understands. * It is suitable when your tooling cannot tolerate reading potentially incomplete or incorrect information due to version differences. * It is also the only method that allows metadata transformation and `KotlinClassMetadata.write` subsequent calls. * - * @throws IllegalArgumentException if the metadata version is unsupported + * @throws IllegalArgumentException if the metadata version is unsupported or if metadata is corrupted * - * @see COMPATIBLE_METADATA_VERSION + * @see JvmMetadataVersion.CURRENT */ @JvmStatic public fun readStrict(annotationData: Metadata): KotlinClassMetadata = readMetadataImpl(annotationData, lenient = false) @@ -791,13 +800,13 @@ public sealed class KotlinClassMetadata { * or equivalent [KotlinClassHeader] can be used. * * This method makes best effort to read unsupported metadata versions. - * If metadata version is greater than [COMPATIBLE_METADATA_VERSION] + 1, this method may ignore parts of the metadata it does not understand but it will not throw an exception. + * If metadata version is greater than [JvmMetadataVersion.CURRENT] + 1, this method may ignore parts of the metadata it does not understand but it will not throw an exception. * Because obtained metadata can be incomplete, its [KotlinClassMetadata.write] method will throw an exception. * This method still cannot read metadata produced by pre-1.0 compilers. * * @throws IllegalArgumentException if the metadata version is that of Kotlin 1.0 or metadata format has been changed in an unpredictable way and reading of incompatible metadata is not possible * - * @see COMPATIBLE_METADATA_VERSION + * @see JvmMetadataVersion.CURRENT */ @JvmStatic public fun readLenient(annotationData: Metadata): KotlinClassMetadata = readMetadataImpl(annotationData, lenient = true) @@ -807,6 +816,13 @@ public sealed class KotlinClassMetadata { throw IllegalArgumentException("This $name cannot be written because it represents metadata read in lenient mode") } + internal fun checkMetadataVersion(version: JvmMetadataVersion) { + require(version.major >= 1 && (version.major > 1 || version.minor >= 4)) { + "This version of kotlinx-metadata-jvm doesn't support writing Kotlin metadata of version earlier than 1.4. " + + "Please change the version from $version to at least [1, 4]." + } + } + /** * A class file kind signifying that the corresponding class file contains a declaration of a Kotlin class. * @@ -860,8 +876,10 @@ public sealed class KotlinClassMetadata { * * @see Metadata.metadataVersion */ - @JvmField // TODO: move it somewhere since it is also used in KotlinModuleMetadata? - public val COMPATIBLE_METADATA_VERSION: IntArray = JvmMetadataVersion.INSTANCE.toArray().copyOf() + @JvmField + @Deprecated("Use JvmMetadataVersion.CURRENT instead", ReplaceWith("JvmMetadataVersion.CURRENT"), DeprecationLevel.WARNING) + public val COMPATIBLE_METADATA_VERSION: IntArray = CompilerMetadataVersion.INSTANCE.toArray().copyOf() + } } diff --git a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/KotlinModuleMetadata.kt b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/KotlinModuleMetadata.kt index 6fc9de0e503..3b5dc252a6d 100644 --- a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/KotlinModuleMetadata.kt +++ b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/KotlinModuleMetadata.kt @@ -21,7 +21,7 @@ import kotlinx.metadata.jvm.internal.JvmReadUtils.throwIfNotCompatible import kotlinx.metadata.jvm.internal.wrapIntoMetadataExceptionWhenNeeded import kotlinx.metadata.jvm.internal.wrapWriteIntoIAE import org.jetbrains.kotlin.metadata.jvm.JvmModuleProtoBuf -import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion as CompilerMetadataVersion import org.jetbrains.kotlin.metadata.jvm.deserialization.ModuleMapping import org.jetbrains.kotlin.metadata.jvm.deserialization.PackageParts import org.jetbrains.kotlin.metadata.jvm.deserialization.serializeToByteArray @@ -181,9 +181,9 @@ public class KotlinModuleMetadata private constructor( @UnstableMetadataApi @JvmStatic @JvmOverloads - public fun write(kmModule: KmModule, metadataVersion: IntArray = COMPATIBLE_METADATA_VERSION): ByteArray = wrapWriteIntoIAE { + public fun write(kmModule: KmModule, metadataVersion: JvmMetadataVersion = JvmMetadataVersion.CURRENT): ByteArray = wrapWriteIntoIAE { val w = Writer().also { it.writeModule(kmModule) } - return w.b.build().serializeToByteArray(JvmMetadataVersion(*metadataVersion), 0) + return w.b.build().serializeToByteArray(CompilerMetadataVersion(metadataVersion.toIntArray(), false), 0) } private fun dataFromBytes(bytes: ByteArray): ModuleMapping { diff --git a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/internal/JvmReadUtils.kt b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/internal/JvmReadUtils.kt index b8b9ad61b30..763292c8dbb 100644 --- a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/internal/JvmReadUtils.kt +++ b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/internal/JvmReadUtils.kt @@ -71,11 +71,4 @@ internal object JvmReadUtils { throw IllegalArgumentException("Provided Metadata instance has version $jvmMetadataVersion, $postfix") } } - - internal fun checkMetadataVersion(version: IntArray) { - require(version.size >= 2 && version[0] >= 1 && (version[0] > 1 || version[1] >= 4)) { - "This version of kotlinx-metadata-jvm doesn't support writing Kotlin metadata of version earlier than 1.4. " + - "Please change the version from ${version.toList()} to at least [1, 4]." - } - } } diff --git a/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/DifferentVersionsTest.kt b/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/DifferentVersionsTest.kt index 8bd646b6af7..8b8fbc3623c 100644 --- a/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/DifferentVersionsTest.kt +++ b/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/DifferentVersionsTest.kt @@ -29,7 +29,7 @@ class DifferentVersionsTest { @Test fun readsCurrentVersion() { - assertContentEquals(KotlinClassMetadata.COMPATIBLE_METADATA_VERSION, metadata.metadataVersion) + assertContentEquals(JvmMetadataVersion.INSTANCE.toArray(), metadata.metadataVersion) assertIs(KotlinClassMetadata.readStrict(metadata)) assertIs(KotlinClassMetadata.readLenient(metadata)) } @@ -51,7 +51,7 @@ class DifferentVersionsTest { @Test fun readsArbitraryFutureVersion() { - val md = metadata.changeVersion(intArrayOf(2, 5, 0)) + val md = metadata.changeVersion(intArrayOf(7, 5, 0)) assertFailsWith { KotlinClassMetadata.readStrict(md) } assertIs(KotlinClassMetadata.readLenient(md)) } diff --git a/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/JavaUsageTest.java b/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/JavaUsageTest.java index f7cb72b1fd6..7fbfb7fa34b 100644 --- a/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/JavaUsageTest.java +++ b/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/JavaUsageTest.java @@ -7,6 +7,7 @@ package kotlinx.metadata.test; import kotlin.Metadata; import kotlinx.metadata.KmClass; +import kotlinx.metadata.jvm.JvmMetadataVersion; import kotlinx.metadata.jvm.KotlinClassHeader; import kotlinx.metadata.jvm.KotlinClassMetadata; import org.junit.Test; @@ -32,7 +33,8 @@ public class JavaUsageTest { Metadata m = MetadataSmokeTest.class.getAnnotation(Metadata.class); KotlinClassMetadata clazz1 = ((KotlinClassMetadata) Objects.requireNonNull(KotlinClassMetadata.readStrict(m))); Metadata written = clazz1.write(); - assertArrayEquals(written.mv(), KotlinClassMetadata.COMPATIBLE_METADATA_VERSION); + //noinspection KotlinInternalInJava + assertArrayEquals(written.mv(), JvmMetadataVersion.CURRENT.toIntArray()); assertEquals(50, written.xi()); } } diff --git a/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/JvmMetadataVersionTest.kt b/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/JvmMetadataVersionTest.kt new file mode 100644 index 00000000000..ef7a6a16f0f --- /dev/null +++ b/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/JvmMetadataVersionTest.kt @@ -0,0 +1,36 @@ +/* + * 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 kotlinx.metadata.test + +import kotlinx.metadata.jvm.JvmMetadataVersion +import kotlin.test.* + +class JvmMetadataVersionTest { + + fun mv(major: Int, minor: Int, patch: Int) = JvmMetadataVersion(major, minor, patch) + + @Test + fun testEquality() { + assertEquals(mv(1, 2, 3), mv(1, 2, 3)) + assertNotEquals(mv(0, 2, 3), mv(1, 2, 3)) + assertNotEquals(mv(1, 0, 3), mv(1, 2, 3)) + assertNotEquals(mv(1, 2, 3), mv(1, 2, 0)) + } + + @Test + fun testComparison() { + assertTrue(mv(1, 2, 3) > mv(1, 2, 0)) + assertTrue(mv(1, 0, 3) < mv(1, 2, 0)) + assertTrue(mv(1, 2, 3) < mv(2, 0, 0)) + } + + @Test + fun testConstructor() { + assertFailsWith { mv(-1, 0, 0) } + assertFailsWith { mv(0, -1, 0) } + assertFailsWith { mv(0, 0, -1) } + } +} diff --git a/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/MetadataExceptionsTest.kt b/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/MetadataExceptionsTest.kt index 99b6eb816ea..cb6ced0854d 100644 --- a/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/MetadataExceptionsTest.kt +++ b/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/MetadataExceptionsTest.kt @@ -6,9 +6,10 @@ package kotlinx.metadata.test import kotlinx.metadata.KmClass +import kotlinx.metadata.jvm.JvmMetadataVersion import kotlinx.metadata.jvm.KotlinClassMetadata import kotlinx.metadata.jvm.Metadata -import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion as CompilerMetadataVersion import org.jetbrains.kotlin.protobuf.InvalidProtocolBufferException import org.junit.Test import kotlin.test.* @@ -18,7 +19,7 @@ class MetadataExceptionsTest { fun testReadMalformedInput() { val malformedInput = "abcdefdkdgwaydgyuawdfg543awyudfuiawty" // random string guaranteed by dropping ball on a keyboard val malformedMetadata = - Metadata(KotlinClassMetadata.CLASS_KIND, KotlinClassMetadata.COMPATIBLE_METADATA_VERSION, arrayOf(malformedInput)) + Metadata(KotlinClassMetadata.CLASS_KIND, CompilerMetadataVersion.INSTANCE.toArray(), arrayOf(malformedInput)) val e = assertFailsWith { (KotlinClassMetadata.readStrict(malformedMetadata) as KotlinClassMetadata.Class) } @@ -29,7 +30,7 @@ class MetadataExceptionsTest { fun testWriteMalformedClass() { val kmClass = KmClass() // kotlin.UninitializedPropertyAccessException: lateinit property name has not been initialized val e = assertFailsWith { - KotlinClassMetadata.Class(kmClass, KotlinClassMetadata.COMPATIBLE_METADATA_VERSION, 0).write() + KotlinClassMetadata.Class(kmClass, JvmMetadataVersion.CURRENT, 0).write() } assertIs(e.cause) } @@ -49,10 +50,10 @@ class MetadataExceptionsTest { @Test fun testReadNewerVersion() { - val versionPlus2 = JvmMetadataVersion.INSTANCE.next().next() + val versionPlus2 = CompilerMetadataVersion.INSTANCE.next().next() doTestVersion( versionPlus2.toArray(), - "version $versionPlus2, while maximum supported version is ${JvmMetadataVersion.INSTANCE_NEXT}" + "version $versionPlus2, while maximum supported version is ${CompilerMetadataVersion.INSTANCE_NEXT}" ) } @@ -60,7 +61,7 @@ class MetadataExceptionsTest { fun testInvalidVersion() { doTestVersion(intArrayOf(), "instance does not have metadataVersion in it and therefore is malformed and cannot be read") doTestVersion( - JvmMetadataVersion.INVALID_VERSION.toArray(), + CompilerMetadataVersion.INVALID_VERSION.toArray(), "instance does not have metadataVersion in it and therefore is malformed and cannot be read" ) } diff --git a/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/MetadataSmokeTest.kt b/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/MetadataSmokeTest.kt index 769dc090f23..27f40e77b9d 100644 --- a/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/MetadataSmokeTest.kt +++ b/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/MetadataSmokeTest.kt @@ -63,7 +63,7 @@ class MetadataSmokeTest { } } - val annotationData = KotlinClassMetadata.Class(klass, KotlinClassMetadata.COMPATIBLE_METADATA_VERSION, 0).write() + val annotationData = KotlinClassMetadata.Class(klass, JvmMetadataVersion.CURRENT, 0).write() // Then, produce the bytecode of a .class file with ASM @@ -179,7 +179,7 @@ class MetadataSmokeTest { @OptIn(UnstableMetadataApi::class) fun metadataVersionEarlierThan1_4() { val dummy = MetadataSmokeTest::class.java.readMetadataAsKmClass() - val mv = intArrayOf(1, 3) + val mv = JvmMetadataVersion(1, 3) assertFailsWith { KotlinClassMetadata.Class(dummy, mv, 0).write() } // We can't write empty KmClass() assertFailsWith { KotlinClassMetadata.FileFacade(KmPackage(), mv, 0).write() } assertFailsWith { KotlinClassMetadata.MultiFileClassFacade(listOf("A"), mv, 0).write() } diff --git a/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/WritersContractTest.kt b/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/WritersContractTest.kt index 1c8010aef17..a85e7f7ab1c 100644 --- a/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/WritersContractTest.kt +++ b/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/WritersContractTest.kt @@ -5,27 +5,47 @@ package kotlinx.metadata.test +import kotlinx.metadata.jvm.JvmMetadataVersion import kotlinx.metadata.jvm.KotlinClassMetadata -import org.junit.Ignore +import kotlinx.metadata.jvm.Metadata import org.junit.Test +import kotlin.test.assertContentEquals +import kotlin.test.assertEquals import kotlin.test.assertFailsWith class WritersContractTest { val classMd = WritersContractTest::class.java.getMetadata() val l: () -> Unit = {} val lambdaMd = l::class.java.getMetadata() -// val fileFacadeMd = TODO + val fileFacadeMd = Class.forName("kotlinx.metadata.test.testdata.FileFacade").getMetadata() + val multiFileFacadeMd = Class.forName("kotlinx.metadata.test.testdata.MultiFileClassFacade").getMetadata() + val multiFilePartMd = Class.forName("kotlinx.metadata.test.testdata.MultiFileClassFacade__MultiFileClassFacade1Kt").getMetadata() + + val unknown = Metadata(99, metadataVersion = intArrayOf(2, 0, 0), extraString = "blabla") + + val everyType = listOf(classMd, fileFacadeMd, lambdaMd, multiFileFacadeMd, multiFilePartMd, unknown) @Test - fun lenientDataCantBeWritten() { - val lenientClass = KotlinClassMetadata.readLenient(classMd) + fun lenientDataCantBeWritten() = everyType.forEach { md -> + val lenientClass = KotlinClassMetadata.readLenient(md) assertFailsWith { lenientClass.write() } } @Test - fun oldVersionCantBeWritten() { - val writeableClass = KotlinClassMetadata.readStrict(classMd) as KotlinClassMetadata.Class - writeableClass.version = intArrayOf(1, 2, 0) + fun oldVersionCantBeWritten() = everyType.forEach { md -> + val writeableClass = KotlinClassMetadata.readStrict(md) + writeableClass.version = JvmMetadataVersion(1, 2) assertFailsWith { writeableClass.write() } } + + @Test + fun transformIsIdentical() = everyType.forEach { before -> + val after = KotlinClassMetadata.transform(before) { } + // note: data1 and data2 will always differ + assertEquals(before.kind, after.kind) + assertContentEquals(before.metadataVersion, after.metadataVersion) + assertEquals(before.extraInt, after.extraInt) + assertEquals(before.extraString, after.extraString) + assertEquals(before.packageName, after.packageName) + } } diff --git a/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/testdata/FileFacade.kt b/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/testdata/FileFacade.kt new file mode 100644 index 00000000000..94471c7aba9 --- /dev/null +++ b/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/testdata/FileFacade.kt @@ -0,0 +1,9 @@ +/* + * 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. + */ + +@file:JvmName("FileFacade") +package kotlinx.metadata.test.testdata + +fun insideFileFacade() {} diff --git a/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/testdata/MultiFileClassFacade1.kt b/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/testdata/MultiFileClassFacade1.kt new file mode 100644 index 00000000000..4ad70f552c2 --- /dev/null +++ b/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/testdata/MultiFileClassFacade1.kt @@ -0,0 +1,10 @@ +/* + * 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. + */ + +@file:JvmMultifileClass +@file:JvmName("MultiFileClassFacade") +package kotlinx.metadata.test.testdata + +fun partOne() {} diff --git a/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/testdata/MultiFileClassFacade2.kt b/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/testdata/MultiFileClassFacade2.kt new file mode 100644 index 00000000000..2f0258f9855 --- /dev/null +++ b/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/testdata/MultiFileClassFacade2.kt @@ -0,0 +1,10 @@ +/* + * 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. + */ + +@file:JvmMultifileClass +@file:JvmName("MultiFileClassFacade") +package kotlinx.metadata.test.testdata + +fun partTwo() {} diff --git a/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/JvmAbiMetadataProcessor.kt b/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/JvmAbiMetadataProcessor.kt index bb20a19744a..2086350df2a 100644 --- a/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/JvmAbiMetadataProcessor.kt +++ b/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/JvmAbiMetadataProcessor.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.jvm.abi import kotlinx.metadata.* +import kotlinx.metadata.jvm.JvmMetadataVersion import kotlinx.metadata.jvm.KotlinClassMetadata import kotlinx.metadata.jvm.Metadata import kotlinx.metadata.jvm.localDelegatedProperties @@ -46,7 +47,7 @@ fun abiMetadataProcessor(annotationVisitor: AnnotationVisitor): AnnotationVisito // TODO: maybe jvm-abi-gen should throw this exception by default, and not only in tests. if (System.getProperty("idea.is.unit.test").toBoolean()) { val actual = "${metadataVersion[0]}.${metadataVersion[1]}" - val expected = KotlinClassMetadata.COMPATIBLE_METADATA_VERSION.let { "${it[0]}.${it[1]}" } + val expected = JvmMetadataVersion.CURRENT.toString() throw AssertionError( "jvm-abi-gen can't process class file with the new metadata version because the version of kotlinx-metadata-jvm " + "it depends on is too old.\n" +