Skip to content

Commit 198103e

Browse files
authored
Support diffing bytecode versions for classes (#473)
``` OLD: old.jar NEW: new.jar JAR │ old │ new │ diff ───────┼─────────┼─────────┼──────── class │ 1.2 KiB │ 1.4 KiB │ +201 B other │ 72 B │ 72 B │ 0 B ───────┼─────────┼─────────┼──────── total │ 1.3 KiB │ 1.5 KiB │ +201 B CLASSES │ old │ new │ diff ─────────┼─────┼─────┼─────────── classes │ 1 │ 1 │ 0 (+0 -0) methods │ 4 │ 4 │ 0 (+1 -1) fields │ 1 │ 1 │ 0 (+0 -0) ================= ==== JAR ==== ================= size │ diff │ path ─────────┼────────┼──────────────────────────── 1.4 KiB │ +201 B │ ∆ org/example/MainKt.class ─────────┼────────┼──────────────────────────── 1.4 KiB │ +201 B │ (total) ===================== ==== CLASSES ==== ===================== BYTECODE VERSIONS: old │ new │ diff ─────┼─────┼─────────── 1 │ 1 │ 0 (+1 -1) + org.example.MainKt: 65 - org.example.MainKt: 69 METHODS: old │ new │ diff ─────┼─────┼─────────── 4 │ 4 │ 0 (+1 -1) + kotlin.jvm.internal.Intrinsics checkNotNullParameter(Object, String) - org.example.MainKt main() ```
1 parent 93310bb commit 198103e

File tree

4 files changed

+32
-4
lines changed

4 files changed

+32
-4
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
**Added**
77
- Add `--summary-only` flag.
8+
- Support diffing bytecode versions for classes.
89

910
**Changed**
1011
- Replace `com.jakewharton.diffuse.io.Size` with `me.saket.bytesize.ByteSize` in the APIs.

formats/api/formats.api

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,8 +225,9 @@ public abstract interface class com/jakewharton/diffuse/format/BinaryFormat {
225225

226226
public final class com/jakewharton/diffuse/format/Class {
227227
public static final field Companion Lcom/jakewharton/diffuse/format/Class$Companion;
228-
public synthetic fun <init> (Ljava/lang/String;Ljava/util/List;Ljava/util/List;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
228+
public synthetic fun <init> (Ljava/lang/String;ILjava/util/List;Ljava/util/List;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
229229
public fun equals (Ljava/lang/Object;)Z
230+
public final fun getBytecodeVersion ()I
230231
public final fun getDeclaredMembers ()Ljava/util/List;
231232
public final fun getDescriptor-BeHrSHk ()Ljava/lang/String;
232233
public final fun getReferencedMembers ()Ljava/util/List;

formats/src/main/kotlin/com/jakewharton/diffuse/format/Class.kt

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,19 @@ import org.objectweb.asm.Opcodes
1212
class Class
1313
private constructor(
1414
val descriptor: TypeDescriptor,
15+
val bytecodeVersion: Int,
1516
val declaredMembers: List<Member>,
1617
val referencedMembers: List<Member>,
1718
) {
1819
override fun toString() = descriptor.toString()
1920

20-
override fun hashCode() = Objects.hash(descriptor, declaredMembers, referencedMembers)
21+
override fun hashCode() =
22+
Objects.hash(descriptor, bytecodeVersion, declaredMembers, referencedMembers)
2123

2224
override fun equals(other: Any?) =
2325
other is Class &&
2426
descriptor == other.descriptor &&
27+
bytecodeVersion == other.bytecodeVersion &&
2528
declaredMembers == other.declaredMembers &&
2629
referencedMembers == other.referencedMembers
2730

@@ -36,15 +39,33 @@ private constructor(
3639
val declaredVisitor = DeclaredMembersVisitor(type, referencedVisitor)
3740
reader.accept(declaredVisitor, 0)
3841

39-
return Class(type, declaredVisitor.members.sorted(), referencedVisitor.members.sorted())
42+
return Class(
43+
type,
44+
declaredVisitor.version,
45+
declaredVisitor.members.sorted(),
46+
referencedVisitor.members.sorted(),
47+
)
4048
}
4149
}
4250
}
4351

4452
private class DeclaredMembersVisitor(val type: TypeDescriptor, val methodVisitor: MethodVisitor) :
4553
ClassVisitor(Opcodes.ASM9) {
54+
var version: Int = 0
4655
val members = mutableListOf<Member>()
4756

57+
override fun visit(
58+
version: Int,
59+
access: Int,
60+
name: String,
61+
signature: String?,
62+
superName: String?,
63+
interfaces: Array<out String>?,
64+
) {
65+
this.version = version
66+
super.visit(version, access, name, signature, superName, interfaces)
67+
}
68+
4869
override fun visitMethod(
4970
access: Int,
5071
name: String,

reports/src/main/kotlin/com/jakewharton/diffuse/diff/JarsDiff.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ internal class JarsDiff(
1818
val newMapping: ApiMapping,
1919
) {
2020
val classes = componentDiff(oldJars, newJars) { it.classes.map(Class::descriptor) }
21+
val bytecodeVersions =
22+
componentDiff(oldJars, newJars) { jar ->
23+
jar.classes.map { "${it.descriptor}: ${it.bytecodeVersion}" }
24+
}
2125
val methods = componentDiff(oldJars, newJars) { it.members.filterIsInstance<Method>() }
2226
val declaredMethods =
2327
componentDiff(oldJars, newJars) { it.declaredMembers.filterIsInstance<Method>() }
@@ -29,7 +33,7 @@ internal class JarsDiff(
2933
val referencedFields =
3034
componentDiff(oldJars, newJars) { it.referencedMembers.filterIsInstance<Field>() }
3135

32-
val changed = methods.changed || fields.changed
36+
val changed = bytecodeVersions.changed || methods.changed || fields.changed
3337
}
3438

3539
internal fun JarsDiff.toSummaryTable(name: String) =
@@ -72,6 +76,7 @@ internal fun JarsDiff.toSummaryTable(name: String) =
7276
internal fun JarsDiff.toDetailReport() = buildString {
7377
// TODO appendComponentDiff("STRINGS", strings)?
7478
appendComponentDiff("CLASSES", classes)
79+
appendComponentDiff("BYTECODE VERSIONS", bytecodeVersions)
7580
appendComponentDiff("METHODS", methods)
7681
appendComponentDiff("FIELDS", fields)
7782
}

0 commit comments

Comments
 (0)