diff options
Diffstat (limited to 'src/main/java/com/google')
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 <brackets>'. - */ - public static String htmlEscape(String docString) { - return docString.replace("<", "<").replace(">", ">"); - } - - /** Returns a string that escapes newlines with HTML entities. */ - private static String newlineEscape(String docString) { - return docString.replace("\n", " "); - } - - 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); - } -} |