aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/docgen/BuildEncyclopediaProcessor.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/google/devtools/build/docgen/BuildEncyclopediaProcessor.java')
-rw-r--r--src/main/java/com/google/devtools/build/docgen/BuildEncyclopediaProcessor.java210
1 files changed, 30 insertions, 180 deletions
diff --git a/src/main/java/com/google/devtools/build/docgen/BuildEncyclopediaProcessor.java b/src/main/java/com/google/devtools/build/docgen/BuildEncyclopediaProcessor.java
index 4100b1daa0..4990d97c08 100644
--- a/src/main/java/com/google/devtools/build/docgen/BuildEncyclopediaProcessor.java
+++ b/src/main/java/com/google/devtools/build/docgen/BuildEncyclopediaProcessor.java
@@ -11,13 +11,12 @@
// 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.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.LinkedListMultimap;
@@ -26,16 +25,11 @@ import com.google.common.collect.Ordering;
import com.google.common.collect.Sets;
import com.google.devtools.build.docgen.DocgenConsts.RuleType;
import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
-import com.google.devtools.build.lib.analysis.RuleDefinition;
-import com.google.devtools.build.lib.packages.Attribute;
import com.google.devtools.build.lib.packages.RuleClass;
-import java.io.BufferedWriter;
import java.io.File;
-import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -43,9 +37,8 @@ import java.util.TreeMap;
import java.util.TreeSet;
/**
- * A class to assemble documentation for the Build Encyclopedia. The
- * program parses the documentation fragments of rule-classes and
- * generates the html format documentation.
+ * A class to assemble documentation for the Build Encyclopedia. This class uses
+ * {@link BuildDocCollector} to extract documentation fragments from rule classes.
*/
public class BuildEncyclopediaProcessor {
private static final Predicate<String> RULE_WORTH_DOCUMENTING = new Predicate<String>() {
@@ -73,118 +66,23 @@ public class BuildEncyclopediaProcessor {
public void generateDocumentation(String[] inputDirs, String outputRootDir)
throws BuildEncyclopediaDocException, IOException {
File buildEncyclopediaPath = setupDirectories(outputRootDir);
- try (BufferedWriter bw = new BufferedWriter(new FileWriter(buildEncyclopediaPath))) {
- bw.write(DocgenConsts.HEADER_COMMENT);
- bw.write("\n"); // for the benefit of the block-beginning comment at the top of the template
- Map<String, RuleDocumentation> ruleDocEntries = collectAndProcessRuleDocs(inputDirs, false);
- warnAboutUndocumentedRules(
- Sets.difference(ruleClassProvider.getRuleClassMap().keySet(), ruleDocEntries.keySet()));
- writeRuleClassDocs(ruleDocEntries.values(), bw);
+ Page page = TemplateEngine.newPage(
+ "com/google/devtools/build/docgen/templates/build-encyclopedia.vm");
- bw.write("\n"); // for the benefit of the block-beginning comment at the top of the template
- bw.write(SourceFileReader.readTemplateContents(DocgenConsts.FOOTER_TEMPLATE));
- }
+ BuildDocCollector collector = new BuildDocCollector(ruleClassProvider, false);
+ Map<String, RuleDocumentation> ruleDocEntries = collector.collect(inputDirs);
+ warnAboutUndocumentedRules(
+ Sets.difference(ruleClassProvider.getRuleClassMap().keySet(), ruleDocEntries.keySet()));
+ writeRuleClassDocs(ruleDocEntries.values(), page);
+ page.write(buildEncyclopediaPath);
}
- /**
- * Collects all the rule and attribute documentation present in inputDirs, integrates the
- * attribute documentation in the rule documentation and returns the rule documentation.
- */
- public Map<String, RuleDocumentation> collectAndProcessRuleDocs(String[] inputDirs,
- boolean printMessages) throws BuildEncyclopediaDocException, IOException {
- // RuleDocumentations are generated in order (based on rule type then alphabetically).
- // The ordering is also used to determine in which rule doc the common attribute docs are
- // generated (they are generated at the first appearance).
- Map<String, RuleDocumentation> ruleDocEntries = new TreeMap<>();
- // RuleDocumentationAttribute objects equal based on attributeName so they have to be
- // collected in a List instead of a Set.
- ListMultimap<String, RuleDocumentationAttribute> attributeDocEntries =
- LinkedListMultimap.create();
-
- // Map of rule class name to file that defined it.
- Map<String, File> ruleClassFiles = new HashMap<>();
-
- // Set of files already processed. The same file may be encountered multiple times because
- // directories are processed recursively, and an input directory may be a subdirectory of
- // another one.
- Set<File> processedFiles = new HashSet<>();
-
- for (String inputDir : inputDirs) {
- if (printMessages) {
- System.out.println(" Processing input directory: " + inputDir);
- }
- int ruleNum = ruleDocEntries.size();
- collectDocs(processedFiles, ruleClassFiles, ruleDocEntries, attributeDocEntries,
- new File(inputDir));
- if (printMessages) {
- System.out.println(
- " " + (ruleDocEntries.size() - ruleNum) + " rule documentations found.");
- }
- }
-
- processAttributeDocs(ruleDocEntries.values(), attributeDocEntries);
- return ruleDocEntries;
- }
-
- /**
- * 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
- * apply since it's a closer ancestor of java_library.
- */
- private void processAttributeDocs(Iterable<RuleDocumentation> ruleDocEntries,
- ListMultimap<String, RuleDocumentationAttribute> attributeDocEntries)
- throws BuildEncyclopediaDocException {
- for (RuleDocumentation ruleDoc : ruleDocEntries) {
- RuleClass ruleClass = ruleClassProvider.getRuleClassMap().get(ruleDoc.getRuleName());
- if (ruleClass != null) {
- if (ruleClass.isDocumented()) {
- Class<? extends RuleDefinition> ruleDefinition =
- ruleClassProvider.getRuleClassDefinition(ruleDoc.getRuleName());
- for (Attribute attribute : ruleClass.getAttributes()) {
- String attrName = attribute.getName();
- List<RuleDocumentationAttribute> attributeDocList =
- attributeDocEntries.get(attrName);
- if (attributeDocList != null) {
- // There are attribute docs for this attribute.
- // Search the closest one in the ancestor graph.
- // Note that there can be only one 'closest' attribute since we forbid multiple
- // inheritance of the same attribute in RuleClass.
- int minLevel = Integer.MAX_VALUE;
- RuleDocumentationAttribute bestAttributeDoc = null;
- for (RuleDocumentationAttribute attributeDoc : attributeDocList) {
- int level = attributeDoc.getDefinitionClassAncestryLevel(ruleDefinition);
- if (level >= 0 && level < minLevel) {
- bestAttributeDoc = attributeDoc;
- minLevel = level;
- }
- }
- if (bestAttributeDoc != null) {
- ruleDoc.addAttribute(bestAttributeDoc);
- // If there is no matching attribute doc try to add the common.
- } else if (ruleDoc.getRuleType().equals(RuleType.BINARY)
- && PredefinedAttributes.BINARY_ATTRIBUTES.containsKey(attrName)) {
- ruleDoc.addAttribute(PredefinedAttributes.BINARY_ATTRIBUTES.get(attrName));
- } else if (ruleDoc.getRuleType().equals(RuleType.TEST)
- && PredefinedAttributes.TEST_ATTRIBUTES.containsKey(attrName)) {
- ruleDoc.addAttribute(PredefinedAttributes.TEST_ATTRIBUTES.get(attrName));
- } else if (PredefinedAttributes.COMMON_ATTRIBUTES.containsKey(attrName)) {
- ruleDoc.addAttribute(PredefinedAttributes.COMMON_ATTRIBUTES.get(attrName));
- }
- }
- }
- }
- } else {
- throw ruleDoc.createException("Can't find RuleClass for " + ruleDoc.getRuleName());
- }
- }
- }
/**
* Categorizes, checks and prints all the rule-class documentations.
*/
- private void writeRuleClassDocs(Iterable<RuleDocumentation> docEntries, BufferedWriter bw)
+ private void writeRuleClassDocs(Iterable<RuleDocumentation> docEntries, Page page)
throws BuildEncyclopediaDocException, IOException {
Set<RuleDocumentation> binaryDocs = new TreeSet<>();
Set<RuleDocumentation> libraryDocs = new TreeSet<>();
@@ -217,20 +115,15 @@ public class BuildEncyclopediaProcessor {
}
}
- bw.write("\n"); // for the benefit of the block-beginning comment at the top of the template
- bw.write(SourceFileReader.readTemplateContents(DocgenConsts.HEADER_TEMPLATE,
- generateBEHeaderMapping(docEntries)));
+ renderBeHeader(docEntries, page);
- Map<String, String> sectionMapping = ImmutableMap.of(
- DocgenConsts.VAR_SECTION_BINARY, getRuleDocs(binaryDocs),
- DocgenConsts.VAR_SECTION_LIBRARY, getRuleDocs(libraryDocs),
- DocgenConsts.VAR_SECTION_TEST, getRuleDocs(testDocs),
- DocgenConsts.VAR_SECTION_OTHER, getRuleDocs(otherDocs));
- bw.write("\n"); // for the benefit of the block-beginning comment at the top of the template
- bw.write(SourceFileReader.readTemplateContents(DocgenConsts.BODY_TEMPLATE, sectionMapping));
+ page.add(DocgenConsts.VAR_SECTION_BINARY, getRuleDocs(binaryDocs));
+ page.add(DocgenConsts.VAR_SECTION_LIBRARY, getRuleDocs(libraryDocs));
+ page.add(DocgenConsts.VAR_SECTION_TEST, getRuleDocs(testDocs));
+ page.add(DocgenConsts.VAR_SECTION_OTHER, getRuleDocs(otherDocs));
}
- private Map<String, String> generateBEHeaderMapping(Iterable<RuleDocumentation> docEntries)
+ private void renderBeHeader(Iterable<RuleDocumentation> docEntries, Page page)
throws BuildEncyclopediaDocException {
// Separate rule families into language-specific and generic ones.
Set<String> languageSpecificRuleFamilies = new TreeSet<>();
@@ -266,18 +159,18 @@ public class BuildEncyclopediaProcessor {
}
otherRulesTable = sb.toString();
}
-
- return new ImmutableMap.Builder<String, String>()
- .put(DocgenConsts.VAR_LANG_SPECIFIC_HEADER_TABLE, languageSpecificTable)
- .put(DocgenConsts.VAR_OTHER_RULES_HEADER_TABLE, otherRulesTable)
- .put(DocgenConsts.VAR_COMMON_ATTRIBUTE_DEFINITION, generateCommonAttributeDocs(
- PredefinedAttributes.COMMON_ATTRIBUTES, DocgenConsts.COMMON_ATTRIBUTES))
- .put(DocgenConsts.VAR_TEST_ATTRIBUTE_DEFINITION, generateCommonAttributeDocs(
- PredefinedAttributes.TEST_ATTRIBUTES, DocgenConsts.TEST_ATTRIBUTES))
- .put(DocgenConsts.VAR_BINARY_ATTRIBUTE_DEFINITION, generateCommonAttributeDocs(
- PredefinedAttributes.BINARY_ATTRIBUTES, DocgenConsts.BINARY_ATTRIBUTES))
- .put(DocgenConsts.VAR_LEFT_PANEL, generateLeftNavigationPanel(docEntries))
- .build();
+ page.add(DocgenConsts.VAR_LANG_SPECIFIC_HEADER_TABLE, languageSpecificTable);
+ page.add(DocgenConsts.VAR_OTHER_RULES_HEADER_TABLE, otherRulesTable);
+ page.add(DocgenConsts.VAR_COMMON_ATTRIBUTE_DEFINITION,
+ generateCommonAttributeDocs(
+ PredefinedAttributes.COMMON_ATTRIBUTES, DocgenConsts.COMMON_ATTRIBUTES));
+ page.add(DocgenConsts.VAR_TEST_ATTRIBUTE_DEFINITION,
+ generateCommonAttributeDocs(
+ PredefinedAttributes.TEST_ATTRIBUTES, DocgenConsts.TEST_ATTRIBUTES));
+ page.add(DocgenConsts.VAR_BINARY_ATTRIBUTE_DEFINITION,
+ generateCommonAttributeDocs(
+ PredefinedAttributes.BINARY_ATTRIBUTES, DocgenConsts.BINARY_ATTRIBUTES));
+ page.add(DocgenConsts.VAR_LEFT_PANEL, generateLeftNavigationPanel(docEntries));
}
/**
@@ -398,49 +291,6 @@ public class BuildEncyclopediaProcessor {
return sb.toString();
}
- /**
- * Goes through all the html files and subdirs under inputPath and collects the rule
- * and attribute documentations using the ruleDocEntries and attributeDocEntries variable.
- */
- public void collectDocs(
- Set<File> processedFiles,
- Map<String, File> ruleClassFiles,
- Map<String, RuleDocumentation> ruleDocEntries,
- ListMultimap<String, RuleDocumentationAttribute> attributeDocEntries,
- File inputPath) throws BuildEncyclopediaDocException, IOException {
- if (processedFiles.contains(inputPath)) {
- return;
- }
-
- if (inputPath.isFile()) {
- if (DocgenConsts.JAVA_SOURCE_FILE_SUFFIX.apply(inputPath.getName())) {
- SourceFileReader sfr = new SourceFileReader(
- ruleClassProvider, inputPath.getAbsolutePath());
- sfr.readDocsFromComments();
- for (RuleDocumentation d : sfr.getRuleDocEntries()) {
- String ruleName = d.getRuleName();
- if (ruleDocEntries.containsKey(ruleName)
- && !ruleClassFiles.get(ruleName).equals(inputPath)) {
- System.err.printf("WARNING: '%s' from '%s' overrides value already in map from '%s'\n",
- d.getRuleName(), inputPath, ruleClassFiles.get(ruleName));
- }
- ruleClassFiles.put(ruleName, inputPath);
- ruleDocEntries.put(ruleName, d);
- }
- if (attributeDocEntries != null) {
- // Collect all attribute documentations from this file.
- attributeDocEntries.putAll(sfr.getAttributeDocEntries());
- }
- }
- } else if (inputPath.isDirectory()) {
- for (File childPath : inputPath.listFiles()) {
- collectDocs(processedFiles, ruleClassFiles, ruleDocEntries, attributeDocEntries, childPath);
- }
- }
-
- processedFiles.add(inputPath);
- }
-
private File setupDirectories(String outputRootDir) {
if (outputRootDir != null) {
File outputRootPath = new File(outputRootDir);