aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMårten Kongstad <amhk@google.com>2024-05-08 10:00:32 +0200
committerMårten Kongstad <amhk@google.com>2024-05-08 13:30:58 +0200
commit0d44e721ed0539d9c3ad75aec138204ae2054faa (patch)
treeebf6b756c411be99fa4de30fdf7767f57980aa4e
parent32b652fd68e9d17be61b3a6a0c5ceff213b29b36 (diff)
downloadbuild-0d44e721ed0539d9c3ad75aec138204ae2054faa.tar.gz
check-flagged-apis: handle nested flags
Consider @FlaggedApi(FLAG_OUTER) Clazz { @FlaggedApi(FLAG_INNER) method(); } If FLAG_OUTER is disabled, any class members are ignored. Teach check-flagged-apis to recognize this and stop reporting false positives. Bug: 339183637 Test: atest --host check-flagged-apis-test Change-Id: Ie6799e952dc33874c1239231f841d7dfd947c7ce
-rw-r--r--tools/check-flagged-apis/src/com/android/checkflaggedapis/CheckFlaggedApisTest.kt36
-rw-r--r--tools/check-flagged-apis/src/com/android/checkflaggedapis/Main.kt40
2 files changed, 75 insertions, 1 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 cd859448b0..111ea91f85 100644
--- a/tools/check-flagged-apis/src/com/android/checkflaggedapis/CheckFlaggedApisTest.kt
+++ b/tools/check-flagged-apis/src/com/android/checkflaggedapis/CheckFlaggedApisTest.kt
@@ -270,6 +270,42 @@ class CheckFlaggedApisTest {
}
@Test
+ fun testNestedFlagsOuterFlagWins() {
+ val apiSignature =
+ """
+ // Signature format: 2.0
+ package android {
+ @FlaggedApi("android.flag.foo") public final class A {
+ method @FlaggedApi("android.flag.bar") public boolean method();
+ }
+ @FlaggedApi("android.flag.bar") public final class B {
+ method @FlaggedApi("android.flag.foo") public boolean method();
+ }
+ }
+ """
+ .trim()
+
+ val apiVersions =
+ """
+ <?xml version="1.0" encoding="utf-8"?>
+ <api version="3">
+ <class name="android/B" since="1">
+ <extends name="java/lang/Object"/>
+ </class>
+ </api>
+ """
+ .trim()
+
+ val expected = setOf<ApiError>()
+ val actual =
+ findErrors(
+ parseApiSignature("in-memory", apiSignature.byteInputStream()),
+ parseFlagValues(generateFlagsProto(DISABLED, ENABLED)),
+ parseApiVersions(apiVersions.byteInputStream()))
+ assertEquals(expected, actual)
+ }
+
+ @Test
fun testFindErrorsDisabledFlaggedApiIsPresent() {
val expected =
setOf<ApiError>(
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 b514048bd6..a277ce815f 100644
--- a/tools/check-flagged-apis/src/com/android/checkflaggedapis/Main.kt
+++ b/tools/check-flagged-apis/src/com/android/checkflaggedapis/Main.kt
@@ -385,10 +385,48 @@ internal fun findErrors(
return false
}
+
+ /**
+ * Returns whether the given flag is enabled for the given symbol.
+ *
+ * A flagged member inside a flagged class is ignored (and the flag value considered disabled) if
+ * the class' flag is disabled.
+ *
+ * @param symbol the symbol to check
+ * @param flag the flag to check
+ * @return whether the flag is enabled for the given symbol
+ */
+ fun isFlagEnabledForSymbol(symbol: Symbol, flag: Flag): Boolean {
+ when (symbol) {
+ is ClassSymbol -> return flags.getValue(flag)
+ is MemberSymbol -> {
+ val memberFlagValue = flags.getValue(flag)
+ if (!memberFlagValue) {
+ return false
+ }
+ // Special case: if the MemberSymbol's flag is enabled, but the outer
+ // ClassSymbol's flag (if the class is flagged) is disabled, consider
+ // the MemberSymbol's flag as disabled:
+ //
+ // @FlaggedApi(this-flag-is-disabled) Clazz {
+ // @FlaggedApi(this-flag-is-enabled) method(); // The Clazz' flag "wins"
+ // }
+ //
+ // Note: the current implementation does not handle nested classes.
+ val classFlagValue =
+ flaggedSymbolsInSource
+ .find { it.first.toPrettyString() == symbol.clazz }
+ ?.let { flags.getValue(it.second) }
+ ?: true
+ return classFlagValue
+ }
+ }
+ }
+
val errors = mutableSetOf<ApiError>()
for ((symbol, flag) in flaggedSymbolsInSource) {
try {
- if (flags.getValue(flag)) {
+ if (isFlagEnabledForSymbol(symbol, flag)) {
if (!symbolsInOutput.containsSymbol(symbol)) {
errors.add(EnabledFlaggedApiNotPresentError(symbol, flag))
}