Add new flag to Stardoc and allows Stardoc to output raw serialized proto.
Progress toward https://github.com/bazelbuild/skydoc/issues/189
PiperOrigin-RevId: 253128175
diff --git a/src/main/java/com/google/devtools/build/skydoc/SkydocMain.java b/src/main/java/com/google/devtools/build/skydoc/SkydocMain.java
index 325716d..900f613 100644
--- a/src/main/java/com/google/devtools/build/skydoc/SkydocMain.java
+++ b/src/main/java/com/google/devtools/build/skydoc/SkydocMain.java
@@ -66,6 +66,7 @@
import com.google.devtools.build.lib.syntax.SkylarkImport;
import com.google.devtools.build.lib.syntax.StarlarkSemantics;
import com.google.devtools.build.lib.syntax.UserDefinedFunction;
+import com.google.devtools.build.skydoc.SkydocOptions.OutputFormat;
import com.google.devtools.build.skydoc.fakebuildapi.FakeActionsInfoProvider;
import com.google.devtools.build.skydoc.fakebuildapi.FakeBuildApiGlobals;
import com.google.devtools.build.skydoc.fakebuildapi.FakeConfigApi;
@@ -110,12 +111,15 @@
import com.google.devtools.build.skydoc.rendering.DocstringParseException;
import com.google.devtools.build.skydoc.rendering.FunctionUtil;
import com.google.devtools.build.skydoc.rendering.MarkdownRenderer;
+import com.google.devtools.build.skydoc.rendering.ProtoRenderer;
import com.google.devtools.build.skydoc.rendering.ProviderInfoWrapper;
import com.google.devtools.build.skydoc.rendering.RuleInfoWrapper;
import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.ProviderInfo;
import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.RuleInfo;
import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.UserDefinedFunctionInfo;
import com.google.devtools.common.options.OptionsParser;
+import java.io.BufferedOutputStream;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.NoSuchFileException;
@@ -171,7 +175,8 @@
}
public static void main(String[] args)
- throws IOException, InterruptedException, LabelSyntaxException, EvalException {
+ throws IOException, InterruptedException, LabelSyntaxException, EvalException,
+ DocstringParseException {
OptionsParser parser =
OptionsParser.newOptionsParser(StarlarkSemanticsOptions.class, SkydocOptions.class);
parser.parseAndExitUponError(args);
@@ -226,8 +231,6 @@
System.exit(1);
}
- MarkdownRenderer renderer = new MarkdownRenderer();
-
Map<String, RuleInfo> filteredRuleInfos =
ruleInfoMap.build().entrySet().stream()
.filter(entry -> validSymbolName(symbolNames, entry.getKey()))
@@ -240,11 +243,23 @@
userDefinedFunctions.build().entrySet().stream()
.filter(entry -> validSymbolName(symbolNames, entry.getKey()))
.collect(ImmutableMap.toImmutableMap(Entry::getKey, Entry::getValue));
- try (PrintWriter printWriter = new PrintWriter(outputPath, "UTF-8")) {
- printWriter.println(renderer.renderMarkdownHeader());
- printRuleInfos(printWriter, renderer, filteredRuleInfos);
- printProviderInfos(printWriter, renderer, filteredProviderInfos);
- printUserDefinedFunctions(printWriter, renderer, filteredUserDefinedFunctions);
+
+ if (skydocOptions.outputFormat == OutputFormat.PROTO) {
+ try (BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(outputPath))) {
+ new ProtoRenderer()
+ .appendRuleInfos(filteredRuleInfos.values())
+ .appendProviderInfos(filteredProviderInfos.values())
+ .appendUserDefinedFunctionInfos(filteredUserDefinedFunctions)
+ .writeModuleInfo(out);
+ }
+ } else if (skydocOptions.outputFormat == OutputFormat.MARKDOWN) {
+ MarkdownRenderer renderer = new MarkdownRenderer();
+ try (PrintWriter printWriter = new PrintWriter(outputPath, "UTF-8")) {
+ printWriter.println(renderer.renderMarkdownHeader());
+ printRuleInfos(printWriter, renderer, filteredRuleInfos);
+ printProviderInfos(printWriter, renderer, filteredProviderInfos);
+ printUserDefinedFunctions(printWriter, renderer, filteredUserDefinedFunctions);
+ }
}
}
diff --git a/src/main/java/com/google/devtools/build/skydoc/SkydocOptions.java b/src/main/java/com/google/devtools/build/skydoc/SkydocOptions.java
index d223e8c..8408bf8 100644
--- a/src/main/java/com/google/devtools/build/skydoc/SkydocOptions.java
+++ b/src/main/java/com/google/devtools/build/skydoc/SkydocOptions.java
@@ -14,6 +14,7 @@
package com.google.devtools.build.skydoc;
+import com.google.devtools.common.options.EnumConverter;
import com.google.devtools.common.options.Option;
import com.google.devtools.common.options.OptionDocumentationCategory;
import com.google.devtools.common.options.OptionEffectTag;
@@ -48,6 +49,15 @@
public String outputFilePath;
@Option(
+ name = "output_format",
+ defaultValue = "markdown",
+ converter = OutputFormatConverter.class,
+ documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
+ effectTags = OptionEffectTag.UNKNOWN,
+ help = "The format choice for the output file (\"markdown\" or \"proto\").")
+ public OutputFormat outputFormat;
+
+ @Option(
name = "symbols",
allowMultiple = true,
defaultValue = "",
@@ -64,4 +74,21 @@
effectTags = OptionEffectTag.UNKNOWN,
help = "File path roots to search when resolving transitive bzl dependencies")
public List<String> depRoots;
+
+ /** Converter for {@link OutputFormat} */
+ public static class OutputFormatConverter extends EnumConverter<OutputFormat> {
+
+ public OutputFormatConverter() {
+ super(OutputFormat.class, "output format");
+ }
+ }
+
+ /**
+ * The possible values for the --output_format flag, which controls the format of Stardoc's output
+ * file.
+ */
+ public enum OutputFormat {
+ MARKDOWN,
+ PROTO
+ }
}
diff --git a/src/main/java/com/google/devtools/build/skydoc/rendering/ProtoRenderer.java b/src/main/java/com/google/devtools/build/skydoc/rendering/ProtoRenderer.java
new file mode 100644
index 0000000..1d42833
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/skydoc/rendering/ProtoRenderer.java
@@ -0,0 +1,69 @@
+// Copyright 2019 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.skydoc.rendering;
+
+import com.google.devtools.build.lib.syntax.UserDefinedFunction;
+import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.ModuleInfo;
+import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.ProviderInfo;
+import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.RuleInfo;
+import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.UserDefinedFunctionInfo;
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Map;
+
+/** Produces skydoc output in proto form. */
+public class ProtoRenderer {
+
+ private final ModuleInfo.Builder moduleInfo;
+
+ public ProtoRenderer() {
+ this.moduleInfo = ModuleInfo.newBuilder();
+ }
+
+ /** Appends {@link RuleInfo} protos to a {@link ModuleInfo.Builder}. */
+ public ProtoRenderer appendRuleInfos(Collection<RuleInfo> ruleInfos) {
+ for (RuleInfo ruleInfo : ruleInfos) {
+ moduleInfo.addRuleInfo(ruleInfo);
+ }
+ return this;
+ }
+
+ /** Appends {@link ProviderInfo} protos to a {@link ModuleInfo.Builder}. */
+ public ProtoRenderer appendProviderInfos(Collection<ProviderInfoWrapper> providerInfoWrappers) {
+ for (ProviderInfoWrapper providerInfoWrapper : providerInfoWrappers) {
+ ProviderInfo providerInfo = providerInfoWrapper.getProviderInfo();
+ moduleInfo.addProviderInfo(providerInfo);
+ }
+ return this;
+ }
+
+ /** Appends {@link UserDefinedFunctionInfo} protos to a {@link ModuleInfo.Builder}. */
+ public ProtoRenderer appendUserDefinedFunctionInfos(Map<String, UserDefinedFunction> funcInfosMap)
+ throws DocstringParseException {
+ for (Map.Entry<String, UserDefinedFunction> entry : funcInfosMap.entrySet()) {
+ UserDefinedFunctionInfo funcInfo =
+ FunctionUtil.fromNameAndFunction(entry.getKey(), entry.getValue());
+ moduleInfo.addFuncInfo(funcInfo);
+ }
+ return this;
+ }
+
+ /** Outputs the raw form of a {@link ModuleInfo} proto. */
+ public void writeModuleInfo(BufferedOutputStream outputStream) throws IOException {
+ ModuleInfo build = moduleInfo.build();
+ build.writeTo(outputStream);
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/skydoc/rendering/proto/stardoc_output.proto b/src/main/java/com/google/devtools/build/skydoc/rendering/proto/stardoc_output.proto
index 539245a..b567484 100644
--- a/src/main/java/com/google/devtools/build/skydoc/rendering/proto/stardoc_output.proto
+++ b/src/main/java/com/google/devtools/build/skydoc/rendering/proto/stardoc_output.proto
@@ -23,6 +23,17 @@
option java_package = "com.google.devtools.build.skydoc.rendering.proto";
option java_outer_classname = "StardocOutputProtos";
+// The root output proto of Stardoc. A single invocation of Stardoc will output
+// exactly one instance of this proto, representing all documentation for
+// the input Starlark file.
+message ModuleInfo {
+ repeated RuleInfo rule_info = 1;
+
+ repeated ProviderInfo provider_info = 2;
+
+ repeated UserDefinedFunctionInfo func_info = 3;
+}
+
// Representation of a Starlark rule attribute type. These generally
// have a one-to-one correspondence with functions defined at
// https://docs.bazel.build/versions/master/skylark/lib/attr.html.