From d2c707613e650b7c0f9ec02d6c469cecb408973c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Kongstad?= Date: Mon, 6 May 2024 14:58:18 +0200 Subject: [PATCH] check-flagged-apis: consider interfaces when looking up symbol When searching for potential errors, if a symbol can't be found in the api-verions.xml data, check if it is present in any of the class' interfaces. A follow-up CL will add similar logic to handle super classes. Bug: 334870672 Test: atest --host check-flagged-apis-test Change-Id: Ia6dfcfa8495b89465db60f6a4eb77d304112046b --- .../checkflaggedapis/CheckFlaggedApisTest.kt | 41 +++++++++++++++++++ .../src/com/android/checkflaggedapis/Main.kt | 34 ++++++++++++++- 2 files changed, 73 insertions(+), 2 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 29604f4e31..3cd6a24256 100644 --- a/tools/check-flagged-apis/src/com/android/checkflaggedapis/CheckFlaggedApisTest.kt +++ b/tools/check-flagged-apis/src/com/android/checkflaggedapis/CheckFlaggedApisTest.kt @@ -171,6 +171,47 @@ class CheckFlaggedApisTest { assertEquals(expected, actual) } + @Test + fun testFindErrorsVerifyImplements() { + val apiSignature = + """ + // Signature format: 2.0 + package android { + @FlaggedApi("android.flag.foo") public final class Clazz implements android.Interface { + method @FlaggedApi("android.flag.foo") public boolean foo(); + method @FlaggedApi("android.flag.foo") public boolean bar(); + } + public interface Interface { + method public boolean bar(); + } + } + """ + .trim() + + val apiVersions = + """ + + + + + + + + + + + """ + .trim() + + val expected = setOf() + val actual = + findErrors( + parseApiSignature("in-memory", apiSignature.byteInputStream()), + parseFlagValues(generateFlagsProto(ENABLED, ENABLED)), + parseApiVersions(apiVersions.byteInputStream())) + assertEquals(expected, actual) + } + @Test fun testFindErrorsDisabledFlaggedApiIsPresent() { val expected = 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 0d2d24e19f..867ee94a9a 100644 --- a/tools/check-flagged-apis/src/com/android/checkflaggedapis/Main.kt +++ b/tools/check-flagged-apis/src/com/android/checkflaggedapis/Main.kt @@ -333,15 +333,45 @@ internal fun findErrors( flags: Map, symbolsInOutput: Set ): Set { + fun Set.containsSymbol(symbol: Symbol): Boolean { + // trivial case: the symbol is explicitly listed in api-versions.xml + if (contains(symbol)) { + return true + } + + // non-trivial case: the symbol could be part of the surrounding class' + // super class or interfaces + val (className, memberName) = + when (symbol) { + is ClassSymbol -> return false + is MemberSymbol -> { + Pair(symbol.clazz, symbol.member) + } + } + val clazz = find { it is ClassSymbol && it.clazz == className } as? ClassSymbol? + if (clazz == null) { + return false + } + + for (interfaceName in clazz.interfaces) { + // createMethod is the same as createField, except it allows parenthesis + val interfaceSymbol = Symbol.createMethod(interfaceName, memberName) + if (contains(interfaceSymbol)) { + return true + } + } + + return false + } val errors = mutableSetOf() for ((symbol, flag) in flaggedSymbolsInSource) { try { if (flags.getValue(flag)) { - if (!symbolsInOutput.contains(symbol)) { + if (!symbolsInOutput.containsSymbol(symbol)) { errors.add(EnabledFlaggedApiNotPresentError(symbol, flag)) } } else { - if (symbolsInOutput.contains(symbol)) { + if (symbolsInOutput.containsSymbol(symbol)) { errors.add(DisabledFlaggedApiIsPresentError(symbol, flag)) } }