// Copyright 2014 Google Inc. 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.base.Joiner; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableSet; import com.google.devtools.build.docgen.DocgenConsts.RuleType; import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider; import com.google.devtools.build.lib.packages.Attribute; import com.google.devtools.build.lib.packages.RuleClass; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.TreeSet; /** * A class representing the documentation of a rule along with some meta-data. The sole ruleName * field is used as a key for comparison, equals and hashcode. * *

The class contains meta information about the rule: *

* *

The class also contains physical information about the documentation, * such as declaring file name and the first line of the raw documentation. This can be useful for * proper error signaling during documentation processing. */ class RuleDocumentation implements Comparable { private final String ruleName; private final RuleType ruleType; private final String ruleFamily; private final String htmlDocumentation; // Store these information for error messages private final int startLineCount; private final String fileName; private final ImmutableSet flags; private final Map docVariables = new HashMap<>(); // Only one attribute per attributeName is allowed private final Set attributes = new TreeSet<>(); private final ConfiguredRuleClassProvider ruleClassProvider; /** * 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 flags, 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; } /** * Returns the name of the rule. */ String getRuleName() { return ruleName; } /** * Returns the type of the rule */ RuleType getRuleType() { return ruleType; } /** * Returns the family of the rule. The family is usually the corresponding programming language, * except for rules independent of language, such as genrule. E.g. the family of the java_library * rule is 'JAVA', the family of genrule is 'GENERAL'. */ String getRuleFamily() { return ruleFamily; } /** * Returns the number of first line of the rule documentation in its declaration file. */ int getStartLineCount() { return startLineCount; } /** * Returns true if this rule documentation has the parameter flag. */ boolean hasFlag(String flag) { return flags.contains(flag); } /** * Returns true if this rule applies to a specific programming language (e.g. java_library), * returns false if it is a generic action (e.g. genrule, filegroup). * * A rule is considered to be specific to a programming language by default. Generic rules have * to be marked with the flag GENERIC_RULE in their #BLAZE_RULE definition. */ boolean isLanguageSpecific() { return !flags.contains(DocgenConsts.FLAG_GENERIC_RULE); } /** * Adds a variable name - value pair to the documentation to be substituted. */ void addDocVariable(String varName, String value) { docVariables.put(varName, value); } /** * Adds a rule documentation attribute to this rule documentation. */ void addAttribute(RuleDocumentationAttribute attribute) { attributes.add(attribute); } /** * Returns the html documentation in the exact format it should be written into the Build * Encyclopedia (expanding variables). */ String getHtmlDocumentation() { String expandedDoc = htmlDocumentation; // Substituting variables for (Entry docVariable : docVariables.entrySet()) { expandedDoc = expandedDoc.replace("${" + docVariable.getKey() + "}", expandBuiltInVariables(docVariable.getKey(), docVariable.getValue())); } expandedDoc = expandedDoc.replace("${" + DocgenConsts.VAR_ATTRIBUTE_SIGNATURE + "}", generateAttributeSignatures()); expandedDoc = expandedDoc.replace("${" + DocgenConsts.VAR_ATTRIBUTE_DEFINITION + "}", generateAttributeDefinitions(true)); return String.format("

%s

\n\n%s", ruleName, getDeprecatedString(hasFlag(DocgenConsts.FLAG_DEPRECATED)), ruleName, expandedDoc); } /** * Returns the documentation of the rule in a form which is printable on the command line. */ String getCommandLineDocumentation() { return "\n" + DocgenConsts.toCommandLineFormat(htmlDocumentation); } /** * Returns the html code of the attribute definitions without the header and name * attribute of the rule. */ String generateAttributeDefinitions() { return generateAttributeDefinitions(false); } private String generateAttributeDefinitions(boolean generateNameAndHeader) { StringBuilder sb = new StringBuilder(); if (generateNameAndHeader){ String nameExtraHtmlDoc = docVariables.containsKey(DocgenConsts.VAR_NAME) ? docVariables.get(DocgenConsts.VAR_NAME) : ""; sb.append(String.format(Joiner.on('\n').join(new String[] { "

Arguments

", "