Add -hideAnnotation parameter to doclava.

Basically this is -showAnnotation, but for the opposite use.
Specifies Java annotations that should be treated the same as "@hide"

Test: Sadly there are no unit tests for Doclava, however, this change
builds and treehugger should ensure that Doclava's existing usage
still works.
Change-Id: I76fe6d74eff2db08f65f992ded0cae9144fc31a1
diff --git a/src/com/google/doclava/AnnotationInstanceInfo.java b/src/com/google/doclava/AnnotationInstanceInfo.java
index d353426..07ffd9d 100644
--- a/src/com/google/doclava/AnnotationInstanceInfo.java
+++ b/src/com/google/doclava/AnnotationInstanceInfo.java
@@ -20,6 +20,7 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 
 public class AnnotationInstanceInfo implements Resolvable {
   private ClassInfo mType;
@@ -146,19 +147,40 @@
 
   /**
    * Get a new list containing the set of annotations that are shared between
-   * the input annotations collection and the names of annotations passed in
-   * the showAnnotations parameter
+   * the input annotations collection and the set of allowed annotations.
    */
-  public static ArrayList<AnnotationInstanceInfo> getShowAnnotationsIntersection(
-          ArrayList<AnnotationInstanceInfo> annotations) {
+  public static ArrayList<AnnotationInstanceInfo> getAnnotationsIntersection(
+          Collection<String> allowedAnnotations,
+          Collection<? extends AnnotationInstanceInfo> allAnnotations) {
     ArrayList<AnnotationInstanceInfo> list = new ArrayList<AnnotationInstanceInfo>();
-    if (annotations != null) {
-      for (AnnotationInstanceInfo info : annotations) {
-        if (Doclava.showAnnotations.contains(info.type().qualifiedName())) {
+    java.util.Objects.requireNonNull(allowedAnnotations);
+    if (allAnnotations != null) {
+      for (AnnotationInstanceInfo info : allAnnotations) {
+        if (allowedAnnotations.contains(info.type().qualifiedName())) {
           list.add(info);
         }
       }
     }
     return list;
   }
+
+  /**
+   * Get a new list containing the set of annotations that are shared between
+   * the input annotations collection and the names of annotations passed in
+   * the showAnnotations parameter
+   */
+  public static ArrayList<AnnotationInstanceInfo> getShowAnnotationsIntersection(
+          Collection<? extends AnnotationInstanceInfo> annotations) {
+    return getAnnotationsIntersection(Doclava.showAnnotations, annotations);
+  }
+
+  /**
+   * Get a new list containing the set of annotations that are shared between
+   * the input annotations collection and the names of annotations passed in
+   * the hideAnnotations parameter
+   */
+  public static ArrayList<AnnotationInstanceInfo> getHideAnnotationsIntersection(
+          Collection<? extends AnnotationInstanceInfo> annotations) {
+    return getAnnotationsIntersection(Doclava.hideAnnotations, annotations);
+  }
 }
diff --git a/src/com/google/doclava/ClassInfo.java b/src/com/google/doclava/ClassInfo.java
index 3a305a2..8be7916 100644
--- a/src/com/google/doclava/ClassInfo.java
+++ b/src/com/google/doclava/ClassInfo.java
@@ -135,6 +135,7 @@
     mIsPrimitive = isPrimitive;
     mAnnotations = annotations;
     mShowAnnotations = AnnotationInstanceInfo.getShowAnnotationsIntersection(annotations);
+    mHideAnnotations = AnnotationInstanceInfo.getHideAnnotationsIntersection(annotations);
   }
 
   public void init(TypeInfo typeInfo, ArrayList<ClassInfo> interfaces,
@@ -167,6 +168,7 @@
     mRealSuperclassType = superclassType;
     mAnnotations = annotations;
     mShowAnnotations = AnnotationInstanceInfo.getShowAnnotationsIntersection(annotations);
+    mHideAnnotations = AnnotationInstanceInfo.getHideAnnotationsIntersection(annotations);
 
     // after providing new methods and new superclass info,clear any cached
     // lists of self + superclass methods, ctors, etc.
@@ -1566,8 +1568,8 @@
   }
 
   /**
-   * @return true if the containing package has @hide comment, or an ancestor
-   * class of this class is hidden, or this class has @hide comment.
+   * @return true if the containing package has @hide comment, a hide annotaion,
+   * or a containing class of this class is hidden.
    */
   public boolean isHiddenImpl() {
     ClassInfo cl = this;
@@ -1579,7 +1581,7 @@
       if (pkg != null && pkg.hasHideComment()) {
         return true;
       }
-      if (cl.comment().isHidden()) {
+      if (cl.comment().isHidden() || cl.hasHideAnnotation()) {
         return true;
       }
       cl = cl.containingClass();
@@ -1631,6 +1633,14 @@
     return mShowAnnotations;
   }
 
+  public boolean hasHideAnnotation() {
+    return mHideAnnotations != null && mHideAnnotations.size() > 0;
+  }
+
+  public ArrayList<AnnotationInstanceInfo> hideAnnotations() {
+    return mHideAnnotations;
+  }
+
   public ArrayList<AnnotationInstanceInfo> getShowAnnotationsIncludeOuters() {
     ArrayList<AnnotationInstanceInfo> allAnnotations = new ArrayList<AnnotationInstanceInfo>();
     ClassInfo cl = this;
@@ -1918,6 +1928,7 @@
   private ClassInfo mSuperclass;
   private ArrayList<AnnotationInstanceInfo> mAnnotations;
   private ArrayList<AnnotationInstanceInfo> mShowAnnotations;
+  private ArrayList<AnnotationInstanceInfo> mHideAnnotations;
   private boolean mSuperclassInit;
   private boolean mDeprecatedKnown;
 
diff --git a/src/com/google/doclava/Doclava.java b/src/com/google/doclava/Doclava.java
index 8753992..bf203a3 100644
--- a/src/com/google/doclava/Doclava.java
+++ b/src/com/google/doclava/Doclava.java
@@ -103,6 +103,7 @@
   public static HashSet<String> knownTags = new HashSet<String>();
   public static FederationTagger federationTagger = new FederationTagger();
   public static Set<String> showAnnotations = new HashSet<String>();
+  public static Set<String> hideAnnotations = new HashSet<String>();
   public static boolean showAnnotationOverridesVisibility = false;
   public static Set<String> hiddenPackages = new HashSet<String>();
   public static boolean includeAssets = true;
@@ -246,6 +247,8 @@
         keepListFile = a[1];
       } else if (a[0].equals("-showAnnotation")) {
         showAnnotations.add(a[1]);
+      } else if (a[0].equals("-hideAnnotation")) {
+        hideAnnotations.add(a[1]);
       } else if (a[0].equals("-showAnnotationOverridesVisibility")) {
         showAnnotationOverridesVisibility = true;
       } else if (a[0].equals("-hidePackage")) {
diff --git a/src/com/google/doclava/MemberInfo.java b/src/com/google/doclava/MemberInfo.java
index 2d4a682..fca7df6 100644
--- a/src/com/google/doclava/MemberInfo.java
+++ b/src/com/google/doclava/MemberInfo.java
@@ -39,6 +39,7 @@
     mKind = kind;
     mAnnotations = annotations;
     mShowAnnotations = AnnotationInstanceInfo.getShowAnnotationsIntersection(annotations);
+    mHideAnnotations = AnnotationInstanceInfo.getHideAnnotationsIntersection(annotations);
   }
 
   public abstract boolean isExecutable();
@@ -48,7 +49,7 @@
     if (mShowAnnotations.size() > 0) {
       return false;
     }
-    return super.isHidden();
+    return super.isHidden() || mHideAnnotations.size() > 0;
   }
 
   @Override
@@ -173,6 +174,10 @@
     return mShowAnnotations;
   }
 
+  public ArrayList<AnnotationInstanceInfo> hideAnnotations() {
+    return mHideAnnotations;
+  }
+
   ClassInfo mContainingClass;
   ClassInfo mRealContainingClass;
   String mName;
@@ -187,5 +192,6 @@
   String mKind;
   private ArrayList<AnnotationInstanceInfo> mAnnotations;
   private ArrayList<AnnotationInstanceInfo> mShowAnnotations;
+  private ArrayList<AnnotationInstanceInfo> mHideAnnotations;
 
 }