diff --git a/formats/src/main/kotlin/com/jakewharton/diffuse/format/Aar.kt b/formats/src/main/kotlin/com/jakewharton/diffuse/format/Aar.kt index c36562ca..1d4d85e7 100644 --- a/formats/src/main/kotlin/com/jakewharton/diffuse/format/Aar.kt +++ b/formats/src/main/kotlin/com/jakewharton/diffuse/format/Aar.kt @@ -8,6 +8,7 @@ import com.jakewharton.diffuse.io.Input class Aar private constructor( override val filename: String?, + val bytecodeVersion: Short?, val files: ArchiveFiles, val manifest: AndroidManifest, val classes: Jar, @@ -30,7 +31,7 @@ class Aar private constructor( val libs = zip.entries .filter { it.path.matches(libsJarRegex) } .map { it.asInput().toJar() } - return Aar(name, files, manifest, classes, libs) + return Aar(name, classes.bytecodeVersion, files, manifest, classes, libs) } } } diff --git a/formats/src/main/kotlin/com/jakewharton/diffuse/format/BinaryFormat.kt b/formats/src/main/kotlin/com/jakewharton/diffuse/format/BinaryFormat.kt index ace3b124..e9d6cbec 100644 --- a/formats/src/main/kotlin/com/jakewharton/diffuse/format/BinaryFormat.kt +++ b/formats/src/main/kotlin/com/jakewharton/diffuse/format/BinaryFormat.kt @@ -1,5 +1,5 @@ package com.jakewharton.diffuse.format -interface BinaryFormat { +sealed interface BinaryFormat { val filename: String? } diff --git a/formats/src/main/kotlin/com/jakewharton/diffuse/format/Class.kt b/formats/src/main/kotlin/com/jakewharton/diffuse/format/Class.kt index 603443d1..e04ac23d 100644 --- a/formats/src/main/kotlin/com/jakewharton/diffuse/format/Class.kt +++ b/formats/src/main/kotlin/com/jakewharton/diffuse/format/Class.kt @@ -10,6 +10,7 @@ import org.objectweb.asm.MethodVisitor import org.objectweb.asm.Opcodes class Class private constructor( + val bytecodeVersion: Short, val descriptor: TypeDescriptor, val declaredMembers: List, val referencedMembers: List, @@ -26,13 +27,14 @@ class Class private constructor( @JvmName("parse") fun Input.toClass(): Class { val reader = ClassReader(toByteArray()) + val bytecodeVersion = reader.readShort(0 + 6) val type = TypeDescriptor("L${reader.className};") val referencedVisitor = ReferencedMembersVisitor() val declaredVisitor = DeclaredMembersVisitor(type, referencedVisitor) reader.accept(declaredVisitor, 0) - return Class(type, declaredVisitor.members.sorted(), referencedVisitor.members.sorted()) + return Class(bytecodeVersion, type, declaredVisitor.members.sorted(), referencedVisitor.members.sorted()) } } } diff --git a/formats/src/main/kotlin/com/jakewharton/diffuse/format/Jar.kt b/formats/src/main/kotlin/com/jakewharton/diffuse/format/Jar.kt index 570689a6..61706498 100644 --- a/formats/src/main/kotlin/com/jakewharton/diffuse/format/Jar.kt +++ b/formats/src/main/kotlin/com/jakewharton/diffuse/format/Jar.kt @@ -7,6 +7,7 @@ import com.jakewharton.diffuse.io.Input class Jar private constructor( override val filename: String?, + val bytecodeVersion: Short?, val files: ArchiveFiles, val classes: List, override val declaredMembers: List, @@ -20,17 +21,27 @@ class Jar private constructor( fun Input.toJar(): Jar { toZip().use { zip -> val files = zip.toArchiveFiles { it.toJarFileType() } + val bcVersions = mutableMapOf() val classes = zip.entries + .asSequence() .filter { it.path.endsWith(".class") } - .map { it.asInput().toClass() } + .map { entry -> + entry.asInput().toClass().also { cls -> + // Count all the byte code versions in a Jar. + bcVersions.merge(cls.bytecodeVersion, 1L, Long::plus) + } + } + .toList() + + val mostBytecodeVersion = bcVersions.maxByOrNull { it.value }?.key val declaredMembers = classes.flatMap { it.declaredMembers } val referencedMembers = classes.flatMapTo(LinkedHashSet()) { it.referencedMembers } // Declared methods are likely to reference other declared members. Ensure all are removed. referencedMembers -= declaredMembers - return Jar(name, files, classes, declaredMembers.sorted(), referencedMembers.sorted()) + return Jar(name, mostBytecodeVersion, files, classes, declaredMembers.sorted(), referencedMembers.sorted()) } } } diff --git a/reports/src/main/kotlin/com/jakewharton/diffuse/report/text/AarDiffTextReport.kt b/reports/src/main/kotlin/com/jakewharton/diffuse/report/text/AarDiffTextReport.kt index 31f02fc2..4d1bf981 100644 --- a/reports/src/main/kotlin/com/jakewharton/diffuse/report/text/AarDiffTextReport.kt +++ b/reports/src/main/kotlin/com/jakewharton/diffuse/report/text/AarDiffTextReport.kt @@ -10,10 +10,16 @@ internal class AarDiffTextReport(private val aarDiff: AarDiff) : Report { override fun write(appendable: Appendable) { appendable.apply { append("OLD: ") - appendLine(aarDiff.oldAar.filename) + append(aarDiff.oldAar.filename) + append(" (bytecodeVersion: ") + append(aarDiff.oldAar.bytecodeVersion.toString()) + appendLine(')') append("NEW: ") - appendLine(aarDiff.newAar.filename) + append(aarDiff.newAar.filename) + append(" (bytecodeVersion: ") + append(aarDiff.newAar.bytecodeVersion.toString()) + appendLine(')') appendLine() appendLine( diff --git a/reports/src/main/kotlin/com/jakewharton/diffuse/report/text/JarDiffTextReport.kt b/reports/src/main/kotlin/com/jakewharton/diffuse/report/text/JarDiffTextReport.kt index 66391f83..895b083b 100644 --- a/reports/src/main/kotlin/com/jakewharton/diffuse/report/text/JarDiffTextReport.kt +++ b/reports/src/main/kotlin/com/jakewharton/diffuse/report/text/JarDiffTextReport.kt @@ -10,11 +10,16 @@ internal class JarDiffTextReport(private val jarDiff: JarDiff) : Report { override fun write(appendable: Appendable) { appendable.apply { append("OLD: ") - appendLine(jarDiff.oldJar.filename) + append(jarDiff.oldJar.filename) + append(" (bytecodeVersion: ") + append(jarDiff.oldJar.bytecodeVersion.toString()) + appendLine(')') append("NEW: ") - appendLine(jarDiff.newJar.filename) - + append(jarDiff.newJar.filename) + append(" (bytecodeVersion: ") + append(jarDiff.newJar.bytecodeVersion.toString()) + appendLine(')') appendLine() appendLine(jarDiff.archive.toSummaryTable("JAR", Type.JAR_TYPES)) appendLine()