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 = + @@ -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 = 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,7 +137,11 @@ class CheckFlaggedApisTest { val expected = setOf( 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")), ) 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..143243af85 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 @@ -187,6 +188,25 @@ internal fun parseApiSignature(path: String, input: InputStream): Set + 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") @@ -240,6 +260,29 @@ internal fun parseApiVersions(input: InputStream): Set { output.add(Symbol.create("$className.$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: 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 element, or element missing name attribute" + } + if (methodName == "") { + methodName = packageAndClassName.split("/").last() + } + output.add(Symbol.create("$packageAndClassName.$methodName($methodArgs)")) + } + return output }