Add attribute information to skydoc output
RELNOTES: None.
PiperOrigin-RevId: 204147228
diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeDescriptor.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeDescriptor.java
index 249ee60..3dc7a43 100644
--- a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeDescriptor.java
+++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeDescriptor.java
@@ -21,19 +21,60 @@
* Fake implementation of {@link Descriptor}.
*/
public class FakeDescriptor implements Descriptor {
+ private final Type type;
private final String docString;
+ private final boolean mandatory;
- public FakeDescriptor(String docString) {
+ public FakeDescriptor(Type type, String docString, boolean mandatory) {
+ this.type = type;
this.docString = docString;
+ this.mandatory = mandatory;
+ }
+
+ public Type getType() {
+ return type;
}
public String getDocString() {
return docString;
}
+ public boolean isMandatory() {
+ return mandatory;
+ }
+
@Override
public void repr(SkylarkPrinter printer) {}
- // TODO(cparsons): This class should store information about the attribute definition, for
- // example, the attribute type.
+ /**
+ * Attribute type. For example, an attribute described by attr.label() will be of type LABEL.
+ */
+ public enum Type {
+ INT("Integer"),
+ LABEL("Label"),
+ STRING("String"),
+ STRING_LIST("List of strings"),
+ INT_LIST("List of integers"),
+ LABEL_LIST("List of labels"),
+ BOOLEAN("Boolean"),
+ LICENSE("List of strings"),
+ LABEL_STRING_DICT("Dictionary: Label -> String"),
+ STRING_DICT("Dictionary: String -> String"),
+ STRING_LIST_DICT("Dictionary: String -> List of strings"),
+ OUTPUT("Label"),
+ OUTPUT_LIST("List of labels");
+
+ private final String description;
+
+ Type(String description) {
+ this.description = description;
+ }
+
+ /**
+ * Returns a human-readable string representing this attribute type.
+ */
+ public String getDescription() {
+ return description;
+ }
+ }
}
diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkAttrApi.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkAttrApi.java
index 3dcfaa2..f0ea8a6 100644
--- a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkAttrApi.java
+++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkAttrApi.java
@@ -21,6 +21,7 @@
import com.google.devtools.build.lib.syntax.FuncallExpression;
import com.google.devtools.build.lib.syntax.SkylarkDict;
import com.google.devtools.build.lib.syntax.SkylarkList;
+import com.google.devtools.build.skydoc.fakebuildapi.FakeDescriptor.Type;
/**
* Fake implementation of {@link SkylarkAttrApi}.
@@ -30,13 +31,13 @@
@Override
public Descriptor intAttribute(Integer defaultInt, String doc, Boolean mandatory,
SkylarkList<?> values, FuncallExpression ast, Environment env) throws EvalException {
- return new FakeDescriptor(doc);
+ return new FakeDescriptor(Type.INT, doc, mandatory);
}
@Override
public Descriptor stringAttribute(String defaultString, String doc, Boolean mandatory,
SkylarkList<?> values, FuncallExpression ast, Environment env) throws EvalException {
- return new FakeDescriptor(doc);
+ return new FakeDescriptor(Type.STRING, doc, mandatory);
}
@Override
@@ -44,21 +45,21 @@
Object allowFiles, Object allowSingleFile, Boolean mandatory, SkylarkList<?> providers,
Object allowRules, Boolean singleFile, Object cfg, SkylarkList<?> aspects,
FuncallExpression ast, Environment env) throws EvalException {
- return new FakeDescriptor(doc);
+ return new FakeDescriptor(Type.LABEL, doc, mandatory);
}
@Override
public Descriptor stringListAttribute(Boolean mandatory, Boolean nonEmpty, Boolean allowEmpty,
SkylarkList<?> defaultList, String doc, FuncallExpression ast, Environment env)
throws EvalException {
- return new FakeDescriptor(doc);
+ return new FakeDescriptor(Type.STRING_LIST, doc, mandatory);
}
@Override
public Descriptor intListAttribute(Boolean mandatory, Boolean nonEmpty, Boolean allowEmpty,
SkylarkList<?> defaultList, String doc, FuncallExpression ast, Environment env)
throws EvalException {
- return new FakeDescriptor(doc);
+ return new FakeDescriptor(Type.INT_LIST, doc, mandatory);
}
@Override
@@ -66,7 +67,7 @@
Object allowFiles, Object allowRules, SkylarkList<?> providers, SkylarkList<?> flags,
Boolean mandatory, Boolean nonEmpty, Object cfg, SkylarkList<?> aspects,
FuncallExpression ast, Environment env) throws EvalException {
- return new FakeDescriptor(doc);
+ return new FakeDescriptor(Type.LABEL_LIST, doc, mandatory);
}
@Override
@@ -74,46 +75,46 @@
String doc, Object allowFiles, Object allowRules, SkylarkList<?> providers,
SkylarkList<?> flags, Boolean mandatory, Boolean nonEmpty, Object cfg, SkylarkList<?> aspects,
FuncallExpression ast, Environment env) throws EvalException {
- return new FakeDescriptor(doc);
+ return new FakeDescriptor(Type.LABEL_STRING_DICT, doc, mandatory);
}
@Override
public Descriptor boolAttribute(Boolean defaultO, String doc, Boolean mandatory,
FuncallExpression ast, Environment env) throws EvalException {
- return new FakeDescriptor(doc);
+ return new FakeDescriptor(Type.BOOLEAN, doc, mandatory);
}
@Override
public Descriptor outputAttribute(Object defaultO, String doc, Boolean mandatory,
FuncallExpression ast, Environment env) throws EvalException {
- return new FakeDescriptor(doc);
+ return new FakeDescriptor(Type.OUTPUT, doc, mandatory);
}
@Override
public Descriptor outputListAttribute(Boolean allowEmpty, SkylarkList<?> defaultList, String doc,
Boolean mandatory, Boolean nonEmpty, FuncallExpression ast, Environment env)
throws EvalException {
- return new FakeDescriptor(doc);
+ return new FakeDescriptor(Type.OUTPUT_LIST, doc, mandatory);
}
@Override
public Descriptor stringDictAttribute(Boolean allowEmpty, SkylarkDict<?, ?> defaultO, String doc,
Boolean mandatory, Boolean nonEmpty, FuncallExpression ast, Environment env)
throws EvalException {
- return new FakeDescriptor(doc);
+ return new FakeDescriptor(Type.STRING_DICT, doc, mandatory);
}
@Override
public Descriptor stringListDictAttribute(Boolean allowEmpty, SkylarkDict<?, ?> defaultO,
String doc, Boolean mandatory, Boolean nonEmpty, FuncallExpression ast, Environment env)
throws EvalException {
- return new FakeDescriptor(doc);
+ return new FakeDescriptor(Type.STRING_LIST_DICT, doc, mandatory);
}
@Override
public Descriptor licenseAttribute(Object defaultO, String doc, Boolean mandatory,
FuncallExpression ast, Environment env) throws EvalException {
- return new FakeDescriptor(doc);
+ return new FakeDescriptor(Type.LICENSE, doc, mandatory);
}
@Override
diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkRuleFunctionsApi.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkRuleFunctionsApi.java
index 9b1081b..4260032 100644
--- a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkRuleFunctionsApi.java
+++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkRuleFunctionsApi.java
@@ -14,7 +14,7 @@
package com.google.devtools.build.skydoc.fakebuildapi;
-import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.skylarkbuildapi.FileApi;
@@ -29,10 +29,11 @@
import com.google.devtools.build.lib.syntax.Runtime;
import com.google.devtools.build.lib.syntax.SkylarkDict;
import com.google.devtools.build.lib.syntax.SkylarkList;
+import com.google.devtools.build.skydoc.fakebuildapi.FakeDescriptor.Type;
import com.google.devtools.build.skydoc.rendering.AttributeInfo;
import com.google.devtools.build.skydoc.rendering.RuleInfo;
+import java.util.Comparator;
import java.util.List;
-import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
@@ -44,6 +45,8 @@
*/
public class FakeSkylarkRuleFunctionsApi implements SkylarkRuleFunctionsApi<FileApi> {
+ private static final FakeDescriptor IMPLICIT_NAME_ATTRIBUTE_DESCRIPTOR =
+ new FakeDescriptor(Type.STRING, "A unique name for this rule.", true);
private final List<RuleInfo> ruleInfoList;
/**
@@ -69,20 +72,22 @@
Boolean executionPlatformConstraintsAllowed, SkylarkList<?> execCompatibleWith,
FuncallExpression ast, Environment funcallEnv) throws EvalException {
List<AttributeInfo> attrInfos;
- // TODO(cparsons): Include implicit "Name" attribute.
+ ImmutableMap.Builder<String, FakeDescriptor> attrsMapBuilder = ImmutableMap.builder();
if (attrs != null && attrs != Runtime.NONE) {
SkylarkDict<?, ?> attrsDict = (SkylarkDict<?, ?>) attrs;
- Map<String, FakeDescriptor> attrsMap =
- attrsDict.getContents(String.class, FakeDescriptor.class, "attrs");
- // TODO(cparsons): Include better attribute details. For example, attribute type.
- attrInfos = attrsMap.entrySet().stream()
- .map(entry -> new AttributeInfo(entry.getKey(), entry.getValue().getDocString()))
- .sorted((o1, o2) -> o1.getName().compareTo(o2.getName()))
- .collect(Collectors.toList());
- } else {
- attrInfos = ImmutableList.of();
+ attrsMapBuilder.putAll(attrsDict.getContents(String.class, FakeDescriptor.class, "attrs"));
}
+ attrsMapBuilder.put("name", IMPLICIT_NAME_ATTRIBUTE_DESCRIPTOR);
+ attrInfos = attrsMapBuilder.build().entrySet().stream()
+ .map(entry -> new AttributeInfo(
+ entry.getKey(),
+ entry.getValue().getDocString(),
+ entry.getValue().getType().getDescription(),
+ entry.getValue().isMandatory()))
+ .collect(Collectors.toList());
+ attrInfos.sort(new AttributeNameComparator());
+
RuleDefinitionIdentifier functionIdentifier = new RuleDefinitionIdentifier();
ruleInfoList.add(new RuleInfo(functionIdentifier, ast.getLocation(), doc, attrInfos));
@@ -128,4 +133,22 @@
return this == other;
}
}
+
+ /**
+ * A comparator for {@link AttributeInfo} objects which sorts by attribute name alphabetically,
+ * except that any attribute named "name" is placed first.
+ */
+ private static class AttributeNameComparator implements Comparator<AttributeInfo> {
+
+ @Override
+ public int compare(AttributeInfo o1, AttributeInfo o2) {
+ if (o1.getName().equals("name")) {
+ return o2.getName().equals("name") ? 0 : -1;
+ } else if (o2.getName().equals("name")) {
+ return 1;
+ } else {
+ return o1.getName().compareTo(o2.getName());
+ }
+ }
+ }
}
diff --git a/src/main/java/com/google/devtools/build/skydoc/rendering/AttributeInfo.java b/src/main/java/com/google/devtools/build/skydoc/rendering/AttributeInfo.java
index 8051057..696fe2d 100644
--- a/src/main/java/com/google/devtools/build/skydoc/rendering/AttributeInfo.java
+++ b/src/main/java/com/google/devtools/build/skydoc/rendering/AttributeInfo.java
@@ -21,17 +21,36 @@
private final String name;
private final String docString;
+ private final String typeString;
+ private final boolean mandatory;
- public AttributeInfo(String name, String docString) {
+ public AttributeInfo(String name, String docString, String typeString, boolean mandatory) {
this.name = name;
this.docString = docString;
+ this.typeString = typeString;
+ this.mandatory = mandatory;
}
+ @SuppressWarnings("unused") // Used by markdown template.
public String getName() {
return name;
}
+ @SuppressWarnings("unused") // Used by markdown template.
public String getDocString() {
return docString;
}
+
+ @SuppressWarnings("unused") // Used by markdown template.
+ public String getTypeString() {
+ return typeString;
+ }
+
+ /**
+ * Returns a string representing whether this attribute is required or optional.
+ */
+ @SuppressWarnings("unused") // Used by markdown template.
+ public String getMandatoryString() {
+ return mandatory ? "required" : "optional";
+ }
}
diff --git a/src/main/java/com/google/devtools/build/skydoc/rendering/MarkdownRenderer.java b/src/main/java/com/google/devtools/build/skydoc/rendering/MarkdownRenderer.java
index f9f5495..9632d53 100644
--- a/src/main/java/com/google/devtools/build/skydoc/rendering/MarkdownRenderer.java
+++ b/src/main/java/com/google/devtools/build/skydoc/rendering/MarkdownRenderer.java
@@ -33,7 +33,7 @@
public class MarkdownRenderer {
private static final String TEMPLATE_FILENAME =
- "com/google/devtools/build/skydoc/rendering/templates/test.vm";
+ "com/google/devtools/build/skydoc/rendering/templates/rule.vm";
private final VelocityEngine velocityEngine;
diff --git a/src/main/java/com/google/devtools/build/skydoc/rendering/templates/test.vm b/src/main/java/com/google/devtools/build/skydoc/rendering/templates/rule.vm
similarity index 71%
rename from src/main/java/com/google/devtools/build/skydoc/rendering/templates/test.vm
rename to src/main/java/com/google/devtools/build/skydoc/rendering/templates/rule.vm
index b1600e9..cd5ebaf 100644
--- a/src/main/java/com/google/devtools/build/skydoc/rendering/templates/test.vm
+++ b/src/main/java/com/google/devtools/build/skydoc/rendering/templates/rule.vm
@@ -19,7 +19,14 @@
#foreach ($attribute in $ruleInfo.attributes)
<tr id="#${ruleName}_${attribute.name}">
<td><code>${attribute.name}</code></td>
- <td>${attribute.docString}</td>
+ <td>
+ ${attribute.typeString}; ${attribute.mandatoryString}
+#if (!$attribute.docString.isEmpty())
+ <p>
+ ${attribute.docString}
+ </p>
+#end
+ </td>
</tr>
#end
</tbody>
diff --git a/src/test/java/com/google/devtools/build/skydoc/BUILD b/src/test/java/com/google/devtools/build/skydoc/BUILD
index c12329f..31b365d 100644
--- a/src/test/java/com/google/devtools/build/skydoc/BUILD
+++ b/src/test/java/com/google/devtools/build/skydoc/BUILD
@@ -22,6 +22,7 @@
"//src/main/java/com/google/devtools/build/lib:syntax",
"//src/main/java/com/google/devtools/build/lib/vfs",
"//src/main/java/com/google/devtools/build/skydoc:skydoc_lib",
+ "//src/main/java/com/google/devtools/build/skydoc/fakebuildapi",
"//src/main/java/com/google/devtools/build/skydoc/rendering",
"//src/test/java/com/google/devtools/build/lib:testutil",
"//src/test/java/com/google/devtools/build/lib/skylark:testutil",
@@ -97,3 +98,10 @@
input_file = "testdata/misc_apis_test/input.bzl",
skydoc = "//src/main/java/com/google/devtools/build/skydoc",
)
+
+skydoc_test(
+ name = "attribute_types_test",
+ golden_file = "testdata/attribute_types_test/golden.txt",
+ input_file = "testdata/attribute_types_test/input.bzl",
+ skydoc = "//src/main/java/com/google/devtools/build/skydoc",
+)
diff --git a/src/test/java/com/google/devtools/build/skydoc/SkydocTest.java b/src/test/java/com/google/devtools/build/skydoc/SkydocTest.java
index 89327e3..5bf7a95 100644
--- a/src/test/java/com/google/devtools/build/skydoc/SkydocTest.java
+++ b/src/test/java/com/google/devtools/build/skydoc/SkydocTest.java
@@ -24,6 +24,7 @@
import com.google.devtools.build.lib.syntax.ParserInputSource;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.Path;
+import com.google.devtools.build.skydoc.fakebuildapi.FakeDescriptor.Type;
import com.google.devtools.build.skydoc.rendering.RuleInfo;
import java.io.IOException;
import java.nio.file.Paths;
@@ -67,10 +68,10 @@
" doc = 'This is my rule. It does stuff.',",
" implementation = rule_impl,",
" attrs = {",
- " 'first': attr.label(mandatory=True, allow_files=True, single_file=True),",
- " 'second': attr.string_dict(mandatory=True),",
- " 'third': attr.output(mandatory=True),",
- " 'fourth': attr.bool(default=False, mandatory=False),",
+ " 'a': attr.label(mandatory=True, allow_files=True, single_file=True),",
+ " 'b': attr.string_dict(mandatory=True),",
+ " 'c': attr.output(mandatory=True),",
+ " 'd': attr.bool(default=False, mandatory=False),",
" },",
")");
@@ -88,7 +89,13 @@
assertThat(ruleInfo.getKey()).isEqualTo("my_rule");
assertThat(ruleInfo.getValue().getDocString()).isEqualTo("This is my rule. It does stuff.");
assertThat(getAttrNames(ruleInfo.getValue())).containsExactly(
- "first", "fourth", "second", "third").inOrder();
+ "name", "a", "b", "c", "d").inOrder();
+ assertThat(getAttrTypes(ruleInfo.getValue())).containsExactly(
+ Type.STRING.getDescription(),
+ Type.LABEL.getDescription(),
+ Type.STRING_DICT.getDescription(),
+ Type.LABEL.getDescription(),
+ Type.BOOLEAN.getDescription()).inOrder();
assertThat(unexportedRuleInfos.build()).isEmpty();
}
@@ -97,6 +104,11 @@
.collect(Collectors.toList());
}
+ private static Iterable<String> getAttrTypes(RuleInfo ruleInfo) {
+ return ruleInfo.getAttributes().stream().map(attr -> attr.getTypeString())
+ .collect(Collectors.toList());
+ }
+
@Test
public void testMultipleRuleNames() throws Exception {
scratch.file(
diff --git a/src/test/java/com/google/devtools/build/skydoc/testdata/android_basic_test/golden.txt b/src/test/java/com/google/devtools/build/skydoc/testdata/android_basic_test/golden.txt
index e7c4c5f..a69252b 100644
--- a/src/test/java/com/google/devtools/build/skydoc/testdata/android_basic_test/golden.txt
+++ b/src/test/java/com/google/devtools/build/skydoc/testdata/android_basic_test/golden.txt
@@ -2,7 +2,7 @@
## android_related_rule
<pre>
-android_related_rule(first, fourth, second, third)
+android_related_rule(name, first, fourth, second, third)
</pre>
This rule does android-related things.
@@ -15,21 +15,38 @@
<col class="col-description" />
</colgroup>
<tbody>
+ <tr id="#android_related_rule_name">
+ <td><code>name</code></td>
+ <td>
+ String; required
+ <p>
+ A unique name for this rule.
+ </p>
+ </td>
+ </tr>
<tr id="#android_related_rule_first">
<td><code>first</code></td>
- <td></td>
+ <td>
+ Label; required
+ </td>
</tr>
<tr id="#android_related_rule_fourth">
<td><code>fourth</code></td>
- <td></td>
+ <td>
+ Boolean; optional
+ </td>
</tr>
<tr id="#android_related_rule_second">
<td><code>second</code></td>
- <td></td>
+ <td>
+ Dictionary: String -> String; required
+ </td>
</tr>
<tr id="#android_related_rule_third">
<td><code>third</code></td>
- <td></td>
+ <td>
+ Label; required
+ </td>
</tr>
</tbody>
</table>
diff --git a/src/test/java/com/google/devtools/build/skydoc/testdata/apple_basic_test/golden.txt b/src/test/java/com/google/devtools/build/skydoc/testdata/apple_basic_test/golden.txt
index 882f540..4cbc0be 100644
--- a/src/test/java/com/google/devtools/build/skydoc/testdata/apple_basic_test/golden.txt
+++ b/src/test/java/com/google/devtools/build/skydoc/testdata/apple_basic_test/golden.txt
@@ -2,7 +2,7 @@
## apple_related_rule
<pre>
-apple_related_rule(first, fourth, second, third)
+apple_related_rule(name, first, fourth, second, third)
</pre>
This rule does apple-related things.
@@ -15,21 +15,38 @@
<col class="col-description" />
</colgroup>
<tbody>
+ <tr id="#apple_related_rule_name">
+ <td><code>name</code></td>
+ <td>
+ String; required
+ <p>
+ A unique name for this rule.
+ </p>
+ </td>
+ </tr>
<tr id="#apple_related_rule_first">
<td><code>first</code></td>
- <td></td>
+ <td>
+ Label; required
+ </td>
</tr>
<tr id="#apple_related_rule_fourth">
<td><code>fourth</code></td>
- <td></td>
+ <td>
+ Boolean; optional
+ </td>
</tr>
<tr id="#apple_related_rule_second">
<td><code>second</code></td>
- <td></td>
+ <td>
+ Dictionary: String -> String; required
+ </td>
</tr>
<tr id="#apple_related_rule_third">
<td><code>third</code></td>
- <td></td>
+ <td>
+ Label; required
+ </td>
</tr>
</tbody>
</table>
diff --git a/src/test/java/com/google/devtools/build/skydoc/testdata/attribute_types_test/golden.txt b/src/test/java/com/google/devtools/build/skydoc/testdata/attribute_types_test/golden.txt
new file mode 100644
index 0000000..746e3fe
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/skydoc/testdata/attribute_types_test/golden.txt
@@ -0,0 +1,147 @@
+<a name="#my_rule"></a>
+## my_rule
+
+<pre>
+my_rule(name, a, b, c, d, e, f, g, h, i, j, k, l, m)
+</pre>
+
+This is my rule. It does stuff.
+
+### Attributes
+
+<table class="params-table">
+ <colgroup>
+ <col class="col-param" />
+ <col class="col-description" />
+ </colgroup>
+ <tbody>
+ <tr id="#my_rule_name">
+ <td><code>name</code></td>
+ <td>
+ String; required
+ <p>
+ A unique name for this rule.
+ </p>
+ </td>
+ </tr>
+ <tr id="#my_rule_a">
+ <td><code>a</code></td>
+ <td>
+ Boolean; required
+ <p>
+ Some bool
+ </p>
+ </td>
+ </tr>
+ <tr id="#my_rule_b">
+ <td><code>b</code></td>
+ <td>
+ Integer; required
+ <p>
+ Some int
+ </p>
+ </td>
+ </tr>
+ <tr id="#my_rule_c">
+ <td><code>c</code></td>
+ <td>
+ List of integers; required
+ <p>
+ Some int_list
+ </p>
+ </td>
+ </tr>
+ <tr id="#my_rule_d">
+ <td><code>d</code></td>
+ <td>
+ Label; required
+ <p>
+ Some label
+ </p>
+ </td>
+ </tr>
+ <tr id="#my_rule_e">
+ <td><code>e</code></td>
+ <td>
+ Dictionary: Label -> String; required
+ <p>
+ Some label_keyed_string_dict
+ </p>
+ </td>
+ </tr>
+ <tr id="#my_rule_f">
+ <td><code>f</code></td>
+ <td>
+ List of labels; required
+ <p>
+ Some label_list
+ </p>
+ </td>
+ </tr>
+ <tr id="#my_rule_g">
+ <td><code>g</code></td>
+ <td>
+ List of strings; optional
+ <p>
+ Some license
+ </p>
+ </td>
+ </tr>
+ <tr id="#my_rule_h">
+ <td><code>h</code></td>
+ <td>
+ Label; optional
+ <p>
+ Some output
+ </p>
+ </td>
+ </tr>
+ <tr id="#my_rule_i">
+ <td><code>i</code></td>
+ <td>
+ List of labels; optional
+ <p>
+ Some output_list
+ </p>
+ </td>
+ </tr>
+ <tr id="#my_rule_j">
+ <td><code>j</code></td>
+ <td>
+ String; required
+ <p>
+ Some string
+ </p>
+ </td>
+ </tr>
+ <tr id="#my_rule_k">
+ <td><code>k</code></td>
+ <td>
+ Dictionary: String -> String; required
+ <p>
+ Some string_dict
+ </p>
+ </td>
+ </tr>
+ <tr id="#my_rule_l">
+ <td><code>l</code></td>
+ <td>
+ List of strings; required
+ <p>
+ Some string_list
+ </p>
+ </td>
+ </tr>
+ <tr id="#my_rule_m">
+ <td><code>m</code></td>
+ <td>
+ Dictionary: String -> List of strings; optional
+ <p>
+ Some string_list_dict
+ </p>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+
diff --git a/src/test/java/com/google/devtools/build/skydoc/testdata/attribute_types_test/input.bzl b/src/test/java/com/google/devtools/build/skydoc/testdata/attribute_types_test/input.bzl
new file mode 100644
index 0000000..edcef5f
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/skydoc/testdata/attribute_types_test/input.bzl
@@ -0,0 +1,22 @@
+def my_rule_impl(ctx):
+ return struct()
+
+my_rule = rule(
+ implementation = my_rule_impl,
+ doc = "This is my rule. It does stuff.",
+ attrs = {
+ "a": attr.bool(mandatory = True, doc = "Some bool"),
+ "b": attr.int(mandatory = True, doc = "Some int"),
+ "c": attr.int_list(mandatory = True, doc = "Some int_list"),
+ "d": attr.label(mandatory = True, doc = "Some label"),
+ "e": attr.label_keyed_string_dict(mandatory = True, doc = "Some label_keyed_string_dict"),
+ "f": attr.label_list(mandatory = True, doc = "Some label_list"),
+ "g": attr.license(mandatory = False, doc = "Some license"),
+ "h": attr.output(mandatory = False, doc = "Some output"),
+ "i": attr.output_list(mandatory = False, doc = "Some output_list"),
+ "j": attr.string(mandatory = True, doc = "Some string"),
+ "k": attr.string_dict(mandatory = True, doc = "Some string_dict"),
+ "l": attr.string_list(mandatory = True, doc = "Some string_list"),
+ "m": attr.string_list_dict(mandatory = False, doc = "Some string_list_dict"),
+ },
+)
diff --git a/src/test/java/com/google/devtools/build/skydoc/testdata/cpp_basic_test/golden.txt b/src/test/java/com/google/devtools/build/skydoc/testdata/cpp_basic_test/golden.txt
index 9674b82..ee379d9 100644
--- a/src/test/java/com/google/devtools/build/skydoc/testdata/cpp_basic_test/golden.txt
+++ b/src/test/java/com/google/devtools/build/skydoc/testdata/cpp_basic_test/golden.txt
@@ -2,7 +2,7 @@
## cpp_related_rule
<pre>
-cpp_related_rule(first, fourth, second, third)
+cpp_related_rule(name, first, fourth, second, third)
</pre>
This rule does cpp-related things.
@@ -15,21 +15,38 @@
<col class="col-description" />
</colgroup>
<tbody>
+ <tr id="#cpp_related_rule_name">
+ <td><code>name</code></td>
+ <td>
+ String; required
+ <p>
+ A unique name for this rule.
+ </p>
+ </td>
+ </tr>
<tr id="#cpp_related_rule_first">
<td><code>first</code></td>
- <td></td>
+ <td>
+ Label; required
+ </td>
</tr>
<tr id="#cpp_related_rule_fourth">
<td><code>fourth</code></td>
- <td></td>
+ <td>
+ Boolean; optional
+ </td>
</tr>
<tr id="#cpp_related_rule_second">
<td><code>second</code></td>
- <td></td>
+ <td>
+ Dictionary: String -> String; required
+ </td>
</tr>
<tr id="#cpp_related_rule_third">
<td><code>third</code></td>
- <td></td>
+ <td>
+ Label; required
+ </td>
</tr>
</tbody>
</table>
diff --git a/src/test/java/com/google/devtools/build/skydoc/testdata/java_basic_test/golden.txt b/src/test/java/com/google/devtools/build/skydoc/testdata/java_basic_test/golden.txt
index 7ab9fc0..83f6ea4 100644
--- a/src/test/java/com/google/devtools/build/skydoc/testdata/java_basic_test/golden.txt
+++ b/src/test/java/com/google/devtools/build/skydoc/testdata/java_basic_test/golden.txt
@@ -2,7 +2,7 @@
## java_related_rule
<pre>
-java_related_rule(first, fourth, second, third)
+java_related_rule(name, first, fourth, second, third)
</pre>
This rule does java-related things.
@@ -15,21 +15,38 @@
<col class="col-description" />
</colgroup>
<tbody>
+ <tr id="#java_related_rule_name">
+ <td><code>name</code></td>
+ <td>
+ String; required
+ <p>
+ A unique name for this rule.
+ </p>
+ </td>
+ </tr>
<tr id="#java_related_rule_first">
<td><code>first</code></td>
- <td></td>
+ <td>
+ Label; required
+ </td>
</tr>
<tr id="#java_related_rule_fourth">
<td><code>fourth</code></td>
- <td></td>
+ <td>
+ Boolean; optional
+ </td>
</tr>
<tr id="#java_related_rule_second">
<td><code>second</code></td>
- <td></td>
+ <td>
+ Dictionary: String -> String; required
+ </td>
</tr>
<tr id="#java_related_rule_third">
<td><code>third</code></td>
- <td></td>
+ <td>
+ Label; required
+ </td>
</tr>
</tbody>
</table>
diff --git a/src/test/java/com/google/devtools/build/skydoc/testdata/misc_apis_test/golden.txt b/src/test/java/com/google/devtools/build/skydoc/testdata/misc_apis_test/golden.txt
index 0619f29..810c90b 100644
--- a/src/test/java/com/google/devtools/build/skydoc/testdata/misc_apis_test/golden.txt
+++ b/src/test/java/com/google/devtools/build/skydoc/testdata/misc_apis_test/golden.txt
@@ -2,7 +2,7 @@
## my_rule
<pre>
-my_rule(first, fourth, second, third)
+my_rule(name, first, fourth, second, third)
</pre>
This rule exercises some of the build API.
@@ -15,21 +15,38 @@
<col class="col-description" />
</colgroup>
<tbody>
+ <tr id="#my_rule_name">
+ <td><code>name</code></td>
+ <td>
+ String; required
+ <p>
+ A unique name for this rule.
+ </p>
+ </td>
+ </tr>
<tr id="#my_rule_first">
<td><code>first</code></td>
- <td></td>
+ <td>
+ Label; required
+ </td>
</tr>
<tr id="#my_rule_fourth">
<td><code>fourth</code></td>
- <td></td>
+ <td>
+ Boolean; optional
+ </td>
</tr>
<tr id="#my_rule_second">
<td><code>second</code></td>
- <td></td>
+ <td>
+ Dictionary: String -> String; required
+ </td>
</tr>
<tr id="#my_rule_third">
<td><code>third</code></td>
- <td></td>
+ <td>
+ Label; required
+ </td>
</tr>
</tbody>
</table>
diff --git a/src/test/java/com/google/devtools/build/skydoc/testdata/multiple_files_test/golden.txt b/src/test/java/com/google/devtools/build/skydoc/testdata/multiple_files_test/golden.txt
index 1b2d0a0..771e502 100644
--- a/src/test/java/com/google/devtools/build/skydoc/testdata/multiple_files_test/golden.txt
+++ b/src/test/java/com/google/devtools/build/skydoc/testdata/multiple_files_test/golden.txt
@@ -2,7 +2,7 @@
## my_rule
<pre>
-my_rule(first, second)
+my_rule(name, first, second)
</pre>
This is my rule. It does stuff.
@@ -15,13 +15,29 @@
<col class="col-description" />
</colgroup>
<tbody>
+ <tr id="#my_rule_name">
+ <td><code>name</code></td>
+ <td>
+ String; required
+ <p>
+ A unique name for this rule.
+ </p>
+ </td>
+ </tr>
<tr id="#my_rule_first">
<td><code>first</code></td>
- <td>first my_rule doc string</td>
+ <td>
+ Label; required
+ <p>
+ first my_rule doc string
+ </p>
+ </td>
</tr>
<tr id="#my_rule_second">
<td><code>second</code></td>
- <td></td>
+ <td>
+ Dictionary: String -> String; required
+ </td>
</tr>
</tbody>
</table>
@@ -31,7 +47,7 @@
## other_rule
<pre>
-other_rule(fourth, third)
+other_rule(name, fourth, third)
</pre>
This is another rule.
@@ -44,13 +60,29 @@
<col class="col-description" />
</colgroup>
<tbody>
+ <tr id="#other_rule_name">
+ <td><code>name</code></td>
+ <td>
+ String; required
+ <p>
+ A unique name for this rule.
+ </p>
+ </td>
+ </tr>
<tr id="#other_rule_fourth">
<td><code>fourth</code></td>
- <td></td>
+ <td>
+ Dictionary: String -> String; required
+ </td>
</tr>
<tr id="#other_rule_third">
<td><code>third</code></td>
- <td>third other_rule doc string</td>
+ <td>
+ Label; required
+ <p>
+ third other_rule doc string
+ </p>
+ </td>
</tr>
</tbody>
</table>
@@ -60,7 +92,7 @@
## yet_another_rule
<pre>
-yet_another_rule(fifth)
+yet_another_rule(name, fifth)
</pre>
This is yet another rule
@@ -73,9 +105,20 @@
<col class="col-description" />
</colgroup>
<tbody>
+ <tr id="#yet_another_rule_name">
+ <td><code>name</code></td>
+ <td>
+ String; required
+ <p>
+ A unique name for this rule.
+ </p>
+ </td>
+ </tr>
<tr id="#yet_another_rule_fifth">
<td><code>fifth</code></td>
- <td></td>
+ <td>
+ Label; required
+ </td>
</tr>
</tbody>
</table>
diff --git a/src/test/java/com/google/devtools/build/skydoc/testdata/multiple_rules_test/golden.txt b/src/test/java/com/google/devtools/build/skydoc/testdata/multiple_rules_test/golden.txt
index 7d37f79..3bf31da 100644
--- a/src/test/java/com/google/devtools/build/skydoc/testdata/multiple_rules_test/golden.txt
+++ b/src/test/java/com/google/devtools/build/skydoc/testdata/multiple_rules_test/golden.txt
@@ -2,7 +2,7 @@
## my_rule
<pre>
-my_rule(first, second)
+my_rule(name, first, second)
</pre>
This is my rule. It does stuff.
@@ -15,13 +15,26 @@
<col class="col-description" />
</colgroup>
<tbody>
+ <tr id="#my_rule_name">
+ <td><code>name</code></td>
+ <td>
+ String; required
+ <p>
+ A unique name for this rule.
+ </p>
+ </td>
+ </tr>
<tr id="#my_rule_first">
<td><code>first</code></td>
- <td></td>
+ <td>
+ Label; required
+ </td>
</tr>
<tr id="#my_rule_second">
<td><code>second</code></td>
- <td></td>
+ <td>
+ Dictionary: String -> String; required
+ </td>
</tr>
</tbody>
</table>
@@ -31,7 +44,7 @@
## other_rule
<pre>
-other_rule(fourth, third)
+other_rule(name, fourth, third)
</pre>
This is another rule.
@@ -44,13 +57,26 @@
<col class="col-description" />
</colgroup>
<tbody>
+ <tr id="#other_rule_name">
+ <td><code>name</code></td>
+ <td>
+ String; required
+ <p>
+ A unique name for this rule.
+ </p>
+ </td>
+ </tr>
<tr id="#other_rule_fourth">
<td><code>fourth</code></td>
- <td></td>
+ <td>
+ Dictionary: String -> String; required
+ </td>
</tr>
<tr id="#other_rule_third">
<td><code>third</code></td>
- <td></td>
+ <td>
+ Label; required
+ </td>
</tr>
</tbody>
</table>
@@ -60,7 +86,7 @@
## yet_another_rule
<pre>
-yet_another_rule(fifth)
+yet_another_rule(name, fifth)
</pre>
This is yet another rule
@@ -73,9 +99,20 @@
<col class="col-description" />
</colgroup>
<tbody>
+ <tr id="#yet_another_rule_name">
+ <td><code>name</code></td>
+ <td>
+ String; required
+ <p>
+ A unique name for this rule.
+ </p>
+ </td>
+ </tr>
<tr id="#yet_another_rule_fifth">
<td><code>fifth</code></td>
- <td></td>
+ <td>
+ Label; required
+ </td>
</tr>
</tbody>
</table>
diff --git a/src/test/java/com/google/devtools/build/skydoc/testdata/simple_test/golden.txt b/src/test/java/com/google/devtools/build/skydoc/testdata/simple_test/golden.txt
index d86c0c7..b9f8cec 100644
--- a/src/test/java/com/google/devtools/build/skydoc/testdata/simple_test/golden.txt
+++ b/src/test/java/com/google/devtools/build/skydoc/testdata/simple_test/golden.txt
@@ -2,7 +2,7 @@
## my_rule
<pre>
-my_rule(first, fourth, second, third)
+my_rule(name, first, fourth, second, third)
</pre>
This is my rule. It does stuff.
@@ -15,21 +15,44 @@
<col class="col-description" />
</colgroup>
<tbody>
+ <tr id="#my_rule_name">
+ <td><code>name</code></td>
+ <td>
+ String; required
+ <p>
+ A unique name for this rule.
+ </p>
+ </td>
+ </tr>
<tr id="#my_rule_first">
<td><code>first</code></td>
- <td>first doc string</td>
+ <td>
+ Label; required
+ <p>
+ first doc string
+ </p>
+ </td>
</tr>
<tr id="#my_rule_fourth">
<td><code>fourth</code></td>
- <td>fourth doc string</td>
+ <td>
+ Boolean; optional
+ <p>
+ fourth doc string
+ </p>
+ </td>
</tr>
<tr id="#my_rule_second">
<td><code>second</code></td>
- <td></td>
+ <td>
+ Dictionary: String -> String; required
+ </td>
</tr>
<tr id="#my_rule_third">
<td><code>third</code></td>
- <td></td>
+ <td>
+ Label; required
+ </td>
</tr>
</tbody>
</table>
diff --git a/src/test/java/com/google/devtools/build/skydoc/testdata/unknown_name_test/golden.txt b/src/test/java/com/google/devtools/build/skydoc/testdata/unknown_name_test/golden.txt
index 44040ee..4f78cdf 100644
--- a/src/test/java/com/google/devtools/build/skydoc/testdata/unknown_name_test/golden.txt
+++ b/src/test/java/com/google/devtools/build/skydoc/testdata/unknown_name_test/golden.txt
@@ -2,7 +2,7 @@
## <unknown name>
<pre>
-<unknown name>(first, fourth, second, third)
+<unknown name>(name, first, fourth, second, third)
</pre>
@@ -15,21 +15,38 @@
<col class="col-description" />
</colgroup>
<tbody>
+ <tr id="#<unknown name>_name">
+ <td><code>name</code></td>
+ <td>
+ String; required
+ <p>
+ A unique name for this rule.
+ </p>
+ </td>
+ </tr>
<tr id="#<unknown name>_first">
<td><code>first</code></td>
- <td></td>
+ <td>
+ Label; required
+ </td>
</tr>
<tr id="#<unknown name>_fourth">
<td><code>fourth</code></td>
- <td></td>
+ <td>
+ Boolean; optional
+ </td>
</tr>
<tr id="#<unknown name>_second">
<td><code>second</code></td>
- <td></td>
+ <td>
+ Dictionary: String -> String; required
+ </td>
</tr>
<tr id="#<unknown name>_third">
<td><code>third</code></td>
- <td></td>
+ <td>
+ Label; required
+ </td>
</tr>
</tbody>
</table>