From c3f05a6d92a31d800373217264fd88f55c070739 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Kongstad?= Date: Mon, 6 May 2024 21:42:15 +0200 Subject: [PATCH] check-flagged-apis: record super class when parsing classes Extend ClassSymbol with a nullable reference to the class' superclass. Bug: 334870672 Test: atest --host check-flagged-apis-test Change-Id: Ia2741a4d7fb5de908a03ef640f5fcd38d0ce0e28 --- .../checkflaggedapis/CheckFlaggedApisTest.kt | 24 ++++++++---- .../src/com/android/checkflaggedapis/Main.kt | 37 ++++++++++++++----- 2 files changed, 44 insertions(+), 17 deletions(-) diff --git a/tools/check-flagged-apis/src/com/android/checkflaggedapis/CheckFlaggedApisTest.kt b/tools/check-flagged-apis/src/com/android/checkflaggedapis/CheckFlaggedApisTest.kt index 3cd6a24256..773f4339f0 100644 --- a/tools/check-flagged-apis/src/com/android/checkflaggedapis/CheckFlaggedApisTest.kt +++ b/tools/check-flagged-apis/src/com/android/checkflaggedapis/CheckFlaggedApisTest.kt @@ -49,6 +49,7 @@ private val API_VERSIONS = + @@ -57,6 +58,7 @@ private val API_VERSIONS = + """ @@ -95,7 +97,9 @@ class CheckFlaggedApisTest { fun testParseApiSignature() { val expected = setOf( - Pair(Symbol.createClass("android/Clazz", setOf()), Flag("android.flag.foo")), + Pair( + Symbol.createClass("android/Clazz", "java/lang/Object", setOf()), + Flag("android.flag.foo")), Pair(Symbol.createMethod("android/Clazz", "Clazz()"), Flag("android.flag.foo")), Pair(Symbol.createField("android/Clazz", "FOO"), Flag("android.flag.foo")), Pair(Symbol.createMethod("android/Clazz", "getErrorCode()"), Flag("android.flag.foo")), @@ -108,7 +112,9 @@ class CheckFlaggedApisTest { Pair( Symbol.createMethod("android/Clazz", "innerClassArg(Landroid/Clazz/Builder;)"), Flag("android.flag.foo")), - Pair(Symbol.createClass("android/Clazz/Builder", setOf()), Flag("android.flag.bar")), + Pair( + Symbol.createClass("android/Clazz/Builder", "java/lang/Object", setOf()), + Flag("android.flag.bar")), ) val actual = parseApiSignature("in-memory", API_SIGNATURE.byteInputStream()) assertEquals(expected, actual) @@ -126,14 +132,14 @@ class CheckFlaggedApisTest { fun testParseApiVersions() { val expected: Set = setOf( - Symbol.createClass("android/Clazz", setOf()), + Symbol.createClass("android/Clazz", "java/lang/Object", setOf()), Symbol.createMethod("android/Clazz", "Clazz()"), Symbol.createField("android/Clazz", "FOO"), Symbol.createMethod("android/Clazz", "getErrorCode()"), Symbol.createMethod("android/Clazz", "setData(I[[ILandroid/util/Utility;)"), Symbol.createMethod("android/Clazz", "setVariableData(I[Landroid/util/Atom;)"), Symbol.createMethod("android/Clazz", "innerClassArg(Landroid/Clazz/Builder;)"), - Symbol.createClass("android/Clazz/Builder", setOf()), + Symbol.createClass("android/Clazz/Builder", "java/lang/Object", setOf()), ) val actual = parseApiVersions(API_VERSIONS.byteInputStream()) assertEquals(expected, actual) @@ -146,6 +152,7 @@ class CheckFlaggedApisTest { + @@ -153,7 +160,7 @@ class CheckFlaggedApisTest { .trim() val expected: Set = setOf( - Symbol.createClass("android/Clazz/Foo/Bar", setOf()), + Symbol.createClass("android/Clazz/Foo/Bar", "java/lang/Object", setOf()), Symbol.createMethod("android/Clazz/Foo/Bar", "Bar()"), ) val actual = parseApiVersions(apiVersions.byteInputStream()) @@ -193,6 +200,7 @@ class CheckFlaggedApisTest { + @@ -217,7 +225,8 @@ class CheckFlaggedApisTest { val expected = setOf( DisabledFlaggedApiIsPresentError( - Symbol.createClass("android/Clazz", setOf()), Flag("android.flag.foo")), + Symbol.createClass("android/Clazz", "java/lang/Object", setOf()), + Flag("android.flag.foo")), DisabledFlaggedApiIsPresentError( Symbol.createMethod("android/Clazz", "Clazz()"), Flag("android.flag.foo")), DisabledFlaggedApiIsPresentError( @@ -234,7 +243,8 @@ class CheckFlaggedApisTest { Symbol.createMethod("android/Clazz", "innerClassArg(Landroid/Clazz/Builder;)"), Flag("android.flag.foo")), DisabledFlaggedApiIsPresentError( - Symbol.createClass("android/Clazz/Builder", setOf()), Flag("android.flag.bar")), + Symbol.createClass("android/Clazz/Builder", "java/lang/Object", setOf()), + Flag("android.flag.bar")), ) val actual = findErrors( diff --git a/tools/check-flagged-apis/src/com/android/checkflaggedapis/Main.kt b/tools/check-flagged-apis/src/com/android/checkflaggedapis/Main.kt index 867ee94a9a..dc0d31c375 100644 --- a/tools/check-flagged-apis/src/com/android/checkflaggedapis/Main.kt +++ b/tools/check-flagged-apis/src/com/android/checkflaggedapis/Main.kt @@ -58,8 +58,11 @@ internal sealed class Symbol { companion object { private val FORBIDDEN_CHARS = listOf('#', '$', '.') - fun createClass(clazz: String, interfaces: Set): Symbol { - return ClassSymbol(toInternalFormat(clazz), interfaces.map { toInternalFormat(it) }.toSet()) + fun createClass(clazz: String, superclass: String?, interfaces: Set): Symbol { + return ClassSymbol( + toInternalFormat(clazz), + superclass?.let { toInternalFormat(it) }, + interfaces.map { toInternalFormat(it) }.toSet()) } fun createField(clazz: String, field: String): Symbol { @@ -83,7 +86,11 @@ internal sealed class Symbol { abstract fun toPrettyString(): String } -internal data class ClassSymbol(val clazz: String, val interfaces: Set) : Symbol() { +internal data class ClassSymbol( + val clazz: String, + val superclass: String?, + val interfaces: Set +) : Symbol() { override fun toPrettyString(): String = "$clazz" } @@ -198,6 +205,7 @@ internal fun parseApiSignature(path: String, input: InputStream): Set { requireNotNull(cls.getAttribute("name")) { "Bad XML: element without name attribute" } + var superclass: String? = null val interfaces = mutableSetOf() val children = cls.getChildNodes() for (j in 0.rangeUntil(children.getLength())) { val child = children.item(j) - if (child.getNodeName() == "implements") { - val interfaceName = - requireNotNull(child.getAttribute("name")) { - "Bad XML: element without name attribute" - } - interfaces.add(interfaceName) + when (child.getNodeName()) { + "extends" -> { + superclass = + requireNotNull(child.getAttribute("name")) { + "Bad XML: element without name attribute" + } + } + "implements" -> { + val interfaceName = + requireNotNull(child.getAttribute("name")) { + "Bad XML: element without name attribute" + } + interfaces.add(interfaceName) + } } } - output.add(Symbol.createClass(className, interfaces)) + output.add(Symbol.createClass(className, superclass, interfaces)) } val fields = document.getElementsByTagName("field")