Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ece054c8 authored by Mårten Kongstad's avatar Mårten Kongstad
Browse files

check-flagged-apis: change internal format

Switch the internal format to represent Symbols to (something close to)
the format described in section 4.3.2 of the JVM spec, i.e.

  com/android/SomeClass/someMethod(II[Ljava/lang/String;)Z

This will make parsing method parameters from api-versions.xml easier,
as that file already uses this format, and converting API signature
files to the same format is less painful than going in the other
direction.

Bug: 334870672
Test: atest --host check-flagged-apis-test
Change-Id: I1e1fb8fe208cd51cce2cc129f5aa1cb495672c16
parent 7faf630b
Loading
Loading
Loading
Loading
+15 −15
Original line number Diff line number Diff line
@@ -89,11 +89,11 @@ class CheckFlaggedApisTest {
  fun testParseApiSignature() {
    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")),
            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())
    assertEquals(expected, actual)
@@ -111,11 +111,11 @@ class CheckFlaggedApisTest {
  fun testParseApiVersions() {
    val expected: Set<Symbol> =
        setOf(
            Symbol("android.Clazz"),
            Symbol("android.Clazz.Clazz()"),
            Symbol("android.Clazz.FOO"),
            Symbol("android.Clazz.getErrorCode()"),
            Symbol("android.Clazz.Builder"),
            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())
    assertEquals(expected, actual)
@@ -136,14 +136,14 @@ class CheckFlaggedApisTest {
  fun testFindErrorsDisabledFlaggedApiIsPresent() {
    val expected =
        setOf<ApiError>(
            DisabledFlaggedApiIsPresentError(Symbol("android.Clazz"), Flag("android.flag.foo")),
            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")),
                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")),
                Symbol("android/Clazz/getErrorCode()"), Flag("android.flag.foo")),
            DisabledFlaggedApiIsPresentError(
                Symbol("android.Clazz.Builder"), Flag("android.flag.bar")),
                Symbol("android/Clazz/Builder"), Flag("android.flag.bar")),
        )
    val actual =
        findErrors(
+16 −6
Original line number Diff line number Diff line
@@ -41,21 +41,29 @@ import org.w3c.dom.Node
 * a Java symbol slightly differently. To keep things consistent, all parsed APIs are converted to
 * Symbols.
 *
 * All parts of the fully qualified name of the Symbol are separated by a dot, e.g.:
 * Symbols are encoded using the format similar to the one described in section 4.3.2 of the JVM
 * spec [1], that is, "package.class.inner-class.method(int, int[], android.util.Clazz)" is
 * represented as
 * <pre>
 *   package.class.inner-class.field
 * </pre>
 *   package.class.inner-class.method(II[Landroid/util/Clazz;)
 * <pre>
 *
 * Where possible, the format has been simplified (to make translation of the
 * various input formats easier): for instance, only / is used as delimiter (#
 * and $ are never used).
 *
 * 1. https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.3.2
 */
@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 {
      var sanitizedName = name
      for (ch in FORBIDDEN_CHARS) {
        sanitizedName = sanitizedName.replace(ch, '.')
        sanitizedName = sanitizedName.replace(ch, '/')
      }
      return Symbol(sanitizedName)
    }
@@ -255,7 +263,9 @@ internal fun parseApiVersions(input: InputStream): Set<Symbol> {
          "Bad XML: <field> element without name attribute"
        }
    val className =
        requireNotNull(field.getParentNode()?.getAttribute("name")) { "Bad XML: top level <field> element" }
        requireNotNull(field.getParentNode()?.getAttribute("name")) {
          "Bad XML: top level <field> element"
        }
    output.add(Symbol.create("${className.replace("/", ".")}.$fieldName"))
  }