Internal change
PiperOrigin-RevId: 210729402
diff --git a/src/main/java/com/google/devtools/build/docgen/ApiExporter.java b/src/main/java/com/google/devtools/build/docgen/ApiExporter.java
index 4091322..de98f0d 100644
--- a/src/main/java/com/google/devtools/build/docgen/ApiExporter.java
+++ b/src/main/java/com/google/devtools/build/docgen/ApiExporter.java
@@ -22,17 +22,30 @@
import com.google.devtools.build.docgen.skylark.SkylarkMethodDoc;
import com.google.devtools.build.docgen.skylark.SkylarkModuleDoc;
import com.google.devtools.build.docgen.skylark.SkylarkParamDoc;
+import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
import com.google.devtools.build.lib.util.Classpath.ClassPathException;
+import com.google.devtools.common.options.OptionsParser;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Collections;
import java.util.Map;
/** The main class for the Skylark documentation generator. */
public class ApiExporter {
+ private static ConfiguredRuleClassProvider createRuleClassProvider(String classProvider)
+ throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException,
+ IllegalAccessException {
+ Class<?> providerClass = Class.forName(classProvider);
+ Method createMethod = providerClass.getMethod("create");
+ return (ConfiguredRuleClassProvider) createMethod.invoke(null);
+ }
- private static void appendBuiltins(String builtinsFile) {
- try (BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(builtinsFile))) {
+ private static void appendBuiltins(
+ ProtoFileBuildEncyclopediaProcessor processor, String filename) {
+ try (BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(filename))) {
Builtins.Builder builtins = Builtins.newBuilder();
Map<String, SkylarkModuleDoc> allTypes = SkylarkDocumentationCollector.collectModules();
@@ -58,6 +71,12 @@
type.addField(collectFieldInfo(meth));
}
}
+ // Add native rules to the native type.
+ if (mod.getName().equals("native")) {
+ for (Value.Builder rule : processor.getNativeRules()) {
+ type.addField(rule);
+ }
+ }
builtins.addType(type);
// Include SkylarkModuleDoc in Builtins as a Value.
@@ -96,15 +115,46 @@
return field;
}
+ private static void printUsage(OptionsParser parser) {
+ System.err.println(
+ "Usage: api_exporter_bin -n product_name -p rule_class_provider (-i input_dir)+\n"
+ + " -f outputFile [-b blacklist] [-h]\n\n"
+ + "Exports all Starlark builtins to a file including the embedded native rules.\n"
+ + "The product name (-n), rule class provider (-p), output file (-f) and at least \n"
+ + " one input_dir (-i) must be specified.\n");
+ System.err.println(
+ parser.describeOptionsWithDeprecatedCategories(
+ Collections.<String, String>emptyMap(), OptionsParser.HelpVerbosity.LONG));
+ }
+
public static void main(String[] args) {
- if (args.length != 1) {
- throw new IllegalArgumentException(
- "Expected one argument. Usage:\n" + "{api_exporter_bin} {builtin_output_file}");
+ OptionsParser parser = OptionsParser.newOptionsParser(BuildEncyclopediaOptions.class);
+ parser.parseAndExitUponError(args);
+ BuildEncyclopediaOptions options = parser.getOptions(BuildEncyclopediaOptions.class);
+
+ if (options.help) {
+ printUsage(parser);
+ Runtime.getRuntime().exit(0);
}
- String builtinsProtoFile = args[0];
+ if (options.productName.isEmpty()
+ || options.inputDirs.isEmpty()
+ || options.provider.isEmpty()
+ || options.outputFile.isEmpty()) {
+ printUsage(parser);
+ Runtime.getRuntime().exit(1);
+ }
- appendBuiltins(builtinsProtoFile);
+ try {
+ ProtoFileBuildEncyclopediaProcessor processor =
+ new ProtoFileBuildEncyclopediaProcessor(
+ options.productName, createRuleClassProvider(options.provider));
+ processor.generateDocumentation(options.inputDirs, options.outputFile, options.blacklist);
+
+ appendBuiltins(processor, options.outputFile);
+ } catch (Throwable e) {
+ System.err.println("ERROR: " + e.getMessage());
+ }
}
}
diff --git a/src/main/java/com/google/devtools/build/docgen/BuildEncyclopediaOptions.java b/src/main/java/com/google/devtools/build/docgen/BuildEncyclopediaOptions.java
index 3c68ccb..bfd5840 100644
--- a/src/main/java/com/google/devtools/build/docgen/BuildEncyclopediaOptions.java
+++ b/src/main/java/com/google/devtools/build/docgen/BuildEncyclopediaOptions.java
@@ -55,6 +55,15 @@
public String provider;
@Option(
+ name = "output_file",
+ abbrev = 'f',
+ defaultValue = "",
+ documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
+ effectTags = {OptionEffectTag.UNKNOWN},
+ help = "An output file.")
+ public String outputFile;
+
+ @Option(
name = "output_dir",
abbrev = 'o',
defaultValue = ".",
diff --git a/src/main/java/com/google/devtools/build/docgen/ProtoFileBuildEncyclopediaProcessor.java b/src/main/java/com/google/devtools/build/docgen/ProtoFileBuildEncyclopediaProcessor.java
new file mode 100644
index 0000000..2d75605
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/docgen/ProtoFileBuildEncyclopediaProcessor.java
@@ -0,0 +1,65 @@
+// Copyright 2018 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.devtools.build.docgen.builtin.BuiltinProtos.Callable;
+import com.google.devtools.build.docgen.builtin.BuiltinProtos.Param;
+import com.google.devtools.build.docgen.builtin.BuiltinProtos.Value;
+import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/** Assembles a list of native rules that can be exported to a builtin.proto file. */
+public class ProtoFileBuildEncyclopediaProcessor extends BuildEncyclopediaProcessor {
+ private List<Value.Builder> nativeRules = null;
+
+ public ProtoFileBuildEncyclopediaProcessor(
+ String productName, ConfiguredRuleClassProvider ruleClassProvider) {
+ super(productName, ruleClassProvider);
+ nativeRules = new ArrayList<>();
+ }
+
+ @Override
+ public void generateDocumentation(List<String> inputDirs, String outputFile, String blackList)
+ throws BuildEncyclopediaDocException, IOException {
+ BuildDocCollector collector = new BuildDocCollector(productName, ruleClassProvider, false);
+ RuleLinkExpander expander = new RuleLinkExpander(productName, true);
+ Map<String, RuleDocumentation> ruleDocEntries =
+ collector.collect(inputDirs, blackList, expander);
+ RuleFamilies ruleFamilies = assembleRuleFamilies(ruleDocEntries.values());
+
+ for (RuleFamily entry : ruleFamilies.all) {
+ for (RuleDocumentation doc : entry.getRules()) {
+ Value.Builder rule = Value.newBuilder();
+ rule.setName(doc.getRuleName());
+ rule.setDoc(doc.getHtmlDocumentation());
+ Callable.Builder callable = Callable.newBuilder();
+ for (RuleDocumentationAttribute attr : doc.getAttributes()) {
+ Param.Builder param = Param.newBuilder();
+ param.setName(attr.getAttributeName());
+ callable.addParam(param);
+ }
+ rule.setCallable(callable);
+ nativeRules.add(rule);
+ }
+ }
+ }
+
+ public List<Value.Builder> getNativeRules() {
+ return nativeRules;
+ }
+}