jvm-abi-gen: Add test to check the declaration order in interface jars

This commit is contained in:
Steven Schäfer
2021-12-01 13:40:02 +01:00
committed by Alexander Udalov
parent b8625cd233
commit 05695761ec
14 changed files with 69 additions and 18 deletions
@@ -12,7 +12,8 @@ class BytecodeListingTextCollectingVisitor(
val filter: Filter, val filter: Filter,
val withSignatures: Boolean, val withSignatures: Boolean,
api: Int = Opcodes.API_VERSION, api: Int = Opcodes.API_VERSION,
val withAnnotations: Boolean = true val withAnnotations: Boolean = true,
val sortDeclarations: Boolean = true,
) : ClassVisitor(api) { ) : ClassVisitor(api) {
companion object { companion object {
@JvmOverloads @JvmOverloads
@@ -150,7 +151,9 @@ class BytecodeListingTextCollectingVisitor(
append(className) append(className)
if (declarationsInsideClass.isNotEmpty()) { if (declarationsInsideClass.isNotEmpty()) {
append(" {\n") append(" {\n")
for (declaration in declarationsInsideClass.sortedBy { it.text }) { val orderedDeclarations =
if (sortDeclarations) declarationsInsideClass.sortedBy { it.text } else declarationsInsideClass
for (declaration in orderedDeclarations) {
append(" ").append(declaration.annotations.joinToString("")).append(declaration.text).append("\n") append(" ").append(declaration.annotations.joinToString("")).append(declaration.text).append("\n")
} }
append("}") append("}")
@@ -21,7 +21,8 @@ abstract class AbstractJvmAbiContentTest : BaseJvmAbiTest() {
val visitor = BytecodeListingTextCollectingVisitor( val visitor = BytecodeListingTextCollectingVisitor(
filter = BytecodeListingTextCollectingVisitor.Filter.EMPTY, filter = BytecodeListingTextCollectingVisitor.Filter.EMPTY,
withSignatures = false, withSignatures = false,
api = Opcodes.API_VERSION api = Opcodes.API_VERSION,
sortDeclarations = false, // Declaration order matters for the ABI
) )
reader.accept(visitor, 0) reader.accept(visitor, 0)
classToBytecode[classFile] = visitor.text classToBytecode[classFile] = visitor.text
@@ -55,6 +55,11 @@ public class IrJvmAbiContentTestGenerated extends AbstractIrJvmAbiContentTest {
runTest("plugins/jvm-abi-gen/testData/content/class/"); runTest("plugins/jvm-abi-gen/testData/content/class/");
} }
@TestMetadata("kt50005")
public void testKt50005() throws Exception {
runTest("plugins/jvm-abi-gen/testData/content/kt50005/");
}
@TestMetadata("whenMapping") @TestMetadata("whenMapping")
public void testWhenMapping() throws Exception { public void testWhenMapping() throws Exception {
runTest("plugins/jvm-abi-gen/testData/content/whenMapping/"); runTest("plugins/jvm-abi-gen/testData/content/whenMapping/");
@@ -55,6 +55,11 @@ public class JvmAbiContentTestGenerated extends AbstractJvmAbiContentTest {
runTest("plugins/jvm-abi-gen/testData/content/class/"); runTest("plugins/jvm-abi-gen/testData/content/class/");
} }
@TestMetadata("kt50005")
public void testKt50005() throws Exception {
runTest("plugins/jvm-abi-gen/testData/content/kt50005/");
}
@TestMetadata("whenMapping") @TestMetadata("whenMapping")
public void testWhenMapping() throws Exception { public void testWhenMapping() throws Exception {
runTest("plugins/jvm-abi-gen/testData/content/whenMapping/"); runTest("plugins/jvm-abi-gen/testData/content/whenMapping/");
@@ -55,6 +55,11 @@ public class LegacyJvmAbiContentTestGenerated extends AbstractLegacyJvmAbiConten
runTest("plugins/jvm-abi-gen/testData/content/class/"); runTest("plugins/jvm-abi-gen/testData/content/class/");
} }
@TestMetadata("kt50005")
public void testKt50005() throws Exception {
runTest("plugins/jvm-abi-gen/testData/content/kt50005/");
}
@TestMetadata("whenMapping") @TestMetadata("whenMapping")
public void testWhenMapping() throws Exception { public void testWhenMapping() throws Exception {
runTest("plugins/jvm-abi-gen/testData/content/whenMapping/"); runTest("plugins/jvm-abi-gen/testData/content/whenMapping/");
@@ -9,10 +9,10 @@ public synthetic final class test/Test$annotationImpl$test_A$0 {
enclosing class test/Test enclosing class test/Test
inner (anonymous) class test/Test$annotationImpl$test_A$0 inner (anonymous) class test/Test$annotationImpl$test_A$0
public method <init>(): void public method <init>(): void
public synthetic final method annotationType(): java.lang.Class
public final method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean public final method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean
public final method hashCode(): int public final method hashCode(): int
public final @org.jetbrains.annotations.NotNull method toString(): java.lang.String public final @org.jetbrains.annotations.NotNull method toString(): java.lang.String
public synthetic final method annotationType(): java.lang.Class
} }
@kotlin.Metadata @kotlin.Metadata
public final class test/Test { public final class test/Test {
@@ -0,0 +1,2 @@
// IGNORE_BACKEND_LEGACY: JVM
// IGNORE_BACKEND: JVM
@@ -3,8 +3,8 @@ public final enum class test/E {
// source: 'test.kt' // source: 'test.kt'
public final enum static field A: test.E public final enum static field A: test.E
public final enum static field B: test.E public final enum static field B: test.E
public static method valueOf(p0: java.lang.String): test.E
public static method values(): test.E[] public static method values(): test.E[]
public static method valueOf(p0: java.lang.String): test.E
} }
@kotlin.Metadata @kotlin.Metadata
public final class test/Test { public final class test/Test {
@@ -0,0 +1,2 @@
// IGNORE_BACKEND_LEGACY: JVM
// IGNORE_BACKEND: JVM
+10 -10
View File
@@ -1,43 +1,43 @@
@kotlin.Metadata @kotlin.Metadata
public final class test/BaseClass$Companion { public final class test/BaseClass$Companion {
// source: 'classes.kt' // source: 'classes.kt'
public synthetic method <init>(p0: kotlin.jvm.internal.DefaultConstructorMarker): void
public final inner class test/BaseClass$Companion public final inner class test/BaseClass$Companion
public synthetic method <init>(p0: kotlin.jvm.internal.DefaultConstructorMarker): void
} }
@kotlin.Metadata @kotlin.Metadata
public class test/BaseClass { public class test/BaseClass {
// source: 'classes.kt' // source: 'classes.kt'
public final inner class test/BaseClass$Companion
public final static @org.jetbrains.annotations.NotNull field Companion: test.BaseClass$Companion public final static @org.jetbrains.annotations.NotNull field Companion: test.BaseClass$Companion
public final static field basePublicConst: int public final static field basePublicConst: int
public method <init>(): void public method <init>(): void
public final method baseClassInternalFun$main(): int public method getBaseClassPublicVal(): int
protected final method baseClassProtectedFun(): int
public method baseClassPublicFun(): int public method baseClassPublicFun(): int
public final method getBaseClassInternalVal$main(): int public final method getBaseClassInternalVal$main(): int
public final method baseClassInternalFun$main(): int
protected final method getBaseClassProtectedVal(): int protected final method getBaseClassProtectedVal(): int
public method getBaseClassPublicVal(): int protected final method baseClassProtectedFun(): int
public final inner class test/BaseClass$Companion
} }
@kotlin.Metadata @kotlin.Metadata
public final class test/Class$NestedInnerClass$NestedNestedInnerClass { public final class test/Class$NestedInnerClass$NestedNestedInnerClass {
// source: 'classes.kt' // source: 'classes.kt'
public method <init>(): void
private final inner class test/Class$NestedInnerClass
public final inner class test/Class$NestedInnerClass$NestedNestedInnerClass public final inner class test/Class$NestedInnerClass$NestedNestedInnerClass
private final inner class test/Class$NestedInnerClass
public method <init>(): void
} }
@kotlin.Metadata @kotlin.Metadata
final class test/Class$NestedInnerClass { final class test/Class$NestedInnerClass {
// source: 'classes.kt' // source: 'classes.kt'
public method <init>(): void
private final inner class test/Class$NestedInnerClass
public final inner class test/Class$NestedInnerClass$NestedNestedInnerClass public final inner class test/Class$NestedInnerClass$NestedNestedInnerClass
private final inner class test/Class$NestedInnerClass
public method <init>(): void
} }
@kotlin.Metadata @kotlin.Metadata
public final class test/Class { public final class test/Class {
// source: 'classes.kt' // source: 'classes.kt'
private final inner class test/Class$NestedInnerClass
public method <init>(): void public method <init>(): void
public final method classPublicMethod(): void public final method classPublicMethod(): void
private final inner class test/Class$NestedInnerClass
} }
@kotlin.Metadata @kotlin.Metadata
public interface test/Interface { public interface test/Interface {
@@ -0,0 +1,2 @@
// IGNORE_BACKEND_LEGACY: JVM
// IGNORE_BACKEND: JVM
@@ -0,0 +1,12 @@
@kotlin.Metadata
public final class test/A {
// source: 'test.kt'
public final @kotlin.jvm.JvmField field b: int
public field a: java.lang.String
public method <init>(): void
public final @org.jetbrains.annotations.NotNull method getA(): java.lang.String
public final method setA(@org.jetbrains.annotations.NotNull p0: java.lang.String): void
public final method g(): void
public final method f(): void
public final method h(): void
}
+14
View File
@@ -0,0 +1,14 @@
package test
// The order of fields and methods is visible to annotation processors
// and thus part of the public ABI of a library.
class A {
@JvmField
val b: Int = 0
lateinit var a: String
fun g() {}
fun f() {}
fun h() {}
}
@@ -3,20 +3,20 @@ public final enum class test/E {
// source: 'test.kt' // source: 'test.kt'
public final enum static field A: test.E public final enum static field A: test.E
public final enum static field B: test.E public final enum static field B: test.E
public static method valueOf(p0: java.lang.String): test.E
public static method values(): test.E[] public static method values(): test.E[]
public static method valueOf(p0: java.lang.String): test.E
} }
@kotlin.Metadata @kotlin.Metadata
public synthetic final class test/Test$WhenMappings { public synthetic final class test/Test$WhenMappings {
// source: 'test.kt' // source: 'test.kt'
public synthetic inner class test/Test$WhenMappings
public synthetic final static field $EnumSwitchMapping$0: int[] public synthetic final static field $EnumSwitchMapping$0: int[]
static method <clinit>(): void static method <clinit>(): void
public synthetic inner class test/Test$WhenMappings
} }
@kotlin.Metadata @kotlin.Metadata
public final class test/Test { public final class test/Test {
// source: 'test.kt' // source: 'test.kt'
public synthetic inner class test/Test$WhenMappings
public method <init>(): void public method <init>(): void
public final @org.jetbrains.annotations.NotNull method visibleWhenMapping(@org.jetbrains.annotations.NotNull p0: test.E): java.lang.String public final @org.jetbrains.annotations.NotNull method visibleWhenMapping(@org.jetbrains.annotations.NotNull p0: test.E): java.lang.String
public synthetic inner class test/Test$WhenMappings
} }