Propagate class @Immutable.Ignore to references
If a class is marked at its header with @Immutable.Ignore, the
processor should ignore all usages and references to the class,
regardless of it's used as a return type or type arg.
Without this change, it was required to mark @Ignore on all of
usages of the class.
Test: atest android.processor.ImmutabilityProcessorTest#ignoredClass
Change-Id: I5cd470d86c6eb8c3358656a6d8f6e2588bdb6c66
diff --git a/tools/processors/immutability/src/android/processor/immutability/ImmutabilityProcessor.kt b/tools/processors/immutability/src/android/processor/immutability/ImmutabilityProcessor.kt
index dfebdcc..f29d9b2 100644
--- a/tools/processors/immutability/src/android/processor/immutability/ImmutabilityProcessor.kt
+++ b/tools/processors/immutability/src/android/processor/immutability/ImmutabilityProcessor.kt
@@ -323,8 +323,15 @@
parentPolicyExceptions: Set<Immutable.Policy.Exception>,
nonInterfaceClassFailure: () -> String = { MessageUtils.nonInterfaceReturnFailure() },
): Boolean {
+ // Skip if the symbol being considered is itself ignored
if (isIgnored(symbol)) return false
+
+ // Skip if the type being checked, like for a typeArg or return type, is ignored
if (isIgnored(type)) return false
+
+ // Skip if that typeArg is itself ignored when inspected at the class header level
+ if (isIgnored(type.asElement())) return false
+
if (type.isPrimitive) return false
if (type.isPrimitiveOrVoid) {
printError(parentChain, symbol, MessageUtils.voidReturnFailure())
@@ -355,6 +362,8 @@
var anyError = false
type.typeArguments.forEachIndexed { index, typeArg ->
+ if (isIgnored(typeArg.asElement())) return@forEachIndexed
+
val argError =
visitType(parentChain, seenTypesByPolicy, symbol, typeArg, newPolicyExceptions) {
MessageUtils.nonInterfaceReturnFailure(
diff --git a/tools/processors/immutability/test/android/processor/ImmutabilityProcessorTest.kt b/tools/processors/immutability/test/android/processor/ImmutabilityProcessorTest.kt
index 2f7d59a..43caa45 100644
--- a/tools/processors/immutability/test/android/processor/ImmutabilityProcessorTest.kt
+++ b/tools/processors/immutability/test/android/processor/ImmutabilityProcessorTest.kt
@@ -287,6 +287,42 @@
)
}
+ @Test
+ fun ignoredClass() = test(
+ JavaFileObjects.forSourceString(
+ "$PACKAGE_PREFIX.$DATA_CLASS_NAME",
+ /* language=JAVA */ """
+ package $PACKAGE_PREFIX;
+
+ import java.util.List;
+ import java.util.Map;
+
+ @Immutable
+ public interface $DATA_CLASS_NAME {
+ IgnoredClass getInnerClassOne();
+ NotIgnoredClass getInnerClassTwo();
+ Map<String, IgnoredClass> getInnerClassThree();
+ Map<String, NotIgnoredClass> getInnerClassFour();
+
+ @Immutable.Ignore
+ final class IgnoredClass {
+ public String innerField;
+ }
+
+ final class NotIgnoredClass {
+ public String innerField;
+ }
+ }
+ """.trimIndent()
+ ), errors = listOf(
+ nonInterfaceReturnFailure(line = 9),
+ nonInterfaceReturnFailure(line = 11, prefix = "Value NotIgnoredClass"),
+ classNotImmutableFailure(line = 18, className = "NotIgnoredClass"),
+ nonInterfaceClassFailure(line = 18),
+ memberNotMethodFailure(line = 19),
+ )
+ )
+
private fun test(
source: JavaFileObject,
errors: List<CompilationError>,