Binary compatibility validator: filter out empty facades *after* members are flattened from non-public part superclasses.
Use stable member sort order for members flattened from non-public superclasses, rewrite test to make order matter.
This commit is contained in:
+7
-12
@@ -5,7 +5,6 @@ import org.objectweb.asm.tree.*
|
||||
import java.io.File
|
||||
import java.io.InputStream
|
||||
import java.util.jar.JarFile
|
||||
import kotlin.comparisons.compareBy
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
var src = args[0]
|
||||
@@ -36,19 +35,13 @@ fun getBinaryAPI(classStreams: Sequence<InputStream>, visibilityMap: Map<String,
|
||||
val supertypes = listOf(superName) - "java/lang/Object" + interfaces.sorted()
|
||||
|
||||
val memberSignatures = (
|
||||
fields
|
||||
.sortedBy { it.name }
|
||||
.map { with(it) { FieldBinarySignature(name, desc, isInlineExposed(), AccessFlags(access)) } } +
|
||||
methods
|
||||
.sortedWith(compareBy({ it.name }, { it.desc }))
|
||||
.map { with(it) { MethodBinarySignature(name, desc, isInlineExposed(), AccessFlags(access)) } }
|
||||
fields.map { with(it) { FieldBinarySignature(name, desc, isInlineExposed(), AccessFlags(access)) } } +
|
||||
methods.map { with(it) { MethodBinarySignature(name, desc, isInlineExposed(), AccessFlags(access)) } }
|
||||
).filter {
|
||||
it.isEffectivelyPublic(classAccess, classVisibility)
|
||||
}
|
||||
val isEffectivelyPublic = it.isEffectivelyPublic(classVisibility)
|
||||
&& !(isFileOrMultipartFacade() && memberSignatures.isEmpty())
|
||||
|
||||
ClassBinarySignature(name, superName, outerClassName, supertypes, memberSignatures, classAccess, isEffectivelyPublic)
|
||||
ClassBinarySignature(name, superName, outerClassName, supertypes, memberSignatures, classAccess, isEffectivelyPublic(classVisibility), isFileOrMultipartFacade())
|
||||
}}
|
||||
.asIterable()
|
||||
.sortedBy { it.name }
|
||||
@@ -79,14 +72,16 @@ fun List<ClassBinarySignature>.filterOutNonPublic(): List<ClassBinarySignature>
|
||||
return this.copy(memberSignatures = memberSignatures + inheritedStaticSignatures, supertypes = supertypes - superName)
|
||||
}
|
||||
|
||||
return filter { it -> it.isPublicAndAccessible() }.map { it.flattenNonPublicBases() }
|
||||
return filter { it.isPublicAndAccessible() }
|
||||
.map { it.flattenNonPublicBases() }
|
||||
.filterNot { it.isFileOrMultipartFacade && it.memberSignatures.isEmpty()}
|
||||
}
|
||||
|
||||
fun List<ClassBinarySignature>.dump() = dump(to = System.out)
|
||||
|
||||
fun <T: Appendable> List<ClassBinarySignature>.dump(to: T): T = to.apply { this@dump.forEach {
|
||||
append(it.signature).appendln(" {")
|
||||
it.memberSignatures.forEach { append("\t").appendln(it.signature) }
|
||||
it.memberSignatures.sortedWith(MEMBER_SORT_ORDER).forEach { append("\t").appendln(it.signature) }
|
||||
appendln("}\n")
|
||||
}}
|
||||
|
||||
|
||||
+14
-1
@@ -2,6 +2,7 @@ package org.jetbrains.kotlin.tools
|
||||
|
||||
import org.objectweb.asm.Opcodes
|
||||
import org.objectweb.asm.tree.*
|
||||
import kotlin.comparisons.*
|
||||
|
||||
val ACCESS_NAMES = mapOf(
|
||||
Opcodes.ACC_PUBLIC to "public",
|
||||
@@ -21,7 +22,8 @@ data class ClassBinarySignature(
|
||||
val supertypes: List<String>,
|
||||
val memberSignatures: List<MemberBinarySignature>,
|
||||
val access: AccessFlags,
|
||||
val isEffectivelyPublic: Boolean) {
|
||||
val isEffectivelyPublic: Boolean,
|
||||
val isFileOrMultipartFacade: Boolean) {
|
||||
|
||||
val signature: String
|
||||
get() = "${access.getModifierString()} class $name" + if (supertypes.isEmpty()) "" else " : ${supertypes.joinToString()}"
|
||||
@@ -79,6 +81,17 @@ data class FieldBinarySignature(
|
||||
}
|
||||
}
|
||||
|
||||
val MemberBinarySignature.kind: Int get() = when (this) {
|
||||
is FieldBinarySignature -> 1
|
||||
is MethodBinarySignature -> 2
|
||||
else -> error("Unsupported $this")
|
||||
}
|
||||
|
||||
val MEMBER_SORT_ORDER = compareBy<MemberBinarySignature>(
|
||||
{ it.kind },
|
||||
{ it.name },
|
||||
{ it.desc }
|
||||
)
|
||||
|
||||
|
||||
data class AccessFlags(val access: Int) {
|
||||
|
||||
+2
-2
@@ -1,10 +1,10 @@
|
||||
package cases.java;
|
||||
|
||||
class Part1 {
|
||||
public static void publicMethod(String param) { }
|
||||
public static void publicMethod(int param) { }
|
||||
|
||||
public static class Part2 extends Part1 {
|
||||
public static void publicMethod(int param) { }
|
||||
public static void publicMethod(String param) { }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user