aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main
diff options
context:
space:
mode:
authorGravatar David Chen <dzc@google.com>2016-02-24 22:17:42 +0000
committerGravatar Philipp Wollermann <philwo@google.com>2016-02-25 14:13:22 +0000
commitac13e22630ef3bd6cc67cda14633f976b5ffc044 (patch)
tree70d0ff60ab00b93128ec73fdcf495c72b6898115 /src/main
parent6e30521e0d230ba8138cb8bbe3bf3f4fb4fbfa60 (diff)
Add syntax for referencing docs in other rule families.
This CL implements a new `${link rule.attribute}` syntax which can be used to reference the documentation of rules and attributes of other rule families. For example, `${link cc_library.deps}` will generate a link to the documentation for the `deps` attribute of the `cc_library` rule. Similarly, this syntax can also be used to reference sections of static documentation, for example `${link common-definitions.label-expansion}`. -- MOS_MIGRATED_REVID=115492361
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/com/google/devtools/build/docgen/BuildDocCollector.java15
-rw-r--r--src/main/java/com/google/devtools/build/docgen/DocgenConsts.java10
-rw-r--r--src/main/java/com/google/devtools/build/docgen/RuleDocumentation.java52
-rw-r--r--src/main/java/com/google/devtools/build/docgen/RuleDocumentationAttribute.java35
-rw-r--r--src/main/java/com/google/devtools/build/docgen/RuleLinkExpander.java106
-rw-r--r--src/main/java/com/google/devtools/build/docgen/SourceFileReader.java2
6 files changed, 195 insertions, 25 deletions
diff --git a/src/main/java/com/google/devtools/build/docgen/BuildDocCollector.java b/src/main/java/com/google/devtools/build/docgen/BuildDocCollector.java
index 72de708448..7bb4f71993 100644
--- a/src/main/java/com/google/devtools/build/docgen/BuildDocCollector.java
+++ b/src/main/java/com/google/devtools/build/docgen/BuildDocCollector.java
@@ -122,10 +122,25 @@ public class BuildDocCollector {
}
processAttributeDocs(ruleDocEntries.values(), attributeDocEntries);
+ RuleLinkExpander expander = buildRuleLinkExpander(ruleDocEntries.values());
+ for (RuleDocumentation rule : ruleDocEntries.values()) {
+ rule.setRuleLinkExpander(expander);
+ }
return ruleDocEntries;
}
/**
+ * Generates an index mapping rule name to its normalized rule family name.
+ */
+ private RuleLinkExpander buildRuleLinkExpander(Iterable<RuleDocumentation> rules) {
+ Map<String, String> index = new HashMap<>();
+ for (RuleDocumentation rule : rules) {
+ index.put(rule.getRuleName(), RuleFamily.normalize(rule.getRuleFamily()));
+ }
+ return new RuleLinkExpander(index);
+ }
+
+ /**
* Go through all attributes of all documented rules and search the best attribute documentation
* if exists. The best documentation is the closest documentation in the ancestor graph. E.g. if
* java_library.deps documented in $rule and $java_rule then the one in $java_rule is going to
diff --git a/src/main/java/com/google/devtools/build/docgen/DocgenConsts.java b/src/main/java/com/google/devtools/build/docgen/DocgenConsts.java
index c0e2639b8d..d50a29971b 100644
--- a/src/main/java/com/google/devtools/build/docgen/DocgenConsts.java
+++ b/src/main/java/com/google/devtools/build/docgen/DocgenConsts.java
@@ -93,6 +93,16 @@ public class DocgenConsts {
}
/**
+ * Reference to another rule or Build Encyclopedia section.
+ *
+ * <p>The format of a link reference is rule.attribute (e.g. cc_library.deps). In the case of
+ * static pages such as common definitions the format is page.heading
+ * (e.g. common-definitions.label-expansion).
+ */
+ public static final Pattern BLAZE_RULE_LINK = Pattern.compile(
+ "\\$\\{link (([a-z_-]+)(\\.([a-z_-]+))?)\\}");
+
+ /**
* i.e. <!-- #BLAZE_RULE(NAME = RULE_NAME, TYPE = RULE_TYPE, FAMILY = RULE_FAMILY) -->
* i.e. <!-- #BLAZE_RULE(...)[DEPRECATED] -->
*/
diff --git a/src/main/java/com/google/devtools/build/docgen/RuleDocumentation.java b/src/main/java/com/google/devtools/build/docgen/RuleDocumentation.java
index 6da7f41262..2fec7c495a 100644
--- a/src/main/java/com/google/devtools/build/docgen/RuleDocumentation.java
+++ b/src/main/java/com/google/devtools/build/docgen/RuleDocumentation.java
@@ -57,28 +57,29 @@ public class RuleDocumentation implements Comparable<RuleDocumentation> {
private final Set<RuleDocumentationAttribute> attributes = new TreeSet<>();
private final ConfiguredRuleClassProvider ruleClassProvider;
+ private RuleLinkExpander linkExpander;
+
/**
* Creates a RuleDocumentation from the rule's name, type, family and raw html documentation
* (meaning without expanding the variables in the doc).
*/
RuleDocumentation(String ruleName, String ruleType, String ruleFamily,
String htmlDocumentation, int startLineCount, String fileName, ImmutableSet<String> flags,
- ConfiguredRuleClassProvider ruleClassProvider)
- throws BuildEncyclopediaDocException {
+ ConfiguredRuleClassProvider ruleClassProvider) throws BuildEncyclopediaDocException {
Preconditions.checkNotNull(ruleName);
- this.ruleName = ruleName;
- try {
- this.ruleType = RuleType.valueOf(ruleType);
- } catch (IllegalArgumentException e) {
- throw new BuildEncyclopediaDocException(
- fileName, startLineCount, "Invalid rule type " + ruleType);
- }
- this.ruleFamily = ruleFamily;
- this.htmlDocumentation = htmlDocumentation;
- this.startLineCount = startLineCount;
- this.fileName = fileName;
- this.flags = flags;
- this.ruleClassProvider = ruleClassProvider;
+ this.ruleName = ruleName;
+ try {
+ this.ruleType = RuleType.valueOf(ruleType);
+ } catch (IllegalArgumentException e) {
+ throw new BuildEncyclopediaDocException(
+ fileName, startLineCount, "Invalid rule type " + ruleType);
+ }
+ this.ruleFamily = ruleFamily;
+ this.htmlDocumentation = htmlDocumentation;
+ this.startLineCount = startLineCount;
+ this.fileName = fileName;
+ this.flags = flags;
+ this.ruleClassProvider = ruleClassProvider;
}
/**
@@ -165,16 +166,35 @@ public class RuleDocumentation implements Comparable<RuleDocumentation> {
}
/**
+ * Sets the {@link RuleLinkExpander} to be used to expand links in the HTML documentation for
+ * both this RuleDocumentation and all {@link RuleDocumentationAttribute}s associated with this
+ * rule.
+ */
+ public void setRuleLinkExpander(RuleLinkExpander linkExpander) {
+ this.linkExpander = linkExpander;
+ for (RuleDocumentationAttribute attribute : attributes) {
+ attribute.setRuleLinkExpander(linkExpander);
+ }
+ }
+
+ /**
* Returns the html documentation in the exact format it should be written into the Build
* Encyclopedia (expanding variables).
*/
- public String getHtmlDocumentation() {
+ public String getHtmlDocumentation() throws BuildEncyclopediaDocException {
String expandedDoc = htmlDocumentation;
// Substituting variables
for (Entry<String, String> docVariable : docVariables.entrySet()) {
expandedDoc = expandedDoc.replace("${" + docVariable.getKey() + "}",
expandBuiltInVariables(docVariable.getKey(), docVariable.getValue()));
}
+ if (linkExpander != null) {
+ try {
+ expandedDoc = linkExpander.expand(expandedDoc);
+ } catch (IllegalArgumentException e) {
+ throw new BuildEncyclopediaDocException(fileName, startLineCount, e.getMessage());
+ }
+ }
return expandedDoc;
}
diff --git a/src/main/java/com/google/devtools/build/docgen/RuleDocumentationAttribute.java b/src/main/java/com/google/devtools/build/docgen/RuleDocumentationAttribute.java
index 518a2c45c5..b1b60fb1bd 100644
--- a/src/main/java/com/google/devtools/build/docgen/RuleDocumentationAttribute.java
+++ b/src/main/java/com/google/devtools/build/docgen/RuleDocumentationAttribute.java
@@ -60,7 +60,10 @@ public class RuleDocumentationAttribute implements Comparable<RuleDocumentationA
private final String attributeName;
private final String htmlDocumentation;
private final String commonType;
+ // Used to expand rule link references in the attribute documentation.
+ private RuleLinkExpander linkExpander;
private int startLineCnt;
+ private String fileName;
private Set<String> flags;
private Attribute attribute;
@@ -71,7 +74,7 @@ public class RuleDocumentationAttribute implements Comparable<RuleDocumentationA
static RuleDocumentationAttribute create(
String attributeName, String commonType, String htmlDocumentation) {
RuleDocumentationAttribute docAttribute = new RuleDocumentationAttribute(
- null, attributeName, htmlDocumentation, 0, ImmutableSet.<String>of(), commonType);
+ null, attributeName, htmlDocumentation, 0, "", ImmutableSet.<String>of(), commonType);
return docAttribute;
}
@@ -80,14 +83,15 @@ public class RuleDocumentationAttribute implements Comparable<RuleDocumentationA
* defined rule attributes.
*/
static RuleDocumentationAttribute create(Class<? extends RuleDefinition> definitionClass,
- String attributeName, String htmlDocumentation, int startLineCnt, Set<String> flags) {
+ String attributeName, String htmlDocumentation, int startLineCnt, String fileName,
+ Set<String> flags) {
return new RuleDocumentationAttribute(definitionClass, attributeName, htmlDocumentation,
- startLineCnt, flags, null);
+ startLineCnt, fileName, flags, null);
}
private RuleDocumentationAttribute(Class<? extends RuleDefinition> definitionClass,
- String attributeName, String htmlDocumentation, int startLineCnt, Set<String> flags,
- String commonType) {
+ String attributeName, String htmlDocumentation, int startLineCnt, String fileName,
+ Set<String> flags, String commonType) {
Preconditions.checkNotNull(attributeName, "AttributeName must not be null.");
this.definitionClass = definitionClass;
this.attributeName = attributeName;
@@ -119,10 +123,25 @@ public class RuleDocumentationAttribute implements Comparable<RuleDocumentationA
}
/**
- * Returns the raw html documentation of the rule attribute.
+ * Sets the {@link RuleLinkExpander} to be used to expand links in the HTML documentation.
*/
- public String getHtmlDocumentation() {
- return htmlDocumentation;
+ public void setRuleLinkExpander(RuleLinkExpander linkExpander) {
+ this.linkExpander = linkExpander;
+ }
+
+ /**
+ * Returns the html documentation of the rule attribute.
+ */
+ public String getHtmlDocumentation() throws BuildEncyclopediaDocException {
+ String expandedHtmlDoc = htmlDocumentation;
+ if (linkExpander != null) {
+ try {
+ expandedHtmlDoc = linkExpander.expand(expandedHtmlDoc);
+ } catch (IllegalArgumentException e) {
+ throw new BuildEncyclopediaDocException(fileName, startLineCnt, e.getMessage());
+ }
+ }
+ return expandedHtmlDoc;
}
private String getDefaultValue() {
diff --git a/src/main/java/com/google/devtools/build/docgen/RuleLinkExpander.java b/src/main/java/com/google/devtools/build/docgen/RuleLinkExpander.java
new file mode 100644
index 0000000000..8ac8cbc795
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/docgen/RuleLinkExpander.java
@@ -0,0 +1,106 @@
+// Copyright 2014 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package com.google.devtools.build.docgen;
+
+import com.google.common.collect.ImmutableSet;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+
+/**
+ * Helper class used for expanding link references in rule and attribute documentation.
+ *
+ * <p>See {@link com.google.devtools.build.docgen.DocgenConsts.BLAZE_RULE_LINK} for the regex used
+ * to match link references.
+ */
+class RuleLinkExpander {
+ private static final String EXAMPLES_SUFFIX = "_examples";
+ private static final String ARGS_SUFFIX = "_args";
+
+ private static final Set<String> STATIC_PAGES = ImmutableSet.<String>of(
+ "common-definitions",
+ "make-variables",
+ "predefined-python-variables");
+
+ private final Map<String, String> ruleIndex;
+
+ RuleLinkExpander(Map<String, String> ruleIndex) {
+ this.ruleIndex = ruleIndex;
+ }
+
+ private void appendRuleLink(Matcher matcher, StringBuffer sb, String ruleName, String ref) {
+ String ruleFamily = ruleIndex.get(ruleName);
+ String link = ruleFamily + ".html#" + ref;
+ matcher.appendReplacement(sb, Matcher.quoteReplacement(link));
+ }
+
+ /**
+ * Expands all rule references in the input HTML documentation.
+ *
+ * @param htmlDoc The input HTML documentation with ${link foo.bar} references.
+ * @return The HTML documentation with all link references expanded.
+ */
+ public String expand(String htmlDoc) throws IllegalArgumentException {
+ Matcher matcher = DocgenConsts.BLAZE_RULE_LINK.matcher(htmlDoc);
+ StringBuffer sb = new StringBuffer(htmlDoc.length());
+ while (matcher.find()) {
+ // The first capture group matches the entire reference, e.g. "cc_binary.deps".
+ String ref = matcher.group(1);
+ // The second capture group only matches the rule name, e.g. "cc_binary" in "cc_binary.deps".
+ String name = matcher.group(2);
+
+ // The name in the reference is the name of a rule. Get the rule family for the rule and
+ // replace the reference with a link with the form of rule-family.html#rule.attribute. For
+ // example, ${link cc_library.deps} expands to c-cpp.html#cc_library.deps.
+ if (ruleIndex.containsKey(name)) {
+ appendRuleLink(matcher, sb, name, ref);
+ continue;
+ }
+
+ // The name is referencing the examples or arguments of a rule (e.g. "cc_library_args" or
+ // "cc_library_examples"). Strip the suffix and then try matching the name to a rule family.
+ if (name.endsWith(EXAMPLES_SUFFIX) || name.endsWith(ARGS_SUFFIX)) {
+ String ruleName = name.substring(
+ 0, name.indexOf(name.endsWith(EXAMPLES_SUFFIX) ? EXAMPLES_SUFFIX : ARGS_SUFFIX));
+ if (ruleIndex.containsKey(ruleName)) {
+ appendRuleLink(matcher, sb, ruleName, ref);
+ continue;
+ }
+ }
+
+ // The name is not the name of a rule but is the name of a static page, such as
+ // common-definitions. Generate a link to that page, and append the page heading if
+ // specified. For example, ${link common-definitions.label-expansion} expands to
+ // common-definitions.html#label-expansion.
+ if (STATIC_PAGES.contains(name)) {
+ String link = name + ".html";
+ // The fourth capture group matches the attribute name, or page heading, e.g.
+ // "label-expansion" in "common-definitions.label-expansion".
+ String pageHeading = matcher.group(4);
+ if (pageHeading != null) {
+ link = link + "#" + pageHeading;
+ }
+ matcher.appendReplacement(sb, Matcher.quoteReplacement(link));
+ continue;
+ }
+
+ // If the reference does not match any rule or static page, throw an exception.
+ throw new IllegalArgumentException(
+ "link tag does not match any rule or BE page: " + matcher.group());
+ }
+ matcher.appendTail(sb);
+ return sb.toString();
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/docgen/SourceFileReader.java b/src/main/java/com/google/devtools/build/docgen/SourceFileReader.java
index 651b46efc8..78f0b6dae0 100644
--- a/src/main/java/com/google/devtools/build/docgen/SourceFileReader.java
+++ b/src/main/java/com/google/devtools/build/docgen/SourceFileReader.java
@@ -214,7 +214,7 @@ public class SourceFileReader {
// End of a attribute, create RuleDocumentationAttribute object
docAttributes.put(attributeName, RuleDocumentationAttribute.create(
ruleClassProvider.getRuleClassDefinition(ruleName),
- attributeName, sb.toString(), startLineCnt, flags));
+ attributeName, sb.toString(), startLineCnt, javaSourceFilePath, flags));
sb = new StringBuilder();
inBlazeAttributeDocs = false;
}