From bd8c83bee2b100580f9ade2a958abf22878f4c3b Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Tue, 22 Mar 2016 20:11:40 +0300 Subject: [PATCH] Merge public static API of non-public base supertypes into public subtype --- .../PublicApiDump.kt | 27 ++++++++++++++----- .../org.jetbrains.kotlin.tools/asmUtils.kt | 3 ++- .../src/test/kotlin/cases/java/Facade.java | 9 ++++--- .../src/test/resources/output/cases/java.txt | 4 ++- 4 files changed, 31 insertions(+), 12 deletions(-) diff --git a/libraries/tools/binary-compatibility-validator/src/main/kotlin/org.jetbrains.kotlin.tools/PublicApiDump.kt b/libraries/tools/binary-compatibility-validator/src/main/kotlin/org.jetbrains.kotlin.tools/PublicApiDump.kt index 75a932f3b06..1949228aa10 100644 --- a/libraries/tools/binary-compatibility-validator/src/main/kotlin/org.jetbrains.kotlin.tools/PublicApiDump.kt +++ b/libraries/tools/binary-compatibility-validator/src/main/kotlin/org.jetbrains.kotlin.tools/PublicApiDump.kt @@ -19,7 +19,8 @@ fun main(args: Array) { fun JarFile.classEntries() = entries().asSequence().filter { !it.isDirectory && it.name.endsWith(".class") } -data class ClassBinarySignature(val name: String, val outerName: String?, val modifiers: String, val supertypes: List, val memberSignatures: List, val isPublic: Boolean) +data class ClassBinarySignature(val name: String, val superName: String, val outerName: String?, val modifiers: String, val supertypes: List, val memberSignatures: List, val isPublic: Boolean) +data class MemberBinarySignature(val name: String, val signature: String, val isStatic: Boolean) val ClassBinarySignature.signature: String get() = "$modifiers class $name" + if (supertypes.isEmpty()) "" else ": ${supertypes.joinToString()}" @@ -48,12 +49,12 @@ fun getBinaryAPI(classStreams: Sequence, visibilityMap: Map.filterOutNonPublic(): List fun ClassBinarySignature.isPublicAndAccessible(): Boolean = isPublic && (outerName == null || classByName[outerName]?.isPublicAndAccessible() ?: true) - return filter { it -> it.isPublicAndAccessible() } + fun supertypes(superName: String) = generateSequence({ classByName[superName] }, { classByName[it.superName] }) + + fun ClassBinarySignature.flattenNonPublicBases(): ClassBinarySignature { + + val nonPublicSupertypes = supertypes(superName).takeWhile { !it.isPublicAndAccessible() }.toList() + if (nonPublicSupertypes.isEmpty()) + return this + + val inheritedStaticSignatures = nonPublicSupertypes.flatMap { it.memberSignatures.filter { it.isStatic }} + + // not covered the case when there is public superclass after chain of private superclasses + return this.copy(memberSignatures = memberSignatures + inheritedStaticSignatures, supertypes = supertypes - superName) + } + + return filter { it -> it.isPublicAndAccessible() }.map { it.flattenNonPublicBases() } } fun List.dump() = dump(to = System.out) fun List.dump(to: T): T = to.apply { this@dump.forEach { appendln(it.signature) - it.memberSignatures.forEach { appendln(it) } + it.memberSignatures.forEach { appendln(it.signature) } appendln("------------------\n") }} diff --git a/libraries/tools/binary-compatibility-validator/src/main/kotlin/org.jetbrains.kotlin.tools/asmUtils.kt b/libraries/tools/binary-compatibility-validator/src/main/kotlin/org.jetbrains.kotlin.tools/asmUtils.kt index bed0db6feb3..04e97e1310e 100644 --- a/libraries/tools/binary-compatibility-validator/src/main/kotlin/org.jetbrains.kotlin.tools/asmUtils.kt +++ b/libraries/tools/binary-compatibility-validator/src/main/kotlin/org.jetbrains.kotlin.tools/asmUtils.kt @@ -16,7 +16,8 @@ val ACCESS_NAMES = mapOf( Opcodes.ACC_ANNOTATION to "annotation") -private fun isPublic(access: Int) = access and Opcodes.ACC_PUBLIC != 0 || access and Opcodes.ACC_PROTECTED != 0 +public fun isPublic(access: Int) = access and Opcodes.ACC_PUBLIC != 0 || access and Opcodes.ACC_PROTECTED != 0 +public fun isStatic(access: Int) = access and Opcodes.ACC_STATIC != 0 fun getModifiers(access: Int): List = ACCESS_NAMES.entries.mapNotNull { if (access and it.key != 0) it.value else null } fun getModifierString(access: Int): String = getModifiers(access).joinToString(" ") diff --git a/libraries/tools/binary-compatibility-validator/src/test/kotlin/cases/java/Facade.java b/libraries/tools/binary-compatibility-validator/src/test/kotlin/cases/java/Facade.java index a97e661383c..21b0d9f4c69 100644 --- a/libraries/tools/binary-compatibility-validator/src/test/kotlin/cases/java/Facade.java +++ b/libraries/tools/binary-compatibility-validator/src/test/kotlin/cases/java/Facade.java @@ -2,10 +2,11 @@ package cases.java; class Part1 { public static void publicMethod(String param) { } + + public static class Part2 extends Part1 { + public static void publicMethod(int param) { } + } } -class Part2 extends Part1 { - public static void publicMethod(int param) { } -} -public class Facade extends Part2 { } +public class Facade extends Part1.Part2 { } diff --git a/libraries/tools/binary-compatibility-validator/src/test/resources/output/cases/java.txt b/libraries/tools/binary-compatibility-validator/src/test/resources/output/cases/java.txt index c6871be625d..add24cf0fcb 100644 --- a/libraries/tools/binary-compatibility-validator/src/test/resources/output/cases/java.txt +++ b/libraries/tools/binary-compatibility-validator/src/test/resources/output/cases/java.txt @@ -1,4 +1,6 @@ -public class cases/java/Facade: cases/java/Part2 +public class cases/java/Facade public fun ()V +public static fun publicMethod (I)V +public static fun publicMethod (Ljava/lang/String;)V ------------------