aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/com/google/devtools/build/skydoc/renderer/BUILD45
-rw-r--r--src/main/java/com/google/devtools/build/skydoc/renderer/FileSystemAccessor.java45
-rw-r--r--src/main/java/com/google/devtools/build/skydoc/renderer/ProtoFileAccessor.java42
-rw-r--r--src/main/java/com/google/devtools/build/skydoc/renderer/RendererMain.java260
-rw-r--r--src/main/java/com/google/devtools/build/skydoc/renderer/RendererOptions.java83
-rw-r--r--src/main/java/com/google/devtools/build/skydoc/rendering/BUILD27
-rw-r--r--src/main/java/com/google/devtools/build/skydoc/rendering/MarkdownRenderer.java223
-rw-r--r--src/main/java/com/google/devtools/build/skydoc/rendering/MarkdownUtil.java443
8 files changed, 0 insertions, 1168 deletions
diff --git a/src/main/java/com/google/devtools/build/skydoc/renderer/BUILD b/src/main/java/com/google/devtools/build/skydoc/renderer/BUILD
deleted file mode 100644
index deab52e..0000000
--- a/src/main/java/com/google/devtools/build/skydoc/renderer/BUILD
+++ /dev/null
@@ -1,45 +0,0 @@
-load("@rules_java//java:defs.bzl", "java_binary", "java_library")
-
-package(
- default_applicable_licenses = ["//:license"],
- default_visibility = [
- "//src:__subpackages__",
- "//stardoc:__subpackages__",
- ],
-)
-
-filegroup(
- name = "srcs",
- srcs = glob(["**"]),
- visibility = ["//:__pkg__"],
-)
-
-java_binary(
- name = "renderer",
- jvm_flags = [
- # quiet warnings from com.google.protobuf.UnsafeUtil,
- # see: https://github.com/google/protobuf/issues/3781
- # and: https://github.com/bazelbuild/bazel/issues/5599
- "--add-opens=java.base/java.nio=ALL-UNNAMED",
- "--add-opens=java.base/java.lang=ALL-UNNAMED",
- # ... but only on JDK >= 9
- "-XX:+IgnoreUnrecognizedVMOptions",
- ],
- main_class = "com.google.devtools.build.skydoc.renderer.RendererMain",
- visibility = ["//visibility:public"],
- runtime_deps = [
- ":renderer_lib",
- ],
-)
-
-java_library(
- name = "renderer_lib",
- srcs = glob(["*.java"]),
- deps = [
- "//src/main/java/com/google/devtools/build/skydoc/rendering",
- "//stardoc/proto:stardoc_output_java_proto",
- "@com_google_protobuf//:protobuf_java",
- "@stardoc_maven//:com_beust_jcommander",
- "@stardoc_maven//:com_google_guava_guava",
- ],
-)
diff --git a/src/main/java/com/google/devtools/build/skydoc/renderer/FileSystemAccessor.java b/src/main/java/com/google/devtools/build/skydoc/renderer/FileSystemAccessor.java
deleted file mode 100644
index 3e424d8..0000000
--- a/src/main/java/com/google/devtools/build/skydoc/renderer/FileSystemAccessor.java
+++ /dev/null
@@ -1,45 +0,0 @@
-// 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.renderer;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-/** Implementation of {@link ProtoFileAccessor} which uses the real filesystem. */
-public class FileSystemAccessor implements ProtoFileAccessor {
-
- @Override
- public byte[] getProtoContent(String inputPathString) throws IOException {
- Path inputPath = Paths.get(inputPathString);
- byte[] inputContent = Files.readAllBytes(inputPath);
- return inputContent;
- }
-
- @Override
- public boolean fileExists(String pathString) {
- return Files.exists(Paths.get(pathString));
- }
-
- @Override
- public void writeToOutputLocation(String outputPathString, byte[] content) throws IOException {
- try (FileOutputStream outputStream = new FileOutputStream(outputPathString)) {
- for (byte byteContent : content) {
- outputStream.write(byteContent);
- }
- }
- }
-}
diff --git a/src/main/java/com/google/devtools/build/skydoc/renderer/ProtoFileAccessor.java b/src/main/java/com/google/devtools/build/skydoc/renderer/ProtoFileAccessor.java
deleted file mode 100644
index 3b75d9b..0000000
--- a/src/main/java/com/google/devtools/build/skydoc/renderer/ProtoFileAccessor.java
+++ /dev/null
@@ -1,42 +0,0 @@
-// 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.renderer;
-
-import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos;
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-/**
- * Helper to handle Proto file I/O. This abstraction is useful for tests which don't involve actual
- * file I/O.
- */
-public interface ProtoFileAccessor {
- /**
- * Returns the bytes from the raw proto file.
- *
- * @param inputPathString the path of the input raw {@link StardocOutputProtos} file.
- */
- byte[] getProtoContent(String inputPathString) throws IOException;
-
- /** Returns true if a file exists at the current path. */
- boolean fileExists(String pathString);
-
- /**
- * Creates a {@link FileOutputStream} and writes the bytes to the output location.
- *
- * @param outputPathString the output location that is being written to
- * @param content the bytes from input proto file
- */
- void writeToOutputLocation(String outputPathString, byte[] content) throws IOException;
-}
diff --git a/src/main/java/com/google/devtools/build/skydoc/renderer/RendererMain.java b/src/main/java/com/google/devtools/build/skydoc/renderer/RendererMain.java
deleted file mode 100644
index 39b11df..0000000
--- a/src/main/java/com/google/devtools/build/skydoc/renderer/RendererMain.java
+++ /dev/null
@@ -1,260 +0,0 @@
-// 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.renderer;
-
-import static com.google.common.collect.ImmutableList.toImmutableList;
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static java.util.Comparator.comparing;
-
-import com.beust.jcommander.JCommander;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.devtools.build.skydoc.rendering.MarkdownRenderer;
-import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.AspectInfo;
-import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.AttributeInfo;
-import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.ModuleExtensionInfo;
-import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.ModuleExtensionTagClassInfo;
-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.RepositoryRuleInfo;
-import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.RuleInfo;
-import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.StarlarkFunctionInfo;
-import com.google.protobuf.ExtensionRegistry;
-import com.google.protobuf.InvalidProtocolBufferException;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.Comparator;
-import java.util.List;
-
-/**
- * Main entry point for Renderer binary.
- *
- * <p>This Renderer takes in raw stardoc_proto protos as input and produces rich markdown output.
- */
-public final class RendererMain {
-
- public static void main(String[] args) throws IOException {
-
- RendererOptions rendererOptions = new RendererOptions();
- JCommander jcommander = JCommander.newBuilder().addObject(rendererOptions).build();
- jcommander.setProgramName("renderer");
- jcommander.parse(args);
- if (rendererOptions.printHelp) {
- jcommander.usage();
- return;
- }
-
- String inputPath = rendererOptions.inputPath;
- String outputPath = rendererOptions.outputFilePath;
-
- try (PrintWriter printWriter =
- new PrintWriter(outputPath, UTF_8) {
- // Use consistent line endings on all platforms.
- @Override
- public void println() {
- write("\n");
- }
- }) {
- ModuleInfo moduleInfo =
- ModuleInfo.parseFrom(
- new FileInputStream(inputPath), ExtensionRegistry.getEmptyRegistry());
-
- MarkdownRenderer renderer =
- new MarkdownRenderer(
- rendererOptions.headerTemplateFilePath,
- rendererOptions.ruleTemplateFilePath,
- rendererOptions.providerTemplateFilePath,
- rendererOptions.funcTemplateFilePath,
- rendererOptions.aspectTemplateFilePath,
- rendererOptions.repositoryRuleTemplateFilePath,
- rendererOptions.moduleExtensionTemplateFilePath,
- !moduleInfo.getFile().isEmpty() ? moduleInfo.getFile() : "...");
-
- printWriter.println(renderer.renderMarkdownHeader(moduleInfo));
- printRuleInfos(printWriter, renderer, moduleInfo.getRuleInfoList());
- printProviderInfos(printWriter, renderer, moduleInfo.getProviderInfoList());
- printStarlarkFunctions(printWriter, renderer, moduleInfo.getFuncInfoList());
- printAspectInfos(printWriter, renderer, moduleInfo.getAspectInfoList());
- printRepositoryRuleInfos(printWriter, renderer, moduleInfo.getRepositoryRuleInfoList());
- printModuleExtensionInfos(printWriter, renderer, moduleInfo.getModuleExtensionInfoList());
- } catch (InvalidProtocolBufferException e) {
- throw new IllegalArgumentException("Input file is not a valid ModuleInfo proto.", e);
- }
- }
-
- // A copy of com.google.devtools.build.docgen.DocgenConsts.ATTRIBUTE_ORDERING - we duplicate the
- // ordering here because we intend to move this file from the Bazel tree to the Stardoc repo.
- private static final ImmutableMap<String, Integer> ATTRIBUTE_ORDERING =
- ImmutableMap.<String, Integer>builder()
- .put("name", -99)
- .put("deps", -98)
- .put("src", -97)
- .put("srcs", -96)
- .put("data", -95)
- .put("resource", -94)
- .put("resources", -93)
- .put("out", -92)
- .put("outs", -91)
- .put("hdrs", -90)
- .buildOrThrow();
-
- private static final Comparator<String> ATTRIBUTE_NAME_COMPARATOR =
- (a, b) -> {
- int aOrdering = ATTRIBUTE_ORDERING.getOrDefault(a, 0);
- int bOrdering = ATTRIBUTE_ORDERING.getOrDefault(b, 0);
- if (aOrdering > bOrdering) {
- return 1;
- } else if (aOrdering < bOrdering) {
- return -1;
- } else {
- return Comparator.<String>naturalOrder().compare(a, b);
- }
- };
-
- private static RuleInfo withSortedRuleAttributes(RuleInfo ruleInfo) {
- return ruleInfo.toBuilder()
- .clearAttribute()
- .addAllAttribute(
- ImmutableList.sortedCopyOf(
- comparing(AttributeInfo::getName, ATTRIBUTE_NAME_COMPARATOR),
- ruleInfo.getAttributeList()))
- .build();
- }
-
- private static RepositoryRuleInfo withSortedRuleAttributes(
- RepositoryRuleInfo repositoryRuleInfo) {
- return repositoryRuleInfo.toBuilder()
- .clearAttribute()
- .addAllAttribute(
- ImmutableList.sortedCopyOf(
- comparing(AttributeInfo::getName, ATTRIBUTE_NAME_COMPARATOR),
- repositoryRuleInfo.getAttributeList()))
- .build();
- }
-
- private static ModuleExtensionTagClassInfo withSortedTagAttributes(
- ModuleExtensionTagClassInfo moduleExtensionTagClassInfo) {
- return moduleExtensionTagClassInfo.toBuilder()
- .clearAttribute()
- .addAllAttribute(
- ImmutableList.sortedCopyOf(
- comparing(AttributeInfo::getName, ATTRIBUTE_NAME_COMPARATOR),
- moduleExtensionTagClassInfo.getAttributeList()))
- .build();
- }
-
- private static ModuleExtensionInfo withSortedTagAttributes(
- ModuleExtensionInfo moduleExtensionInfo) {
- return moduleExtensionInfo.toBuilder()
- .clearTagClass()
- .addAllTagClass(
- moduleExtensionInfo.getTagClassList().stream()
- .map(RendererMain::withSortedTagAttributes)
- .collect(toImmutableList()))
- .build();
- }
-
- private static void printRuleInfos(
- PrintWriter printWriter, MarkdownRenderer renderer, List<RuleInfo> ruleInfos)
- throws IOException {
- // rules are printed sorted by their qualified name, and their attributes are sorted by name,
- // with ATTRIBUTE_ORDERING specifying a fixed sort order for some standard attributes.
- ImmutableList<RuleInfo> sortedRuleInfos =
- ruleInfos.stream()
- .map(RendererMain::withSortedRuleAttributes)
- .sorted(comparing(RuleInfo::getRuleName))
- .collect(toImmutableList());
- for (RuleInfo ruleProto : sortedRuleInfos) {
- printWriter.println(renderer.render(ruleProto.getRuleName(), ruleProto));
- printWriter.println();
- }
- }
-
- private static void printProviderInfos(
- PrintWriter printWriter, MarkdownRenderer renderer, List<ProviderInfo> providerInfos)
- throws IOException {
- // providers are printed sorted by their qualified name.
- ImmutableList<ProviderInfo> sortedProviderInfos =
- ImmutableList.sortedCopyOf(comparing(ProviderInfo::getProviderName), providerInfos);
- for (ProviderInfo providerProto : sortedProviderInfos) {
- printWriter.println(renderer.render(providerProto.getProviderName(), providerProto));
- printWriter.println();
- }
- }
-
- private static void printStarlarkFunctions(
- PrintWriter printWriter,
- MarkdownRenderer renderer,
- List<StarlarkFunctionInfo> starlarkFunctions)
- throws IOException {
- // functions are printed sorted by their qualified name.
- ImmutableList<StarlarkFunctionInfo> sortedStarlarkFunctions =
- ImmutableList.sortedCopyOf(
- comparing(StarlarkFunctionInfo::getFunctionName), starlarkFunctions);
- for (StarlarkFunctionInfo funcProto : sortedStarlarkFunctions) {
- printWriter.println(renderer.render(funcProto));
- printWriter.println();
- }
- }
-
- private static void printAspectInfos(
- PrintWriter printWriter, MarkdownRenderer renderer, List<AspectInfo> aspectInfos)
- throws IOException {
- // aspects are printed sorted by their qualified name.
- ImmutableList<AspectInfo> sortedAspectInfos =
- ImmutableList.sortedCopyOf(comparing(AspectInfo::getAspectName), aspectInfos);
- for (AspectInfo aspectProto : sortedAspectInfos) {
- printWriter.println(renderer.render(aspectProto.getAspectName(), aspectProto));
- printWriter.println();
- }
- }
-
- private static void printRepositoryRuleInfos(
- PrintWriter printWriter, MarkdownRenderer renderer, List<RepositoryRuleInfo> ruleInfos)
- throws IOException {
- // Repository rules are printed sorted by their qualified name, and their attributes are sorted
- // by name, with ATTRIBUTE_ORDERING specifying a fixed sort order for some standard attributes.
- ImmutableList<RepositoryRuleInfo> sortedRepositoryRuleInfos =
- ruleInfos.stream()
- .map(RendererMain::withSortedRuleAttributes)
- .sorted(comparing(RepositoryRuleInfo::getRuleName))
- .collect(toImmutableList());
- for (RepositoryRuleInfo repositoryRuleProto : sortedRepositoryRuleInfos) {
- printWriter.println(renderer.render(repositoryRuleProto.getRuleName(), repositoryRuleProto));
- printWriter.println();
- }
- }
-
- private static void printModuleExtensionInfos(
- PrintWriter printWriter, MarkdownRenderer renderer, List<ModuleExtensionInfo> ruleInfos)
- throws IOException {
- // Module extension are printed sorted by their qualified name, and their tag classes'
- // attributes are sorted by name, with ATTRIBUTE_ORDERING specifying a fixed sort order for some
- // standard attributes.
- ImmutableList<ModuleExtensionInfo> sortedModuleExtensionInfos =
- ruleInfos.stream()
- .map(RendererMain::withSortedTagAttributes)
- .sorted(comparing(ModuleExtensionInfo::getExtensionName))
- .collect(toImmutableList());
- for (ModuleExtensionInfo moduleExtensionProto : sortedModuleExtensionInfos) {
- printWriter.println(
- renderer.render(moduleExtensionProto.getExtensionName(), moduleExtensionProto));
- printWriter.println();
- }
- }
-
- private RendererMain() {}
-}
diff --git a/src/main/java/com/google/devtools/build/skydoc/renderer/RendererOptions.java b/src/main/java/com/google/devtools/build/skydoc/renderer/RendererOptions.java
deleted file mode 100644
index 52ed165..0000000
--- a/src/main/java/com/google/devtools/build/skydoc/renderer/RendererOptions.java
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2023 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.renderer;
-
-import com.beust.jcommander.Parameter;
-import com.beust.jcommander.Parameters;
-
-/** Contains options for running {@link RendererMain}. */
-@Parameters(separators = "=")
-class RendererOptions {
-
- @Parameter(
- names = "--input",
- required = true,
- description = "The path of the proto file that will be converted to markdown")
- String inputPath;
-
- @Parameter(
- names = "--output",
- required = true,
- description = "The path of the file to output documentation into")
- String outputFilePath;
-
- @Parameter(
- names = "--header_template",
- required = true,
- description = "The template for the header string")
- String headerTemplateFilePath;
-
- @Parameter(
- names = "--rule_template",
- required = true,
- description = "The template for the documentation of a rule")
- String ruleTemplateFilePath;
-
- @Parameter(
- names = "--provider_template",
- required = true,
- description = "The template for the documentation of a provider")
- String providerTemplateFilePath;
-
- @Parameter(
- names = "--func_template",
- required = true,
- description = "The template for the documentation of a function")
- String funcTemplateFilePath;
-
- @Parameter(
- names = "--aspect_template",
- required = true,
- description = "The template for the documentation of an aspect")
- String aspectTemplateFilePath;
-
- @Parameter(
- names = "--repository_rule_template",
- required = true,
- description = "The template for the documentation of a repository rule")
- String repositoryRuleTemplateFilePath;
-
- @Parameter(
- names = "--module_extension_template",
- required = true,
- description = "The template for the documentation of a module extension")
- String moduleExtensionTemplateFilePath;
-
- @Parameter(
- names = {"--help", "-h"},
- description = "Print help and exit",
- help = true)
- boolean printHelp;
-}
diff --git a/src/main/java/com/google/devtools/build/skydoc/rendering/BUILD b/src/main/java/com/google/devtools/build/skydoc/rendering/BUILD
deleted file mode 100644
index 014af3b..0000000
--- a/src/main/java/com/google/devtools/build/skydoc/rendering/BUILD
+++ /dev/null
@@ -1,27 +0,0 @@
-load("@rules_java//java:defs.bzl", "java_library")
-
-package(
- default_applicable_licenses = ["//:license"],
- default_visibility = [
- "//src:__subpackages__",
- "//stardoc:__subpackages__",
- ],
-)
-
-filegroup(
- name = "srcs",
- srcs = glob(["**"]),
- visibility = ["//:__pkg__"],
-)
-
-java_library(
- name = "rendering",
- srcs = glob(
- ["*.java"],
- ),
- deps = [
- "//stardoc/proto:stardoc_output_java_proto",
- "@stardoc_maven//:com_google_escapevelocity_escapevelocity",
- "@stardoc_maven//:com_google_guava_guava",
- ],
-)
diff --git a/src/main/java/com/google/devtools/build/skydoc/rendering/MarkdownRenderer.java b/src/main/java/com/google/devtools/build/skydoc/rendering/MarkdownRenderer.java
deleted file mode 100644
index 2ff4a4e..0000000
--- a/src/main/java/com/google/devtools/build/skydoc/rendering/MarkdownRenderer.java
+++ /dev/null
@@ -1,223 +0,0 @@
-// 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.skydoc.rendering;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.AspectInfo;
-import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.ModuleExtensionInfo;
-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.RepositoryRuleInfo;
-import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.RuleInfo;
-import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.StarlarkFunctionInfo;
-import com.google.escapevelocity.EvaluationException;
-import com.google.escapevelocity.ParseException;
-import com.google.escapevelocity.Template;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-/** Produces skydoc output in markdown form. */
-public class MarkdownRenderer {
- // TODO(kendalllane): Refactor MarkdownRenderer to take in something other than filepaths.
- private final String headerTemplateFilename;
- private final String ruleTemplateFilename;
- private final String providerTemplateFilename;
- private final String functionTemplateFilename;
- private final String aspectTemplateFilename;
- private final String repositoryRuleTemplateFilename;
- private final String moduleExtensionTemplateFilename;
- private final String extensionBzlFile;
-
- public MarkdownRenderer(
- String headerTemplate,
- String ruleTemplate,
- String providerTemplate,
- String functionTemplate,
- String aspectTemplate,
- String repositoryRuleTemplate,
- String moduleExtensionTemplate,
- String extensionBzlFile) {
- this.headerTemplateFilename = headerTemplate;
- this.ruleTemplateFilename = ruleTemplate;
- this.providerTemplateFilename = providerTemplate;
- this.functionTemplateFilename = functionTemplate;
- this.aspectTemplateFilename = aspectTemplate;
- this.repositoryRuleTemplateFilename = repositoryRuleTemplate;
- this.moduleExtensionTemplateFilename = moduleExtensionTemplate;
- this.extensionBzlFile = extensionBzlFile;
- }
-
- /**
- * Returns a markdown header string that should appear at the top of Stardoc's output, providing a
- * summary for the input Starlark module.
- */
- public String renderMarkdownHeader(ModuleInfo moduleInfo) throws IOException {
- ImmutableMap<String, Object> vars =
- ImmutableMap.of(
- "util",
- new MarkdownUtil(extensionBzlFile),
- "moduleDocstring",
- moduleInfo.getModuleDocstring());
- Reader reader = readerFromPath(headerTemplateFilename);
- try {
- return Template.parseFrom(reader).evaluate(vars);
- } catch (ParseException | EvaluationException e) {
- throw new IOException(e);
- }
- }
-
- /**
- * Returns a markdown rendering of rule documentation for the given rule information object with
- * the given rule name.
- */
- public String render(String ruleName, RuleInfo ruleInfo) throws IOException {
- ImmutableMap<String, Object> vars =
- ImmutableMap.of(
- "util", new MarkdownUtil(extensionBzlFile), "ruleName", ruleName, "ruleInfo", ruleInfo);
- Reader reader = readerFromPath(ruleTemplateFilename);
- try {
- return Template.parseFrom(reader).evaluate(vars);
- } catch (ParseException | EvaluationException e) {
- throw new IOException(e);
- }
- }
-
- /**
- * Returns a markdown rendering of provider documentation for the given provider information
- * object with the given name.
- */
- public String render(String providerName, ProviderInfo providerInfo) throws IOException {
- ImmutableMap<String, Object> vars =
- ImmutableMap.of(
- "util",
- new MarkdownUtil(extensionBzlFile),
- "providerName",
- providerName,
- "providerInfo",
- providerInfo);
- Reader reader = readerFromPath(providerTemplateFilename);
- try {
- return Template.parseFrom(reader).evaluate(vars);
- } catch (ParseException | EvaluationException e) {
- throw new IOException(e);
- }
- }
-
- /**
- * Returns a markdown rendering of a user-defined function's documentation for the function info
- * object.
- */
- public String render(StarlarkFunctionInfo functionInfo) throws IOException {
- ImmutableMap<String, Object> vars =
- ImmutableMap.of("util", new MarkdownUtil(extensionBzlFile), "funcInfo", functionInfo);
- Reader reader = readerFromPath(functionTemplateFilename);
- try {
- return Template.parseFrom(reader).evaluate(vars);
- } catch (ParseException | EvaluationException e) {
- throw new IOException(e);
- }
- }
-
- /**
- * Returns a markdown rendering of aspect documentation for the given aspect information object
- * with the given aspect name.
- */
- public String render(String aspectName, AspectInfo aspectInfo) throws IOException {
- ImmutableMap<String, Object> vars =
- ImmutableMap.of(
- "util",
- new MarkdownUtil(extensionBzlFile),
- "aspectName",
- aspectName,
- "aspectInfo",
- aspectInfo);
- Reader reader = readerFromPath(aspectTemplateFilename);
- try {
- return Template.parseFrom(reader).evaluate(vars);
- } catch (ParseException | EvaluationException e) {
- throw new IOException(e);
- }
- }
-
- /**
- * Returns a markdown rendering of repository rule documentation for the given repository rule
- * information object with the given name.
- */
- public String render(String repositoryRuleName, RepositoryRuleInfo repositoryRuleInfo)
- throws IOException {
- ImmutableMap<String, Object> vars =
- ImmutableMap.of(
- "util",
- new MarkdownUtil(extensionBzlFile),
- "ruleName",
- repositoryRuleName,
- "ruleInfo",
- repositoryRuleInfo);
- Reader reader = readerFromPath(repositoryRuleTemplateFilename);
- try {
- return Template.parseFrom(reader).evaluate(vars);
- } catch (ParseException | EvaluationException e) {
- throw new IOException(e);
- }
- }
-
- /**
- * Returns a markdown rendering of module extension documentation for the given module extension
- * information object with the given name.
- */
- public String render(String moduleExtensionName, ModuleExtensionInfo moduleExtensionInfo)
- throws IOException {
- ImmutableMap<String, Object> vars =
- ImmutableMap.of(
- "util",
- new MarkdownUtil(extensionBzlFile),
- "extensionName",
- moduleExtensionName,
- "extensionInfo",
- moduleExtensionInfo);
- Reader reader = readerFromPath(moduleExtensionTemplateFilename);
- try {
- return Template.parseFrom(reader).evaluate(vars);
- } catch (ParseException | EvaluationException e) {
- throw new IOException(e);
- }
- }
-
- /**
- * Returns a reader from the given path.
- *
- * @param filePath The given path, either a filesystem path or a java Resource
- */
- private static Reader readerFromPath(String filePath) throws IOException {
- if (Files.exists(Paths.get(filePath))) {
- Path path = Paths.get(filePath);
- return Files.newBufferedReader(path, UTF_8);
- }
-
- InputStream inputStream = MarkdownRenderer.class.getClassLoader().getResourceAsStream(filePath);
- if (inputStream == null) {
- throw new FileNotFoundException(filePath + " was not found as a resource.");
- }
- return new InputStreamReader(inputStream, UTF_8);
- }
-}
diff --git a/src/main/java/com/google/devtools/build/skydoc/rendering/MarkdownUtil.java b/src/main/java/com/google/devtools/build/skydoc/rendering/MarkdownUtil.java
deleted file mode 100644
index afb2b5e..0000000
--- a/src/main/java/com/google/devtools/build/skydoc/rendering/MarkdownUtil.java
+++ /dev/null
@@ -1,443 +0,0 @@
-// 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.skydoc.rendering;
-
-import static com.google.common.collect.ImmutableList.toImmutableList;
-import static java.util.Comparator.naturalOrder;
-import static java.util.stream.Collectors.joining;
-
-import com.google.common.base.Joiner;
-import com.google.common.collect.ImmutableList;
-import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.AspectInfo;
-import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.AttributeInfo;
-import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.AttributeType;
-import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.FunctionParamInfo;
-import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.ModuleExtensionInfo;
-import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.ModuleExtensionTagClassInfo;
-import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.ProviderInfo;
-import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.ProviderNameGroup;
-import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.RepositoryRuleInfo;
-import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.RuleInfo;
-import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.StarlarkFunctionInfo;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/** Contains a number of utility methods for markdown rendering. */
-public final class MarkdownUtil {
- private final String extensionBzlFile;
-
- private static final int MAX_LINE_LENGTH = 100;
-
- public MarkdownUtil(String extensionBzlFile) {
- this.extensionBzlFile = extensionBzlFile;
- }
-
- /**
- * Formats the input string so that it is displayable in a Markdown table cell. This performs the
- * following operations:
- *
- * <ul>
- * <li>Trims the string of leading/trailing whitespace.
- * <li>Escapes pipe characters ({@code |}) as {@code \|}.
- * <li>Transforms Markdown code blocks ({@code ```}) into HTML preformatted code blocks, and
- * transforms newlines within those code blocks into character entities
- * <li>Transforms remaining 'new paragraph' patterns (two or more sequential newline characters)
- * into line break HTML tags.
- * <li>Turns remaining newlines into spaces (as they generally indicate intended line wrap).
- * </ul>
- *
- * TODO(https://github.com/bazelbuild/stardoc/issues/118): also format Markdown lists as HTML.
- */
- public static String markdownCellFormat(String docString) {
- return new MarkdownCellFormatter(docString).format();
- }
-
- // See https://github.github.com/gfm
- private static final class MarkdownCellFormatter {
- // Lines of the input docstring, without newline terminators.
- private final ImmutableList<String> lines;
- // Index of the current line in lines, 0-based.
- int currentLine;
- // Formatted result.
- StringBuilder result;
-
- private static final Pattern CODE_BLOCK_OPENING_FENCE =
- Pattern.compile("^ {0,3}(?<fence>```+|~~~+) *(?<lang>\\w*)[^`~]*$");
-
- MarkdownCellFormatter(String docString) {
- lines = docString.trim().replace("|", "\\|").lines().collect(toImmutableList());
- currentLine = 0;
- result = new StringBuilder();
- }
-
- /** Consumes the input and yields the formatted result. */
- String format() {
- boolean prefixContentWithSpace = false;
- for (; currentLine < lines.size(); currentLine++) {
- if (formatParagraphBreak()) {
- prefixContentWithSpace = false;
- continue;
- }
- if (prefixContentWithSpace) {
- result.append(" ");
- }
- prefixContentWithSpace = true;
- if (formatFencedCodeBlock()) {
- continue;
- }
- result.append(lines.get(currentLine));
- }
- return result.toString();
- }
-
- /**
- * If a fenced code block begins at {@link #currentLine}, render to {@link #result}, update
- * {@link #currentLine} to point to the closing fence, and return true.
- */
- private boolean formatFencedCodeBlock() {
- // See https://github.github.com/gfm/#fenced-code-blocks
- Matcher opening = CODE_BLOCK_OPENING_FENCE.matcher(lines.get(currentLine));
- if (!opening.matches()) {
- return false;
- }
- Pattern closingFence = Pattern.compile("^ {0,3}" + opening.group("fence") + " *$");
- for (int closingLine = currentLine + 1; closingLine < lines.size(); closingLine++) {
- if (closingFence.matcher(lines.get(closingLine)).matches()) {
- // We found the closing fence: format the block's contents as HTML.
- String language = opening.group("lang");
- if (language != null && !language.isEmpty()) {
- result.append("<pre><code class=\"language-").append(language).append("\">");
- } else {
- result.append("<pre><code>");
- }
- int firstContentLine = currentLine + 1;
- for (int i = firstContentLine; i < closingLine; i++) {
- if (i > firstContentLine) {
- result.append(newlineEscape("\n"));
- }
- result.append(htmlEscape(lines.get(i)));
- }
- result.append("</code></pre>");
- currentLine = closingLine;
- return true;
- }
- }
- // We did not find the closing fence.
- return false;
- }
-
- /**
- * If blank lines appear at {@link #currentLine}, render to {@link #result}, update {@link
- * #currentLine} to point to the last line of the break, and return true.
- */
- private boolean formatParagraphBreak() {
- int numEmptyLines = 0;
- for (int i = currentLine; i < lines.size(); i++) {
- if (lines.get(i).isEmpty()) {
- numEmptyLines++;
- } else {
- break;
- }
- }
- if (numEmptyLines > 0) {
- result.append("<br><br>");
- currentLine += numEmptyLines - 1;
- return true;
- }
- return false;
- }
- }
-
- /**
- * Return a string that escapes angle brackets for HTML.
- *
- * <p>For example: 'Information with <brackets>.' becomes 'Information with &lt;brackets&gt;'.
- */
- public static String htmlEscape(String docString) {
- return docString.replace("<", "&lt;").replace(">", "&gt;");
- }
-
- /** Returns a string that escapes newlines with HTML entities. */
- private static String newlineEscape(String docString) {
- return docString.replace("\n", "&#10;");
- }
-
- private static final Pattern CONSECUTIVE_BACKTICKS = Pattern.compile("`+");
-
- /**
- * Returns a Markdown code span (e.g. {@code `return foo;`}) that contains the given literal text,
- * which may itself contain backticks.
- *
- * <p>For example:
- *
- * <ul>
- * <li>{@code markdownCodeSpan("foo")} returns {@code "`foo`"}
- * <li>{@code markdownCodeSpan("fo`o")} returns {@code "``fo`o``"}
- * <li>{@code markdownCodeSpan("`foo`")} returns {@code "`` foo` ``""}
- * </ul>
- */
- public static String markdownCodeSpan(String code) {
- // https://github.github.com/gfm/#code-span
- int numConsecutiveBackticks =
- CONSECUTIVE_BACKTICKS
- .matcher(code)
- .results()
- .map(match -> match.end() - match.start())
- .max(naturalOrder())
- .orElse(0);
- String padding = code.startsWith("`") || code.endsWith("`") ? " " : "";
- return String.format(
- "%1$s%2$s%3$s%2$s%1$s", "`".repeat(numConsecutiveBackticks + 1), padding, code);
- }
-
- /**
- * Return a string representing the rule summary for the given rule with the given name.
- *
- * <p>For example: 'my_rule(foo, bar)'. The summary will contain hyperlinks for each attribute.
- */
- @SuppressWarnings("unused") // Used by markdown template.
- public String ruleSummary(String ruleName, RuleInfo ruleInfo) {
- ImmutableList<String> attributeNames =
- ruleInfo.getAttributeList().stream().map(AttributeInfo::getName).collect(toImmutableList());
- return summary(ruleName, attributeNames);
- }
-
- /**
- * Return a string representing the summary for the given provider with the given name.
- *
- * <p>For example: 'MyInfo(foo, bar)'. The summary will contain hyperlinks for each field.
- */
- @SuppressWarnings("unused") // Used by markdown template.
- public String providerSummary(String providerName, ProviderInfo providerInfo) {
- ImmutableList<String> fieldNames =
- providerInfo.getFieldInfoList().stream()
- .map(field -> field.getName())
- .collect(toImmutableList());
- return summary(providerName, fieldNames);
- }
-
- /**
- * Return a string representing the aspect summary for the given aspect with the given name.
- *
- * <p>For example: 'my_aspect(foo, bar)'. The summary will contain hyperlinks for each attribute.
- */
- @SuppressWarnings("unused") // Used by markdown template.
- public String aspectSummary(String aspectName, AspectInfo aspectInfo) {
- ImmutableList<String> attributeNames =
- aspectInfo.getAttributeList().stream()
- .map(AttributeInfo::getName)
- .collect(toImmutableList());
- return summary(aspectName, attributeNames);
- }
-
- /**
- * Return a string representing the repository rule summary for the given repository rule with the
- * given name.
- *
- * <p>For example: 'my_repo_rule(foo, bar)'. The summary will contain hyperlinks for each
- * attribute.
- */
- @SuppressWarnings("unused") // Used by markdown template.
- public String repositoryRuleSummary(String ruleName, RepositoryRuleInfo ruleInfo) {
- ImmutableList<String> attributeNames =
- ruleInfo.getAttributeList().stream().map(AttributeInfo::getName).collect(toImmutableList());
- return summary(ruleName, attributeNames);
- }
-
- /**
- * Return a string representing the module extension summary for the given module extension with
- * the given name.
- *
- * <p>For example:
- *
- * <pre>
- * my_ext = use_extension("//some:file.bzl", "my_ext")
- * my_ext.tag1(foo, bar)
- * my_ext.tag2(baz)
- * </pre>
- *
- * <p>The summary will contain hyperlinks for each attribute.
- */
- @SuppressWarnings("unused") // Used by markdown template.
- public String moduleExtensionSummary(String extensionName, ModuleExtensionInfo extensionInfo) {
- StringBuilder summaryBuilder = new StringBuilder();
- summaryBuilder.append(
- String.format(
- "%s = use_extension(\"%s\", \"%s\")", extensionName, extensionBzlFile, extensionName));
- for (ModuleExtensionTagClassInfo tagClass : extensionInfo.getTagClassList()) {
- ImmutableList<String> attributeNames =
- tagClass.getAttributeList().stream()
- .map(AttributeInfo::getName)
- .collect(toImmutableList());
- summaryBuilder
- .append("\n")
- .append(
- summary(
- String.format("%s.%s", extensionName, tagClass.getTagName()), attributeNames));
- }
- return summaryBuilder.toString();
- }
-
- /**
- * Return a string representing the summary for the given user-defined function.
- *
- * <p>For example: 'my_func(foo, bar)'. The summary will contain hyperlinks for each parameter.
- */
- @SuppressWarnings("unused") // Used by markdown template.
- public String funcSummary(StarlarkFunctionInfo funcInfo) {
- ImmutableList<String> paramNames =
- funcInfo.getParameterList().stream()
- .map(FunctionParamInfo::getName)
- .collect(toImmutableList());
- return summary(funcInfo.getFunctionName(), paramNames);
- }
-
- private static String summary(String functionName, ImmutableList<String> paramNames) {
- ImmutableList<ImmutableList<String>> paramLines =
- wrap(functionName, paramNames, MAX_LINE_LENGTH);
- List<String> paramLinksLines = new ArrayList<>();
- for (List<String> params : paramLines) {
- String paramLinksLine =
- params.stream()
- .map(param -> String.format("<a href=\"#%s-%s\">%s</a>", functionName, param, param))
- .collect(joining(", "));
- paramLinksLines.add(paramLinksLine);
- }
- String paramList =
- Joiner.on(",\n" + " ".repeat(functionName.length() + 1)).join(paramLinksLines);
- return String.format("%s(%s)", functionName, paramList);
- }
-
- /**
- * Wraps the given function parameter names to be able to construct a function summary that stays
- * within the provided line length limit.
- *
- * @param functionName the function name.
- * @param paramNames the function parameter names.
- * @param maxLineLength the maximal line length.
- * @return the lines with the wrapped parameter names.
- */
- private static ImmutableList<ImmutableList<String>> wrap(
- String functionName, ImmutableList<String> paramNames, int maxLineLength) {
- ImmutableList.Builder<ImmutableList<String>> paramLines = ImmutableList.builder();
- ImmutableList.Builder<String> linesBuilder = new ImmutableList.Builder<>();
- int leading = functionName.length();
- int length = leading;
- int punctuation = 2; // cater for left parenthesis/space before and comma after parameter
- for (String paramName : paramNames) {
- length += paramName.length() + punctuation;
- if (length > maxLineLength) {
- paramLines.add(linesBuilder.build());
- length = leading + paramName.length();
- linesBuilder = new ImmutableList.Builder<>();
- }
- linesBuilder.add(paramName);
- }
- paramLines.add(linesBuilder.build());
- return paramLines.build();
- }
-
- /**
- * Returns a string describing the given attribute's type. The description consists of a hyperlink
- * if there is a relevant hyperlink to Bazel documentation available.
- */
- public String attributeTypeString(AttributeInfo attrInfo) {
- String typeLink;
- switch (attrInfo.getType()) {
- case LABEL:
- case LABEL_LIST:
- case OUTPUT:
- typeLink = "https://bazel.build/concepts/labels";
- break;
- case NAME:
- typeLink = "https://bazel.build/concepts/labels#target-names";
- break;
- case STRING_DICT:
- case STRING_LIST_DICT:
- case LABEL_STRING_DICT:
- typeLink = "https://bazel.build/rules/lib/dict";
- break;
- default:
- typeLink = null;
- break;
- }
- if (typeLink == null) {
- return attributeTypeDescription(attrInfo.getType());
- } else {
- return String.format(
- "<a href=\"%s\">%s</a>", typeLink, attributeTypeDescription(attrInfo.getType()));
- }
- }
-
- public String mandatoryString(AttributeInfo attrInfo) {
- return attrInfo.getMandatory() ? "required" : "optional";
- }
-
- /**
- * Returns "required" if providing a value for this parameter is mandatory. Otherwise, returns
- * "optional".
- */
- public String mandatoryString(FunctionParamInfo paramInfo) {
- return paramInfo.getMandatory() ? "required" : "optional";
- }
-
- /**
- * Return a string explaining what providers an attribute requires. Adds hyperlinks to providers.
- */
- public String attributeProviders(AttributeInfo attributeInfo) {
- List<ProviderNameGroup> providerNames = attributeInfo.getProviderNameGroupList();
- List<String> finalProviderNames = new ArrayList<>();
- for (ProviderNameGroup providerNameList : providerNames) {
- List<String> providers = providerNameList.getProviderNameList();
- finalProviderNames.add(Joiner.on(", ").join(providers));
- }
- return Joiner.on("; or ").join(finalProviderNames);
- }
-
- private static String attributeTypeDescription(AttributeType attributeType) {
- switch (attributeType) {
- case NAME:
- return "Name";
- case INT:
- return "Integer";
- case STRING:
- return "String";
- case STRING_LIST:
- return "List of strings";
- case INT_LIST:
- return "List of integers";
- case BOOLEAN:
- return "Boolean";
- case LABEL_STRING_DICT:
- return "Dictionary: Label -> String";
- case STRING_DICT:
- return "Dictionary: String -> String";
- case STRING_LIST_DICT:
- return "Dictionary: String -> List of strings";
- case LABEL:
- case OUTPUT:
- return "Label";
- case LABEL_LIST:
- case OUTPUT_LIST:
- return "List of labels";
- case UNKNOWN:
- case UNRECOGNIZED:
- throw new IllegalArgumentException("Unhandled type " + attributeType);
- }
- throw new IllegalArgumentException("Unhandled type " + attributeType);
- }
-}