Display annotations and annotation values when they are requested

This exports the annotation field names and values, as well as displays them
in the generated output whenever the annotation is chosen with the
"-showAnnotation" argument to doclava

Bug: 8440225
Change-Id: Iea71d3af2593e5067f4b1b1fbd3463539609f676
diff --git a/res/assets/templates/macros.cs b/res/assets/templates/macros.cs
index eed8737..16711c4 100644
--- a/res/assets/templates/macros.cs
+++ b/res/assets/templates/macros.cs
@@ -144,6 +144,41 @@
   /if ?><?cs
 /def ?>
 
+
+<?cs
+# Show a list of annotations associated with obj
+#
+# pre is an HTML string to start the list.
+# between is an HTML string to include between each successive element.
+# post is an HTML string to end the list.
+# for example, call:show_annotations_list(cl, "<p>Annotations: ", "<br />", "</p>")
+# ?><?cs
+def:show_annotations_list(obj, pre, between, post) ?><?cs
+  each:anno = obj.showAnnotations ?><?cs
+    if:first(anno) ?><?cs
+      var:pre ?><?cs
+    /if ?>
+    @<?cs var:anno.type.label ?>(<?cs
+    each:elem = anno.elementValues ?><?cs
+      var:elem.name ?>&nbsp;=&nbsp;<?cs
+      var:elem.value ?><?cs
+      if:last(elem) == 0 ?>, <?cs
+      /if ?><?cs
+    /each ?>)<?cs
+    if:last(anno) == 0 ?><?cs
+      var:between ?><?cs
+    /if ?><?cs
+    if:last(anno) ?><?cs
+      var:post ?><?cs
+    /if ?><?cs
+  /each ?><?cs
+/def ?>
+
+<?cs # Show a comma-separated list of annotations associated with obj ?><?cs
+def:show_simple_annotations_list(obj, pre, post) ?><?cs
+  call:show_annotations_list(obj, pre, ", ", post) ?><?cs
+/def ?>
+
 <?cs # Show the red box with the deprecated warning ?><?cs 
 def:deprecated_warning(obj) ?><?cs
   if:subcount(obj.deprecated) ?><p>
diff --git a/src/com/google/doclava/AnnotationInstanceInfo.java b/src/com/google/doclava/AnnotationInstanceInfo.java
index c72ca9a..d353426 100644
--- a/src/com/google/doclava/AnnotationInstanceInfo.java
+++ b/src/com/google/doclava/AnnotationInstanceInfo.java
@@ -120,13 +120,27 @@
       return allResolved;
   }
 
+  /**
+   * Convert the specified list of {@code AnnotationInstanceInfo} into an HDF-formatted list, and
+   * add the HDF list into the specified {@code Data}.
+   */
   public static void makeLinkListHDF(Data data, String base, AnnotationInstanceInfo[] annotations) {
     if (annotations == null) return;
 
     final int N = annotations.length;
     for (int i = 0; i < N; i++) {
       AnnotationInstanceInfo aii = annotations[i];
-      aii.type().makeShortDescrHDF(data, base + "." + i);
+      final String aiiBase = base + "." + i;
+
+      // Serialize data about the annotation element values
+      for (int elemIdx = 0; elemIdx < aii.elementValues().size(); ++elemIdx) {
+        final String elemBase = aiiBase + ".elementValues." + elemIdx;
+        final AnnotationValueInfo value = aii.elementValues().get(elemIdx);
+        data.setValue(elemBase + ".name", value.element().name());
+        data.setValue(elemBase + ".value", value.valueString());
+      }
+
+      aii.type().makeShortDescrHDF(data, aiiBase);
     }
   }
 
diff --git a/src/com/google/doclava/MemberInfo.java b/src/com/google/doclava/MemberInfo.java
index 76087eb..da11360 100644
--- a/src/com/google/doclava/MemberInfo.java
+++ b/src/com/google/doclava/MemberInfo.java
@@ -143,9 +143,20 @@
     return mContainingClass;
   }
 
+  /**
+   * Returns {@code true} if the member's scope is above the minimum requested scope passed to
+   * Doclava, <emph>or</emph> if the member is tagged with an annotation which was specified in a
+   * "-showAnnotation" argument to Doclava
+   */
   public boolean checkLevel() {
-    return Doclava.checkLevel(mIsPublic, mIsProtected, mIsPackagePrivate, mIsPrivate,
-        isHiddenOrRemoved());
+    if (Doclava.checkLevel(mIsPublic, mIsProtected, mIsPackagePrivate, mIsPrivate,
+        isHiddenOrRemoved())) {
+      return true;
+    } else if (mShowAnnotations != null && !mShowAnnotations.isEmpty()) {
+      return true;
+    }
+
+    return false;
   }
 
   public String kind() {