Display annotations and annotation values when they are requested
(cherry-picked from commit 6fa3e41df1664e59c13830b012b9be39c2b31cae)

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() {