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
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 b514048..a277ce8 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 @@
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))
}