Add production visibility to @VisibleForTesting
This will be used to let lint and Studio for example
highlight when production/non-test code is accessing
APIs outside the intended visibility scope.
191365: Validate @VisibleForTesting actual visibility
Change-Id: I372171aa1df5b4c8bf3e69f492be92dc60d34391
diff --git a/annotations/src/android/support/annotation/VisibleForTesting.java b/annotations/src/android/support/annotation/VisibleForTesting.java
index 0c893ff..ddce1d5 100644
--- a/annotations/src/android/support/annotation/VisibleForTesting.java
+++ b/annotations/src/android/support/annotation/VisibleForTesting.java
@@ -18,11 +18,57 @@
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.CLASS;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
/**
* Denotes that the class, method or field has its visibility relaxed, so that it is more widely
* visible than otherwise necessary to make code testable.
+ * <p>
+ * You can optionally specify what the visibility <b>should</b> have been if not for
+ * testing; this allows tools to catch unintended access from within production
+ * code.
+ * <p>
+ * Example:
+ * <pre><code>
+ * @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
+ * public String printDiagnostics() { ... }
+ * </code></pre>
+ *
+ * If not specified, the intended visibility is assumed to be private.
*/
@Retention(CLASS)
public @interface VisibleForTesting {
+ /**
+ * The visibility the annotated element would have if it did not need to be made visible for
+ * testing.
+ */
+ @ProductionVisibility
+ int otherwise() default PRIVATE;
+
+ /**
+ * The annotated element would have "private" visibility
+ */
+ int PRIVATE = 2; // Happens to be the same as Modifier.PRIVATE
+
+ /**
+ * The annotated element would have "package private" visibility
+ */
+ int PACKAGE_PRIVATE = 3;
+
+ /**
+ * The annotated element would have "protected" visibility
+ */
+ int PROTECTED = 4; // Happens to be the same as Modifier.PROTECTED
+
+ /**
+ * The annotated element should never be called from production code, only from tests.
+ * <p>
+ * This is equivalent to {@code @RestrictTo.Scope.TESTS}.
+ */
+ int NONE = 5;
+
+ @IntDef({PRIVATE, PACKAGE_PRIVATE, PROTECTED, NONE})
+ @Retention(SOURCE)
+ @interface ProductionVisibility {
+ }
}