aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Wright <michaelwr@google.com>2024-04-29 20:29:35 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2024-04-29 20:29:35 +0000
commitcfbcdc1ec59b4304b8f493baccd2080b98e52874 (patch)
tree2645a085ecb6d72452cbc81077526bf1b45926cd
parent013330b02889e12d8cc8f23c91f5f7cff7e985d6 (diff)
parent8d74fd0a3115cf45f16acd412a073a01ffb11b53 (diff)
downloadbuild-cfbcdc1ec59b4304b8f493baccd2080b98e52874.tar.gz
Merge changes Ia860d7b0,Ie98db767 into main
* changes: check-flagged-apis: allow / chars in Symbol names check-flagged-apis: add support for methods (no parameters)
-rw-r--r--tools/check-flagged-apis/src/com/android/checkflaggedapis/CheckFlaggedApisTest.kt12
-rw-r--r--tools/check-flagged-apis/src/com/android/checkflaggedapis/Main.kt52
2 files changed, 58 insertions, 6 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 62c9cbb832..0569bfd71b 100644
--- a/tools/check-flagged-apis/src/com/android/checkflaggedapis/CheckFlaggedApisTest.kt
+++ b/tools/check-flagged-apis/src/com/android/checkflaggedapis/CheckFlaggedApisTest.kt
@@ -31,8 +31,9 @@ private val API_SIGNATURE =
// Signature format: 2.0
package android {
@FlaggedApi("android.flag.foo") public final class Clazz {
- ctor public Clazz();
+ ctor @FlaggedApi("android.flag.foo") public Clazz();
field @FlaggedApi("android.flag.foo") public static final int FOO = 1; // 0x1
+ method @FlaggedApi("android.flag.foo") public int getErrorCode();
}
@FlaggedApi("android.flag.bar") public static class Clazz.Builder {
}
@@ -47,6 +48,7 @@ private val API_VERSIONS =
<class name="android/Clazz" since="1">
<method name="&lt;init>()V"/>
<field name="FOO"/>
+ <method name="getErrorCode()I"/>
</class>
<class name="android/Clazz${"$"}Builder" since="2">
</class>
@@ -88,7 +90,9 @@ class CheckFlaggedApisTest {
val expected =
setOf(
Pair(Symbol("android.Clazz"), Flag("android.flag.foo")),
+ Pair(Symbol("android.Clazz.Clazz()"), Flag("android.flag.foo")),
Pair(Symbol("android.Clazz.FOO"), Flag("android.flag.foo")),
+ Pair(Symbol("android.Clazz.getErrorCode()"), Flag("android.flag.foo")),
Pair(Symbol("android.Clazz.Builder"), Flag("android.flag.bar")),
)
val actual = parseApiSignature("in-memory", API_SIGNATURE.byteInputStream())
@@ -108,7 +112,9 @@ class CheckFlaggedApisTest {
val expected: Set<Symbol> =
setOf(
Symbol("android.Clazz"),
+ Symbol("android.Clazz.Clazz()"),
Symbol("android.Clazz.FOO"),
+ Symbol("android.Clazz.getErrorCode()"),
Symbol("android.Clazz.Builder"),
)
val actual = parseApiVersions(API_VERSIONS.byteInputStream())
@@ -131,8 +137,12 @@ class CheckFlaggedApisTest {
val expected =
setOf<ApiError>(
DisabledFlaggedApiIsPresentError(Symbol("android.Clazz"), Flag("android.flag.foo")),
+ DisabledFlaggedApiIsPresentError(
+ Symbol("android.Clazz.Clazz()"), Flag("android.flag.foo")),
DisabledFlaggedApiIsPresentError(Symbol("android.Clazz.FOO"), Flag("android.flag.foo")),
DisabledFlaggedApiIsPresentError(
+ Symbol("android.Clazz.getErrorCode()"), Flag("android.flag.foo")),
+ DisabledFlaggedApiIsPresentError(
Symbol("android.Clazz.Builder"), Flag("android.flag.bar")),
)
val actual =
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 918a5d9bf3..c3a323bb59 100644
--- a/tools/check-flagged-apis/src/com/android/checkflaggedapis/Main.kt
+++ b/tools/check-flagged-apis/src/com/android/checkflaggedapis/Main.kt
@@ -22,6 +22,7 @@ import com.android.tools.metalava.model.BaseItemVisitor
import com.android.tools.metalava.model.ClassItem
import com.android.tools.metalava.model.FieldItem
import com.android.tools.metalava.model.Item
+import com.android.tools.metalava.model.MethodItem
import com.android.tools.metalava.model.text.ApiFile
import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.core.ProgramResult
@@ -48,7 +49,7 @@ import org.w3c.dom.Node
@JvmInline
internal value class Symbol(val name: String) {
companion object {
- private val FORBIDDEN_CHARS = listOf('/', '#', '$')
+ private val FORBIDDEN_CHARS = listOf('#', '$')
/** Create a new Symbol from a String that may include delimiters other than dot. */
fun create(name: String): Symbol {
@@ -187,6 +188,25 @@ internal fun parseApiSignature(path: String, input: InputStream): Set<Pair<Symbo
}
}
+ override fun visitMethod(method: MethodItem) {
+ getFlagOrNull(method)?.let { flag ->
+ val name = buildString {
+ append(method.containingClass().qualifiedName())
+ append(".")
+ append(method.name())
+ append("(")
+ // TODO(334870672): replace this early return with proper parsing of the command line
+ // arguments, followed by translation to Lname/of/class; + III format
+ if (!method.parameters().isEmpty()) {
+ return
+ }
+ append(")")
+ }
+ val symbol = Symbol.create(name)
+ output.add(Pair(symbol, flag))
+ }
+ }
+
private fun getFlagOrNull(item: Item): Flag? {
return item.modifiers
.findAnnotation("android.annotation.FlaggedApi")
@@ -223,7 +243,7 @@ internal fun parseApiVersions(input: InputStream): Set<Symbol> {
requireNotNull(cls.getAttribute("name")) {
"Bad XML: <class> element without name attribute"
}
- output.add(Symbol.create(className))
+ output.add(Symbol.create(className.replace("/", ".")))
}
val fields = document.getElementsByTagName("field")
@@ -235,9 +255,31 @@ internal fun parseApiVersions(input: InputStream): Set<Symbol> {
"Bad XML: <field> element without name attribute"
}
val className =
- requireNotNull(field.getParentNode()) { "Bad XML: top level <field> element" }
- .getAttribute("name")
- output.add(Symbol.create("$className.$fieldName"))
+ requireNotNull(field.getParentNode()?.getAttribute("name")) { "Bad XML: top level <field> element" }
+ output.add(Symbol.create("${className.replace("/", ".")}.$fieldName"))
+ }
+
+ val methods = document.getElementsByTagName("method")
+ // ktfmt doesn't understand the `..<` range syntax; explicitly call .rangeUntil instead
+ for (i in 0.rangeUntil(methods.getLength())) {
+ val method = methods.item(i)
+ val methodSignature =
+ requireNotNull(method.getAttribute("name")) {
+ "Bad XML: <method> element without name attribute"
+ }
+ val methodSignatureParts = methodSignature.split(Regex("\\(|\\)"))
+ if (methodSignatureParts.size != 3) {
+ throw Exception("Bad XML: method signature '$methodSignature': debug $methodSignatureParts")
+ }
+ var (methodName, methodArgs, methodReturnValue) = methodSignatureParts
+ val packageAndClassName =
+ requireNotNull(method.getParentNode()?.getAttribute("name")) {
+ "Bad XML: top level <method> element, or <class> element missing name attribute"
+ }
+ if (methodName == "<init>") {
+ methodName = packageAndClassName.split("/").last()
+ }
+ output.add(Symbol.create("${packageAndClassName.replace("/", ".")}.$methodName($methodArgs)"))
}
return output