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; + } +}