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
This commit is contained in:
@@ -49,6 +49,7 @@ private val API_VERSIONS =
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<api version="3">
|
<api version="3">
|
||||||
<class name="android/Clazz" since="1">
|
<class name="android/Clazz" since="1">
|
||||||
|
<extends name="java/lang/Object"/>
|
||||||
<method name="<init>()V"/>
|
<method name="<init>()V"/>
|
||||||
<field name="FOO"/>
|
<field name="FOO"/>
|
||||||
<method name="getErrorCode()I"/>
|
<method name="getErrorCode()I"/>
|
||||||
@@ -57,6 +58,7 @@ private val API_VERSIONS =
|
|||||||
<method name="innerClassArg(Landroid/Clazz${"$"}Builder;)"/>
|
<method name="innerClassArg(Landroid/Clazz${"$"}Builder;)"/>
|
||||||
</class>
|
</class>
|
||||||
<class name="android/Clazz${"$"}Builder" since="2">
|
<class name="android/Clazz${"$"}Builder" since="2">
|
||||||
|
<extends name="java/lang/Object"/>
|
||||||
</class>
|
</class>
|
||||||
</api>
|
</api>
|
||||||
"""
|
"""
|
||||||
@@ -95,7 +97,9 @@ class CheckFlaggedApisTest {
|
|||||||
fun testParseApiSignature() {
|
fun testParseApiSignature() {
|
||||||
val expected =
|
val expected =
|
||||||
setOf(
|
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.createMethod("android/Clazz", "Clazz()"), Flag("android.flag.foo")),
|
||||||
Pair(Symbol.createField("android/Clazz", "FOO"), Flag("android.flag.foo")),
|
Pair(Symbol.createField("android/Clazz", "FOO"), Flag("android.flag.foo")),
|
||||||
Pair(Symbol.createMethod("android/Clazz", "getErrorCode()"), Flag("android.flag.foo")),
|
Pair(Symbol.createMethod("android/Clazz", "getErrorCode()"), Flag("android.flag.foo")),
|
||||||
@@ -108,7 +112,9 @@ class CheckFlaggedApisTest {
|
|||||||
Pair(
|
Pair(
|
||||||
Symbol.createMethod("android/Clazz", "innerClassArg(Landroid/Clazz/Builder;)"),
|
Symbol.createMethod("android/Clazz", "innerClassArg(Landroid/Clazz/Builder;)"),
|
||||||
Flag("android.flag.foo")),
|
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())
|
val actual = parseApiSignature("in-memory", API_SIGNATURE.byteInputStream())
|
||||||
assertEquals(expected, actual)
|
assertEquals(expected, actual)
|
||||||
@@ -126,14 +132,14 @@ class CheckFlaggedApisTest {
|
|||||||
fun testParseApiVersions() {
|
fun testParseApiVersions() {
|
||||||
val expected: Set<Symbol> =
|
val expected: Set<Symbol> =
|
||||||
setOf(
|
setOf(
|
||||||
Symbol.createClass("android/Clazz", setOf()),
|
Symbol.createClass("android/Clazz", "java/lang/Object", setOf()),
|
||||||
Symbol.createMethod("android/Clazz", "Clazz()"),
|
Symbol.createMethod("android/Clazz", "Clazz()"),
|
||||||
Symbol.createField("android/Clazz", "FOO"),
|
Symbol.createField("android/Clazz", "FOO"),
|
||||||
Symbol.createMethod("android/Clazz", "getErrorCode()"),
|
Symbol.createMethod("android/Clazz", "getErrorCode()"),
|
||||||
Symbol.createMethod("android/Clazz", "setData(I[[ILandroid/util/Utility;)"),
|
Symbol.createMethod("android/Clazz", "setData(I[[ILandroid/util/Utility;)"),
|
||||||
Symbol.createMethod("android/Clazz", "setVariableData(I[Landroid/util/Atom;)"),
|
Symbol.createMethod("android/Clazz", "setVariableData(I[Landroid/util/Atom;)"),
|
||||||
Symbol.createMethod("android/Clazz", "innerClassArg(Landroid/Clazz/Builder;)"),
|
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())
|
val actual = parseApiVersions(API_VERSIONS.byteInputStream())
|
||||||
assertEquals(expected, actual)
|
assertEquals(expected, actual)
|
||||||
@@ -146,6 +152,7 @@ class CheckFlaggedApisTest {
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<api version="3">
|
<api version="3">
|
||||||
<class name="android/Clazz${'$'}Foo${'$'}Bar" since="1">
|
<class name="android/Clazz${'$'}Foo${'$'}Bar" since="1">
|
||||||
|
<extends name="java/lang/Object"/>
|
||||||
<method name="<init>()V"/>
|
<method name="<init>()V"/>
|
||||||
</class>
|
</class>
|
||||||
</api>
|
</api>
|
||||||
@@ -153,7 +160,7 @@ class CheckFlaggedApisTest {
|
|||||||
.trim()
|
.trim()
|
||||||
val expected: Set<Symbol> =
|
val expected: Set<Symbol> =
|
||||||
setOf(
|
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()"),
|
Symbol.createMethod("android/Clazz/Foo/Bar", "Bar()"),
|
||||||
)
|
)
|
||||||
val actual = parseApiVersions(apiVersions.byteInputStream())
|
val actual = parseApiVersions(apiVersions.byteInputStream())
|
||||||
@@ -193,6 +200,7 @@ class CheckFlaggedApisTest {
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<api version="3">
|
<api version="3">
|
||||||
<class name="android/Clazz" since="1">
|
<class name="android/Clazz" since="1">
|
||||||
|
<extends name="java/lang/Object"/>
|
||||||
<implements name="android/Interface"/>
|
<implements name="android/Interface"/>
|
||||||
<method name="foo()Z"/>
|
<method name="foo()Z"/>
|
||||||
</class>
|
</class>
|
||||||
@@ -217,7 +225,8 @@ class CheckFlaggedApisTest {
|
|||||||
val expected =
|
val expected =
|
||||||
setOf<ApiError>(
|
setOf<ApiError>(
|
||||||
DisabledFlaggedApiIsPresentError(
|
DisabledFlaggedApiIsPresentError(
|
||||||
Symbol.createClass("android/Clazz", setOf()), Flag("android.flag.foo")),
|
Symbol.createClass("android/Clazz", "java/lang/Object", setOf()),
|
||||||
|
Flag("android.flag.foo")),
|
||||||
DisabledFlaggedApiIsPresentError(
|
DisabledFlaggedApiIsPresentError(
|
||||||
Symbol.createMethod("android/Clazz", "Clazz()"), Flag("android.flag.foo")),
|
Symbol.createMethod("android/Clazz", "Clazz()"), Flag("android.flag.foo")),
|
||||||
DisabledFlaggedApiIsPresentError(
|
DisabledFlaggedApiIsPresentError(
|
||||||
@@ -234,7 +243,8 @@ class CheckFlaggedApisTest {
|
|||||||
Symbol.createMethod("android/Clazz", "innerClassArg(Landroid/Clazz/Builder;)"),
|
Symbol.createMethod("android/Clazz", "innerClassArg(Landroid/Clazz/Builder;)"),
|
||||||
Flag("android.flag.foo")),
|
Flag("android.flag.foo")),
|
||||||
DisabledFlaggedApiIsPresentError(
|
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 =
|
val actual =
|
||||||
findErrors(
|
findErrors(
|
||||||
|
@@ -58,8 +58,11 @@ internal sealed class Symbol {
|
|||||||
companion object {
|
companion object {
|
||||||
private val FORBIDDEN_CHARS = listOf('#', '$', '.')
|
private val FORBIDDEN_CHARS = listOf('#', '$', '.')
|
||||||
|
|
||||||
fun createClass(clazz: String, interfaces: Set<String>): Symbol {
|
fun createClass(clazz: String, superclass: String?, interfaces: Set<String>): Symbol {
|
||||||
return ClassSymbol(toInternalFormat(clazz), interfaces.map { toInternalFormat(it) }.toSet())
|
return ClassSymbol(
|
||||||
|
toInternalFormat(clazz),
|
||||||
|
superclass?.let { toInternalFormat(it) },
|
||||||
|
interfaces.map { toInternalFormat(it) }.toSet())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createField(clazz: String, field: String): Symbol {
|
fun createField(clazz: String, field: String): Symbol {
|
||||||
@@ -83,7 +86,11 @@ internal sealed class Symbol {
|
|||||||
abstract fun toPrettyString(): String
|
abstract fun toPrettyString(): String
|
||||||
}
|
}
|
||||||
|
|
||||||
internal data class ClassSymbol(val clazz: String, val interfaces: Set<String>) : Symbol() {
|
internal data class ClassSymbol(
|
||||||
|
val clazz: String,
|
||||||
|
val superclass: String?,
|
||||||
|
val interfaces: Set<String>
|
||||||
|
) : Symbol() {
|
||||||
override fun toPrettyString(): String = "$clazz"
|
override fun toPrettyString(): String = "$clazz"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,6 +205,7 @@ internal fun parseApiSignature(path: String, input: InputStream): Set<Pair<Symbo
|
|||||||
val symbol =
|
val symbol =
|
||||||
Symbol.createClass(
|
Symbol.createClass(
|
||||||
cls.baselineElementId(),
|
cls.baselineElementId(),
|
||||||
|
cls.superClass()?.baselineElementId(),
|
||||||
cls.allInterfaces()
|
cls.allInterfaces()
|
||||||
.map { it.baselineElementId() }
|
.map { it.baselineElementId() }
|
||||||
.filter { it != cls.baselineElementId() }
|
.filter { it != cls.baselineElementId() }
|
||||||
@@ -263,19 +271,28 @@ internal fun parseApiVersions(input: InputStream): Set<Symbol> {
|
|||||||
requireNotNull(cls.getAttribute("name")) {
|
requireNotNull(cls.getAttribute("name")) {
|
||||||
"Bad XML: <class> element without name attribute"
|
"Bad XML: <class> element without name attribute"
|
||||||
}
|
}
|
||||||
|
var superclass: String? = null
|
||||||
val interfaces = mutableSetOf<String>()
|
val interfaces = mutableSetOf<String>()
|
||||||
val children = cls.getChildNodes()
|
val children = cls.getChildNodes()
|
||||||
for (j in 0.rangeUntil(children.getLength())) {
|
for (j in 0.rangeUntil(children.getLength())) {
|
||||||
val child = children.item(j)
|
val child = children.item(j)
|
||||||
if (child.getNodeName() == "implements") {
|
when (child.getNodeName()) {
|
||||||
val interfaceName =
|
"extends" -> {
|
||||||
requireNotNull(child.getAttribute("name")) {
|
superclass =
|
||||||
"Bad XML: <implements> element without name attribute"
|
requireNotNull(child.getAttribute("name")) {
|
||||||
}
|
"Bad XML: <extends> element without name attribute"
|
||||||
interfaces.add(interfaceName)
|
}
|
||||||
|
}
|
||||||
|
"implements" -> {
|
||||||
|
val interfaceName =
|
||||||
|
requireNotNull(child.getAttribute("name")) {
|
||||||
|
"Bad XML: <implements> 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")
|
val fields = document.getElementsByTagName("field")
|
||||||
|
Reference in New Issue
Block a user