Allows Renderer Binary to output aspect information as a markdown output
Depends on CL 259570926.

Work toward https://github.com/bazelbuild/skydoc/issues/196

PiperOrigin-RevId: 260145437
diff --git a/src/test/java/com/google/devtools/build/skydoc/BUILD b/src/test/java/com/google/devtools/build/skydoc/BUILD
index d5b6ecc..7c0c9e2 100644
--- a/src/test/java/com/google/devtools/build/skydoc/BUILD
+++ b/src/test/java/com/google/devtools/build/skydoc/BUILD
@@ -17,6 +17,7 @@
 filegroup(
     name = "test_template_files",
     srcs = [
+        "//src/test/java/com/google/devtools/build/skydoc:test_templates/aspect.vm",
         "//src/test/java/com/google/devtools/build/skydoc:test_templates/func.vm",
         "//src/test/java/com/google/devtools/build/skydoc:test_templates/header.vm",
         "//src/test/java/com/google/devtools/build/skydoc:test_templates/provider.vm",
@@ -247,6 +248,12 @@
     input_file = "testdata/struct_default_value_test/input.bzl",
 )
 
+skydoc_test(
+    name = "aspect_test",
+    golden_file = "testdata/aspect_test/golden.txt",
+    input_file = "testdata/aspect_test/input.bzl",
+)
+
 genrule(
     name = "generate_bzl_test_dep",
     srcs = ["testdata/generated_bzl_test/dep.bzl.tpl"],
diff --git a/src/test/java/com/google/devtools/build/skydoc/MarkdownRendererTest.java b/src/test/java/com/google/devtools/build/skydoc/MarkdownRendererTest.java
index 2bf849a..440d9c1 100644
--- a/src/test/java/com/google/devtools/build/skydoc/MarkdownRendererTest.java
+++ b/src/test/java/com/google/devtools/build/skydoc/MarkdownRendererTest.java
@@ -17,6 +17,7 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import com.google.devtools.build.skydoc.rendering.MarkdownRenderer;
+import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.AspectInfo;
 import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.AttributeInfo;
 import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.AttributeType;
 import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.FunctionParamInfo;
@@ -39,9 +40,15 @@
   private final String providerTemplatePath =
       "com/google/devtools/build/skydoc/test_templates/provider.vm";
   private final String funcTemplatePath = "com/google/devtools/build/skydoc/test_templates/func.vm";
+  private final String aspectTemplatePath =
+      "com/google/devtools/build/skydoc/test_templates/aspect.vm";
   private final MarkdownRenderer renderer =
       new MarkdownRenderer(
-          headerTemplatePath, ruleTemplatePath, providerTemplatePath, funcTemplatePath);
+          headerTemplatePath,
+          ruleTemplatePath,
+          providerTemplatePath,
+          funcTemplatePath,
+          aspectTemplatePath);
 
   @Test
   public void testHeaderStrings() throws IOException {
@@ -150,4 +157,46 @@
                 + "          the first parameter\n"
                 + "        </p>\n");
   }
+
+  @Test
+  public void testAspectStrings() throws IOException {
+    AttributeInfo attrInfo =
+        AttributeInfo.newBuilder()
+            .setName("first")
+            .setDocString("the first attribute")
+            .setTypeValue(AttributeType.STRING.getNumber())
+            .build();
+    AspectInfo aspectInfo =
+        AspectInfo.newBuilder()
+            .setAspectName("my_aspect")
+            .setDocString("This aspect does things.")
+            .addAttribute(attrInfo)
+            .addAspectAttribute("deps")
+            .build();
+
+    assertThat(renderer.render(aspectInfo.getAspectName(), aspectInfo))
+        .isEqualTo(
+            "<a name=\"#my_aspect\"></a>\n"
+                + "\n"
+                + "## my_aspect\n"
+                + "\n"
+                + "<pre>\n"
+                + "null(<a href=\"#null-first\">first</a>)\n"
+                + "</pre>\n"
+                + "\n"
+                + "This aspect does things.\n"
+                + "\n"
+                + "### Aspect Attributes\n"
+                + "\n"
+                + "        <code>deps</code><\n"
+                + "        String; required.\n"
+                + "\n"
+                + "### Attributes\n"
+                + "\n"
+                + "      <code>first</code>\n"
+                + "      String; optional\n"
+                + "        <p>\n"
+                + "          the first attribute\n"
+                + "        </p>\n");
+  }
 }
diff --git a/src/test/java/com/google/devtools/build/skydoc/test_templates/aspect.vm b/src/test/java/com/google/devtools/build/skydoc/test_templates/aspect.vm
new file mode 100644
index 0000000..747f073
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/skydoc/test_templates/aspect.vm
@@ -0,0 +1,32 @@
+<a name="#${aspectName}"></a>
+
+#[[##]]# ${aspectName}
+
+<pre>
+${util.aspectSummary(aspectName, $aspectInfo)}
+</pre>
+
+$aspectInfo.getDocString()
+
+#[[###]]# Aspect Attributes
+
+#if (!$aspectInfo.getAspectAttributeList().isEmpty())
+#foreach ($aspectAttribute in $aspectInfo.getAspectAttributeList())
+        <code>${aspectAttribute}</code><
+        String; required.
+#end
+#end
+
+#[[###]]# Attributes
+
+#if (!$aspectInfo.getAttributeList().isEmpty())
+#foreach ($attribute in $aspectInfo.getAttributeList())
+      <code>${attribute.name}</code>
+      ${util.attributeTypeString($attribute)}; ${util.mandatoryString($attribute)}
+#if (!$attribute.docString.isEmpty())
+        <p>
+          ${attribute.docString.trim()}
+        </p>
+#end
+#end
+#end
diff --git a/src/test/java/com/google/devtools/build/skydoc/testdata/aspect_test/golden.txt b/src/test/java/com/google/devtools/build/skydoc/testdata/aspect_test/golden.txt
new file mode 100644
index 0000000..a4d2093
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/skydoc/testdata/aspect_test/golden.txt
@@ -0,0 +1,148 @@
+<!-- Generated with Stardoc: http://skydoc.bazel.build -->
+
+<a name="#my_aspect_impl"></a>
+
+## my_aspect_impl
+
+<pre>
+my_aspect_impl(<a href="#my_aspect_impl-ctx">ctx</a>)
+</pre>
+
+
+
+### Parameters
+
+<table class="params-table">
+  <colgroup>
+    <col class="col-param" />
+    <col class="col-description" />
+  </colgroup>
+  <tbody>
+    <tr id="my_aspect_impl-ctx">
+      <td><code>ctx</code></td>
+      <td>
+        required.
+      </td>
+    </tr>
+  </tbody>
+</table>
+
+
+<a name="#my_aspect"></a>
+
+## my_aspect
+
+<pre>
+my_aspect(<a href="#my_aspect-name">name</a>, <a href="#my_aspect-first">first</a>, <a href="#my_aspect-second">second</a>)
+</pre>
+
+This is my aspect. It does stuff.
+
+### Aspect Attributes
+
+<table class="params-table">
+  <colgroup>
+    <col class="col-param" />
+    <col class="col-description" />
+  </colgroup>
+  <tbody>
+    <tr id="my_aspect-deps">
+      <td><code>deps</code></td>
+      <td>
+        String; required.
+    <tr id="my_aspect-attr_aspect">
+      <td><code>attr_aspect</code></td>
+      <td>
+        String; required.
+      </td>
+    </tr>
+  </tbody>
+</table>
+
+### Attributes
+
+<table class="params-table">
+  <colgroup>
+    <col class="col-param" />
+    <col class="col-description" />
+  </colgroup>
+  <tbody>
+    <tr id="my_aspect-name">
+      <td><code>name</code></td>
+      <td>
+        <a href="https://bazel.build/docs/build-ref.html#name">Name</a>; required
+        <p>
+          A unique name for this target.
+        </p>
+      </td>
+    </tr>
+    <tr id="my_aspect-first">
+      <td><code>first</code></td>
+      <td>
+        <a href="https://bazel.build/docs/build-ref.html#labels">Label</a>; required
+      </td>
+    </tr>
+    <tr id="my_aspect-second">
+      <td><code>second</code></td>
+      <td>
+        <a href="https://bazel.build/docs/skylark/lib/dict.html">Dictionary: String -> String</a>; required
+      </td>
+    </tr>
+  </tbody>
+</table>
+
+
+<a name="#other_aspect"></a>
+
+## other_aspect
+
+<pre>
+other_aspect(<a href="#other_aspect-name">name</a>, <a href="#other_aspect-third">third</a>)
+</pre>
+
+This is another aspect.
+
+### Aspect Attributes
+
+<table class="params-table">
+  <colgroup>
+    <col class="col-param" />
+    <col class="col-description" />
+  </colgroup>
+  <tbody>
+    <tr id="other_aspect-*">
+      <td><code>*</code></td>
+      <td>
+        String; required.
+      </td>
+    </tr>
+  </tbody>
+</table>
+
+### Attributes
+
+<table class="params-table">
+  <colgroup>
+    <col class="col-param" />
+    <col class="col-description" />
+  </colgroup>
+  <tbody>
+    <tr id="other_aspect-name">
+      <td><code>name</code></td>
+      <td>
+        <a href="https://bazel.build/docs/build-ref.html#name">Name</a>; required
+        <p>
+          A unique name for this target.
+        </p>
+      </td>
+    </tr>
+    <tr id="other_aspect-third">
+      <td><code>third</code></td>
+      <td>
+        Integer; required
+      </td>
+    </tr>
+  </tbody>
+</table>
+
+
diff --git a/src/test/java/com/google/devtools/build/skydoc/testdata/aspect_test/input.bzl b/src/test/java/com/google/devtools/build/skydoc/testdata/aspect_test/input.bzl
new file mode 100644
index 0000000..1ffedb4
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/skydoc/testdata/aspect_test/input.bzl
@@ -0,0 +1,24 @@
+"""The input file for the aspect test"""
+
+def my_aspect_impl(ctx):
+    return []
+
+my_aspect = aspect(
+    implementation = my_aspect_impl,
+    doc = "This is my aspect. It does stuff.",
+    attr_aspects = ["deps", "attr_aspect"],
+    attrs = {
+        "first": attr.label(mandatory = True, allow_single_file = True),
+        "second": attr.string_dict(mandatory = True),
+    },
+)
+
+other_aspect = aspect(
+    implementation = my_aspect_impl,
+    doc = "This is another aspect.",
+    attr_aspects = ["*"],
+    attrs = {
+        "_hidden": attr.string(),
+        "third": attr.int(mandatory = True),
+    },
+)