diff options
Diffstat (limited to 'src/main/java/com/google')
19 files changed, 997 insertions, 11 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java index e85915f3b9..85e3b9786e 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java @@ -415,12 +415,12 @@ public class SkylarkRuleClassFunctions implements SkylarkRuleFunctionsApi<Artifa @Override public SkylarkAspect aspect( BaseFunction implementation, - SkylarkList attributeAspects, + SkylarkList<?> attributeAspects, Object attrs, - SkylarkList requiredAspectProvidersArg, - SkylarkList providesArg, - SkylarkList fragments, - SkylarkList hostFragments, + SkylarkList<?> requiredAspectProvidersArg, + SkylarkList<?> providesArg, + SkylarkList<?> fragments, + SkylarkList<?> hostFragments, SkylarkList<?> toolchains, String doc, FuncallExpression ast, diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkAttrApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkAttrApi.java index d9e0bebba5..edc3fb8165 100644 --- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkAttrApi.java +++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkAttrApi.java @@ -792,7 +792,7 @@ public interface SkylarkAttrApi extends SkylarkValue { useEnvironment = true) public Descriptor outputListAttribute( Boolean allowEmpty, - SkylarkList defaultList, + SkylarkList<?> defaultList, String doc, Boolean mandatory, Boolean nonEmpty, diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkRuleFunctionsApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkRuleFunctionsApi.java index 1f7a7e0dd6..84abfe1bce 100644 --- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkRuleFunctionsApi.java +++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkRuleFunctionsApi.java @@ -429,12 +429,12 @@ public interface SkylarkRuleFunctionsApi<FileApiT extends FileApi> { ) public SkylarkAspectApi aspect( BaseFunction implementation, - SkylarkList attributeAspects, + SkylarkList<?> attributeAspects, Object attrs, - SkylarkList requiredAspectProvidersArg, - SkylarkList providesArg, - SkylarkList fragments, - SkylarkList hostFragments, + SkylarkList<?> requiredAspectProvidersArg, + SkylarkList<?> providesArg, + SkylarkList<?> fragments, + SkylarkList<?> hostFragments, SkylarkList<?> toolchains, String doc, FuncallExpression ast, diff --git a/src/main/java/com/google/devtools/build/skydoc/BUILD b/src/main/java/com/google/devtools/build/skydoc/BUILD new file mode 100644 index 0000000000..d3bcf4b101 --- /dev/null +++ b/src/main/java/com/google/devtools/build/skydoc/BUILD @@ -0,0 +1,44 @@ +# Description: +# Skydoc is a documentation generator for skylark files. +# +# It is currently experimental and in development. +# +# Usage: +# skydoc <target_file> <output_file> + +package( + default_visibility = ["//src:__subpackages__"], +) + +licenses(["notice"]) # Apache 2.0 + +filegroup( + name = "srcs", + srcs = glob(["**"]) + [ + "//src/main/java/com/google/devtools/build/skydoc/fakebuildapi:srcs", + "//src/main/java/com/google/devtools/build/skydoc/rendering:srcs", + ], +) + +java_binary( + name = "skydoc", + main_class = "com.google.devtools.build.skydoc.SkydocMain", + runtime_deps = [ + ":skydoc_lib", + ], +) + +java_library( + name = "skydoc_lib", + srcs = glob(["*.java"]), + deps = [ + "//src/main/java/com/google/devtools/build/lib:events", + "//src/main/java/com/google/devtools/build/lib:syntax", + "//src/main/java/com/google/devtools/build/lib/skylarkbuildapi", + "//src/main/java/com/google/devtools/build/lib/vfs:pathfragment", + "//src/main/java/com/google/devtools/build/skydoc/fakebuildapi", + "//src/main/java/com/google/devtools/build/skydoc/rendering", + "//third_party:guava", + "//third_party:jsr305", + ], +) diff --git a/src/main/java/com/google/devtools/build/skydoc/SkydocMain.java b/src/main/java/com/google/devtools/build/skydoc/SkydocMain.java new file mode 100644 index 0000000000..1e14cc1a16 --- /dev/null +++ b/src/main/java/com/google/devtools/build/skydoc/SkydocMain.java @@ -0,0 +1,190 @@ +// 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; + +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.common.collect.ImmutableMap; +import com.google.devtools.build.lib.events.EventHandler; +import com.google.devtools.build.lib.events.Location; +import com.google.devtools.build.lib.skylarkbuildapi.TopLevelBootstrap; +import com.google.devtools.build.lib.syntax.BuildFileAST; +import com.google.devtools.build.lib.syntax.Environment; +import com.google.devtools.build.lib.syntax.Environment.Extension; +import com.google.devtools.build.lib.syntax.Environment.GlobalFrame; +import com.google.devtools.build.lib.syntax.MethodLibrary; +import com.google.devtools.build.lib.syntax.Mutability; +import com.google.devtools.build.lib.syntax.ParserInputSource; +import com.google.devtools.build.lib.syntax.Runtime; +import com.google.devtools.build.lib.vfs.PathFragment; +import com.google.devtools.build.skydoc.fakebuildapi.FakeActionsInfoProvider; +import com.google.devtools.build.skydoc.fakebuildapi.FakeBuildApiGlobals; +import com.google.devtools.build.skydoc.fakebuildapi.FakeDefaultInfoProvider; +import com.google.devtools.build.skydoc.fakebuildapi.FakeOutputGroupInfo.FakeOutputGroupInfoProvider; +import com.google.devtools.build.skydoc.fakebuildapi.FakeSkylarkAttrApi; +import com.google.devtools.build.skydoc.fakebuildapi.FakeSkylarkCommandLineApi; +import com.google.devtools.build.skydoc.fakebuildapi.FakeSkylarkNativeModuleApi; +import com.google.devtools.build.skydoc.fakebuildapi.FakeSkylarkRuleFunctionsApi; +import com.google.devtools.build.skydoc.fakebuildapi.FakeStructApi.FakeStructProviderApi; +import com.google.devtools.build.skydoc.rendering.RuleInfo; +import java.io.IOException; +import java.io.PrintWriter; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Main entry point for the Skydoc binary. + * + * <p>Skydoc generates human-readable documentation for relevant details of skylark files by + * running a skylark interpreter with a fake implementation of the build API.</p> + * + * <p>Currently, Skydoc generates documentation for skylark rule definitions (discovered by + * invocations of the build API function {@code rule()}.</p> + * + * <p>Usage:</p> + * <pre> + * skydoc {target_skylark_file} {output_file} + * </pre> + */ +public class SkydocMain { + + // Pattern to match the assignment of a variable to a rule definition + // For example, 'my_rule = rule(' will match and have 'my_rule' available as group(1). + private static final Pattern ruleDefinitionLinePattern = + Pattern.compile("([^\\s]+) = rule\\("); + + private final EventHandler eventHandler = new SystemOutEventHandler(); + + public static void main(String[] args) throws IOException, InterruptedException { + if (args.length != 2) { + throw new IllegalArgumentException("Expected two arguments. Usage:\n" + + "{skydoc_bin} {target_skylark_file} {output_file}"); + } + + String bzlPath = args[0]; + String outputPath = args[1]; + + Path path = Paths.get(bzlPath); + byte[] content = Files.readAllBytes(path); + + ParserInputSource parserInputSource = + ParserInputSource.create(content, PathFragment.create(path.toString())); + + List<RuleInfo> ruleInfoList = new SkydocMain().eval(parserInputSource); + + try (PrintWriter printWriter = new PrintWriter(outputPath, "UTF-8")) { + printRuleInfos(printWriter, ruleInfoList); + } + } + + // TODO(cparsons): Improve output (markdown or HTML). + private static void printRuleInfos( + PrintWriter printWriter, List<RuleInfo> ruleInfos) throws IOException { + for (RuleInfo ruleInfo : ruleInfos) { + Location location = ruleInfo.getLocation(); + Path filePath = Paths.get(location.getPath().getPathString()); + List<String> lines = Files.readAllLines(filePath, UTF_8); + String definingString = lines.get(location.getStartLine() - 1); + // Rule definitions don't specify their own visible name directly. Instead, the name of + // a rule is dependent on the name of the variable assigend to the return value of rule(). + // This attempts to find a line of the form 'foo = rule(' and thus label the rule as + // named 'foo'. + // TODO(cparsons): Inspect the global bindings of the environment instead of using string + // matching. + Matcher matcher = ruleDefinitionLinePattern.matcher(definingString); + if (matcher.matches()) { + printWriter.println(matcher.group(1)); + } else { + printWriter.println("<unknown name>"); + } + printWriter.println(ruleInfo.getDescription()); + } + } + + /** + * Evaluates/interprets the skylark file at the given input source using a fake build API and + * collects information about all rule definitions made in that file. + * + * @param parserInputSource the input source representing the input skylark file + * @return a list of {@link RuleInfo} objects describing the rule definitions + * @throws InterruptedException if evaluation is interrupted + */ + // TODO(cparsons): Evaluate load statements recursively. + public List<RuleInfo> eval(ParserInputSource parserInputSource) + throws InterruptedException { + List<RuleInfo> ruleInfoList = new ArrayList<>(); + + BuildFileAST buildFileAST = BuildFileAST.parseSkylarkFile( + parserInputSource, eventHandler); + + Environment env = createEnvironment( + eventHandler, + globalFrame(ruleInfoList), + /* imports= */ ImmutableMap.of()); + + if (!buildFileAST.exec(env, eventHandler)) { + throw new RuntimeException("Error loading file"); + } + + env.mutability().freeze(); + + return ruleInfoList; + } + + /** + * Initialize and return a global frame containing the fake build API. + * + * @param ruleInfoList the list of {@link RuleInfo} objects, to which rule() invocation + * information will be added + */ + private static GlobalFrame globalFrame(List<RuleInfo> ruleInfoList) { + // TODO(cparsons): Complete the Fake Build API stubs. For example, implement provider(), + // and include the other bootstraps. + TopLevelBootstrap topLevelBootstrap = + new TopLevelBootstrap(new FakeBuildApiGlobals(), + new FakeSkylarkAttrApi(), + new FakeSkylarkCommandLineApi(), + new FakeSkylarkNativeModuleApi(), + new FakeSkylarkRuleFunctionsApi(ruleInfoList), + new FakeStructProviderApi(), + new FakeOutputGroupInfoProvider(), + new FakeActionsInfoProvider(), + new FakeDefaultInfoProvider()); + + ImmutableMap.Builder<String, Object> envBuilder = ImmutableMap.builder(); + + Runtime.addConstantsToBuilder(envBuilder); + MethodLibrary.addBindingsToBuilder(envBuilder); + topLevelBootstrap.addBindingsToBuilder(envBuilder); + + return GlobalFrame.createForBuiltins(envBuilder.build()); + } + + private static Environment createEnvironment(EventHandler eventHandler, GlobalFrame globals, + Map<String, Extension> imports) { + return Environment.builder(Mutability.create("Skydoc")) + .useDefaultSemantics() + .setGlobals(globals) + .setImportedExtensions(imports) + .setEventHandler(eventHandler) + .build(); + } +} diff --git a/src/main/java/com/google/devtools/build/skydoc/SystemOutEventHandler.java b/src/main/java/com/google/devtools/build/skydoc/SystemOutEventHandler.java new file mode 100644 index 0000000000..8d45627276 --- /dev/null +++ b/src/main/java/com/google/devtools/build/skydoc/SystemOutEventHandler.java @@ -0,0 +1,50 @@ +// 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; + +import com.google.devtools.build.lib.events.Event; +import com.google.devtools.build.lib.events.EventHandler; + +/** + * A simple {@link EventHandler} which outputs log information to system.out and system.err. + */ +class SystemOutEventHandler implements EventHandler { + + @Override + public void handle(Event event) { + switch (event.getKind()) { + case ERROR: + case WARNING: + case STDERR: + System.err.println(messageWithLocation(event)); + break; + case DEBUG: + case INFO: + case PROGRESS: + case STDOUT: + System.out.println(messageWithLocation(event)); + break; + default: + System.err.println("Unknown message type: " + event); + } + } + + private String messageWithLocation(Event event) { + String location = event.getLocation() == null + ? "<no location>" + : event.getLocation().print(); + return location + ": " + event.getMessage(); + } +} diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/BUILD b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/BUILD new file mode 100644 index 0000000000..766f404582 --- /dev/null +++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/BUILD @@ -0,0 +1,25 @@ +package( + default_visibility = ["//src:__subpackages__"], +) + +licenses(["notice"]) # Apache 2.0 + +filegroup( + name = "srcs", + srcs = glob(["**"]), +) + +java_library( + name = "fakebuildapi", + srcs = glob(["*.java"]), + deps = [ + "//src/main/java/com/google/devtools/build/lib:events", + "//src/main/java/com/google/devtools/build/lib:skylarkinterface", + "//src/main/java/com/google/devtools/build/lib:syntax", + "//src/main/java/com/google/devtools/build/lib/cmdline", + "//src/main/java/com/google/devtools/build/lib/skylarkbuildapi", + "//src/main/java/com/google/devtools/build/skydoc/rendering", + "//third_party:guava", + "//third_party:jsr305", + ], +) diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeActionsInfoProvider.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeActionsInfoProvider.java new file mode 100644 index 0000000000..b8643e30e8 --- /dev/null +++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeActionsInfoProvider.java @@ -0,0 +1,27 @@ +// 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.fakebuildapi; + +import com.google.devtools.build.lib.skylarkbuildapi.ActionsInfoProviderApi; +import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter; + +/** + * Fake implementation of {@link ActionsInfoProviderApi}. + */ +public class FakeActionsInfoProvider implements ActionsInfoProviderApi { + + @Override + public void repr(SkylarkPrinter printer) {} +} diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeBuildApiGlobals.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeBuildApiGlobals.java new file mode 100644 index 0000000000..d523070517 --- /dev/null +++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeBuildApiGlobals.java @@ -0,0 +1,33 @@ +// 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.fakebuildapi; + +import com.google.devtools.build.lib.events.Location; +import com.google.devtools.build.lib.skylarkbuildapi.LateBoundDefaultApi; +import com.google.devtools.build.lib.skylarkbuildapi.SkylarkBuildApiGlobals; +import com.google.devtools.build.lib.syntax.Environment; +import com.google.devtools.build.lib.syntax.EvalException; + +/** + * Fake implementation of {@link FakeBuildApiGlobals}. + */ +public class FakeBuildApiGlobals implements SkylarkBuildApiGlobals { + + @Override + public LateBoundDefaultApi configurationField(String fragment, String name, Location loc, + Environment env) throws EvalException { + return null; + } +} diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeDefaultInfoProvider.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeDefaultInfoProvider.java new file mode 100644 index 0000000000..1f5eacfaa3 --- /dev/null +++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeDefaultInfoProvider.java @@ -0,0 +1,38 @@ +// 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.fakebuildapi; + +import com.google.devtools.build.lib.events.Location; +import com.google.devtools.build.lib.skylarkbuildapi.DefaultInfoApi; +import com.google.devtools.build.lib.skylarkbuildapi.DefaultInfoApi.DefaultInfoApiProvider; +import com.google.devtools.build.lib.skylarkbuildapi.FileApi; +import com.google.devtools.build.lib.skylarkbuildapi.RunfilesApi; +import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter; +import com.google.devtools.build.lib.syntax.EvalException; + +/** + * Fake implementation of {@link DefaultInfoApiProvider}. + */ +public class FakeDefaultInfoProvider implements DefaultInfoApiProvider<RunfilesApi, FileApi> { + + @Override + public DefaultInfoApi constructor(Object files, Object runfiles, Object dataRunfiles, + Object defaultRunfiles, Object executable, Location loc) throws EvalException { + return null; + } + + @Override + public void repr(SkylarkPrinter printer) {} +} diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeDescriptor.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeDescriptor.java new file mode 100644 index 0000000000..77c912d6b8 --- /dev/null +++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeDescriptor.java @@ -0,0 +1,30 @@ +// 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.fakebuildapi; + +import com.google.devtools.build.lib.skylarkbuildapi.SkylarkAttrApi.Descriptor; +import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter; + +/** + * Fake implementation of {@link Descriptor}. + */ +public class FakeDescriptor implements Descriptor { + + @Override + public void repr(SkylarkPrinter printer) {} + + // TODO(cparsons): This class should store information about the attribute definition, for + // example, the attribute type. +}
\ No newline at end of file diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeOutputGroupInfo.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeOutputGroupInfo.java new file mode 100644 index 0000000000..79b7014f9a --- /dev/null +++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeOutputGroupInfo.java @@ -0,0 +1,57 @@ +// 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.fakebuildapi; + +import com.google.devtools.build.lib.events.Location; +import com.google.devtools.build.lib.skylarkbuildapi.OutputGroupInfoApi; +import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter; +import com.google.devtools.build.lib.syntax.EvalException; +import com.google.devtools.build.lib.syntax.SkylarkDict; + +/** + * Fake implementation of {@link OutputGroupInfoApi}. + */ +public class FakeOutputGroupInfo implements OutputGroupInfoApi { + + @Override + public String toProto(Location loc) throws EvalException { + return ""; + } + + @Override + public String toJson(Location loc) throws EvalException { + return ""; + } + + @Override + public void repr(SkylarkPrinter printer) { + + } + + /** + * Fake implementation of {@link OutputGroupInfoApiProvider}. + */ + public static class FakeOutputGroupInfoProvider implements OutputGroupInfoApiProvider { + + @Override + public OutputGroupInfoApi constructor(SkylarkDict<?, ?> kwargs, Location loc) + throws EvalException { + return new FakeOutputGroupInfo(); + } + + @Override + public void repr(SkylarkPrinter printer) {} + } +} diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkAttrApi.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkAttrApi.java new file mode 100644 index 0000000000..f9e5f8c5c5 --- /dev/null +++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkAttrApi.java @@ -0,0 +1,121 @@ +// 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.fakebuildapi; + +import com.google.devtools.build.lib.skylarkbuildapi.SkylarkAttrApi; +import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter; +import com.google.devtools.build.lib.syntax.Environment; +import com.google.devtools.build.lib.syntax.EvalException; +import com.google.devtools.build.lib.syntax.FuncallExpression; +import com.google.devtools.build.lib.syntax.SkylarkDict; +import com.google.devtools.build.lib.syntax.SkylarkList; + +/** + * Fake implementation of {@link SkylarkAttrApi}. + */ +public class FakeSkylarkAttrApi implements SkylarkAttrApi { + + @Override + public Descriptor intAttribute(Integer defaultInt, String doc, Boolean mandatory, + SkylarkList<?> values, FuncallExpression ast, Environment env) throws EvalException { + return new FakeDescriptor(); + } + + @Override + public Descriptor stringAttribute(String defaultString, String doc, Boolean mandatory, + SkylarkList<?> values, FuncallExpression ast, Environment env) throws EvalException { + return new FakeDescriptor(); + } + + @Override + public Descriptor labelAttribute(Object defaultO, String doc, Boolean executable, + Object allowFiles, Object allowSingleFile, Boolean mandatory, SkylarkList<?> providers, + Object allowRules, Boolean singleFile, Object cfg, SkylarkList<?> aspects, + FuncallExpression ast, Environment env) throws EvalException { + return new FakeDescriptor(); + } + + @Override + public Descriptor stringListAttribute(Boolean mandatory, Boolean nonEmpty, Boolean allowEmpty, + SkylarkList<?> defaultList, String doc, FuncallExpression ast, Environment env) + throws EvalException { + return new FakeDescriptor(); + } + + @Override + public Descriptor intListAttribute(Boolean mandatory, Boolean nonEmpty, Boolean allowEmpty, + SkylarkList<?> defaultList, String doc, FuncallExpression ast, Environment env) + throws EvalException { + return new FakeDescriptor(); + } + + @Override + public Descriptor labelListAttribute(Boolean allowEmpty, Object defaultList, String doc, + Object allowFiles, Object allowRules, SkylarkList<?> providers, SkylarkList<?> flags, + Boolean mandatory, Boolean nonEmpty, Object cfg, SkylarkList<?> aspects, + FuncallExpression ast, Environment env) throws EvalException { + return new FakeDescriptor(); + } + + @Override + public Descriptor labelKeyedStringDictAttribute(Boolean allowEmpty, Object defaultList, + String doc, Object allowFiles, Object allowRules, SkylarkList<?> providers, + SkylarkList<?> flags, Boolean mandatory, Boolean nonEmpty, Object cfg, SkylarkList<?> aspects, + FuncallExpression ast, Environment env) throws EvalException { + return new FakeDescriptor(); + } + + @Override + public Descriptor boolAttribute(Boolean defaultO, String doc, Boolean mandatory, + FuncallExpression ast, Environment env) throws EvalException { + return new FakeDescriptor(); + } + + @Override + public Descriptor outputAttribute(Object defaultO, String doc, Boolean mandatory, + FuncallExpression ast, Environment env) throws EvalException { + return new FakeDescriptor(); + } + + @Override + public Descriptor outputListAttribute(Boolean allowEmpty, SkylarkList<?> defaultList, String doc, + Boolean mandatory, Boolean nonEmpty, FuncallExpression ast, Environment env) + throws EvalException { + return new FakeDescriptor(); + } + + @Override + public Descriptor stringDictAttribute(Boolean allowEmpty, SkylarkDict<?, ?> defaultO, String doc, + Boolean mandatory, Boolean nonEmpty, FuncallExpression ast, Environment env) + throws EvalException { + return new FakeDescriptor(); + } + + @Override + public Descriptor stringListDictAttribute(Boolean allowEmpty, SkylarkDict<?, ?> defaultO, + String doc, Boolean mandatory, Boolean nonEmpty, FuncallExpression ast, Environment env) + throws EvalException { + return new FakeDescriptor(); + } + + @Override + public Descriptor licenseAttribute(Object defaultO, String doc, Boolean mandatory, + FuncallExpression ast, Environment env) throws EvalException { + return new FakeDescriptor(); + } + + @Override + public void repr(SkylarkPrinter printer) {} +} diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkCommandLineApi.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkCommandLineApi.java new file mode 100644 index 0000000000..8c114610c1 --- /dev/null +++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkCommandLineApi.java @@ -0,0 +1,29 @@ +// 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.fakebuildapi; + +import com.google.devtools.build.lib.skylarkbuildapi.SkylarkCommandLineApi; +import com.google.devtools.build.lib.syntax.SkylarkNestedSet; + +/** + * Fake implementation of {@link SkylarkCommandLineApi}. + */ +public class FakeSkylarkCommandLineApi implements SkylarkCommandLineApi { + + @Override + public String joinPaths(String separator, SkylarkNestedSet files) { + return ""; + } +} diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkNativeModuleApi.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkNativeModuleApi.java new file mode 100644 index 0000000000..22fa94e3e4 --- /dev/null +++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkNativeModuleApi.java @@ -0,0 +1,72 @@ +// 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.fakebuildapi; + +import com.google.devtools.build.lib.events.Location; +import com.google.devtools.build.lib.skylarkbuildapi.SkylarkNativeModuleApi; +import com.google.devtools.build.lib.syntax.Environment; +import com.google.devtools.build.lib.syntax.EvalException; +import com.google.devtools.build.lib.syntax.FuncallExpression; +import com.google.devtools.build.lib.syntax.Runtime.NoneType; +import com.google.devtools.build.lib.syntax.SkylarkDict; +import com.google.devtools.build.lib.syntax.SkylarkList; +import com.google.devtools.build.lib.syntax.SkylarkList.MutableList; + +/** + * Fake implementation of {@link SkylarkNativeModuleApi}. + */ +public class FakeSkylarkNativeModuleApi implements SkylarkNativeModuleApi { + + @Override + public SkylarkList<?> glob(SkylarkList<?> include, SkylarkList<?> exclude, + Integer excludeDirectories, FuncallExpression ast, Environment env) + throws EvalException, InterruptedException { + return MutableList.of(env); + } + + @Override + public Object existingRule(String name, FuncallExpression ast, Environment env) + throws EvalException, InterruptedException { + return null; + } + + @Override + public SkylarkDict<String, SkylarkDict<String, Object>> existingRules(FuncallExpression ast, + Environment env) throws EvalException, InterruptedException { + return SkylarkDict.of(env); + } + + @Override + public NoneType packageGroup(String name, SkylarkList<?> packages, SkylarkList<?> includes, + FuncallExpression ast, Environment env) throws EvalException { + return null; + } + + @Override + public NoneType exportsFiles(SkylarkList<?> srcs, Object visibility, Object licenses, + FuncallExpression ast, Environment env) throws EvalException { + return null; + } + + @Override + public String packageName(FuncallExpression ast, Environment env) throws EvalException { + return ""; + } + + @Override + public String repositoryName(Location location, Environment env) throws EvalException { + return ""; + } +} diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkRuleFunctionsApi.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkRuleFunctionsApi.java new file mode 100644 index 0000000000..dcae202abc --- /dev/null +++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkRuleFunctionsApi.java @@ -0,0 +1,103 @@ +// 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.fakebuildapi; + +import com.google.common.collect.ImmutableSet; +import com.google.devtools.build.lib.cmdline.Label; +import com.google.devtools.build.lib.events.Location; +import com.google.devtools.build.lib.skylarkbuildapi.FileApi; +import com.google.devtools.build.lib.skylarkbuildapi.FileTypeApi; +import com.google.devtools.build.lib.skylarkbuildapi.ProviderApi; +import com.google.devtools.build.lib.skylarkbuildapi.SkylarkAspectApi; +import com.google.devtools.build.lib.skylarkbuildapi.SkylarkAttrApi.Descriptor; +import com.google.devtools.build.lib.skylarkbuildapi.SkylarkRuleFunctionsApi; +import com.google.devtools.build.lib.syntax.BaseFunction; +import com.google.devtools.build.lib.syntax.Environment; +import com.google.devtools.build.lib.syntax.EvalException; +import com.google.devtools.build.lib.syntax.FuncallExpression; +import com.google.devtools.build.lib.syntax.SkylarkDict; +import com.google.devtools.build.lib.syntax.SkylarkList; +import com.google.devtools.build.skydoc.rendering.RuleInfo; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Fake implementation of {@link SkylarkRuleFunctionsApi}. + * + * <p>This fake hooks into the global {@code rule()} function, noting calls of that function + * with a {@link RuleInfoCollector} given in the class constructor.</p> + */ +public class FakeSkylarkRuleFunctionsApi implements SkylarkRuleFunctionsApi<FileApi> { + + private final List<RuleInfo> ruleInfoList; + + /** + * Constructor. + * + * @param ruleInfoList the list of {@link RuleInfo} objects to which rule() invocation information + * will be added + */ + public FakeSkylarkRuleFunctionsApi(List<RuleInfo> ruleInfoList) { + this.ruleInfoList = ruleInfoList; + } + + @Override + public ProviderApi provider(String doc, Object fields, Location location) throws EvalException { + return null; + } + + @Override + public BaseFunction rule(BaseFunction implementation, Boolean test, Object attrs, + Object implicitOutputs, Boolean executable, Boolean outputToGenfiles, + SkylarkList<?> fragments, SkylarkList<?> hostFragments, Boolean skylarkTestable, + SkylarkList<?> toolchains, String doc, SkylarkList<?> providesArg, + Boolean executionPlatformConstraintsAllowed, SkylarkList<?> execCompatibleWith, + FuncallExpression ast, Environment funcallEnv) throws EvalException { + Set<String> attrNames; + if (attrs != null) { + SkylarkDict<?, ?> attrsDict = (SkylarkDict<?, ?>) attrs; + Map<String, Descriptor> attrsMap = + attrsDict.getContents(String.class, Descriptor.class, "attrs"); + attrNames = attrsMap.keySet(); + } else { + attrNames = ImmutableSet.of(); + } + + // TODO(cparsons): Improve details given to RuleInfo (for example, attribute types). + ruleInfoList.add(new RuleInfo(ast.getLocation(), doc, attrNames)); + return implementation; + } + + @Override + public Label label(String labelString, Boolean relativeToCallerRepository, Location loc, + Environment env) throws EvalException { + return null; + } + + @Override + public FileTypeApi<FileApi> fileType(SkylarkList<?> types, Location loc, Environment env) + throws EvalException { + return null; + } + + @Override + public SkylarkAspectApi aspect(BaseFunction implementation, SkylarkList<?> attributeAspects, + Object attrs, SkylarkList<?> requiredAspectProvidersArg, SkylarkList<?> providesArg, + SkylarkList<?> fragments, SkylarkList<?> hostFragments, SkylarkList<?> toolchains, String doc, + FuncallExpression ast, Environment funcallEnv) throws EvalException { + return null; + } +} diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeStructApi.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeStructApi.java new file mode 100644 index 0000000000..abdea383f6 --- /dev/null +++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeStructApi.java @@ -0,0 +1,88 @@ +// 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.fakebuildapi; + +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.devtools.build.lib.events.Location; +import com.google.devtools.build.lib.skylarkbuildapi.StructApi; +import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter; +import com.google.devtools.build.lib.syntax.ClassObject; +import com.google.devtools.build.lib.syntax.EvalException; +import com.google.devtools.build.lib.syntax.SkylarkDict; +import java.util.Map; +import javax.annotation.Nullable; + +/** + * Fake implementation of {@link StructApi}. + */ +public class FakeStructApi implements StructApi, ClassObject { + + private final Map<String, Object> objects; + + public FakeStructApi(Map<String, Object> objects) { + this.objects = objects; + } + + public FakeStructApi() { + this(ImmutableMap.of()); + } + + @Override + public String toProto(Location loc) throws EvalException { + return ""; + } + + @Override + public String toJson(Location loc) throws EvalException { + return ""; + } + + @Override + public void repr(SkylarkPrinter printer) {} + + @Nullable + @Override + public Object getValue(String name) throws EvalException { + return objects.get(name); + } + + @Override + public ImmutableCollection<String> getFieldNames() throws EvalException { + return ImmutableList.of(); + } + + @Nullable + @Override + public String getErrorMessageForUnknownField(String field) { + return ""; + } + + /** + * Fake implementation of {@link StructProviderApi}. + */ + public static class FakeStructProviderApi implements StructProviderApi { + + @Override + public StructApi createStruct(SkylarkDict<?, ?> kwargs, Location loc) throws EvalException { + return new FakeStructApi(kwargs.getContents(String.class, Object.class, "kwargs")); + } + + @Override + public void repr(SkylarkPrinter printer) {} + } +} + diff --git a/src/main/java/com/google/devtools/build/skydoc/rendering/BUILD b/src/main/java/com/google/devtools/build/skydoc/rendering/BUILD new file mode 100644 index 0000000000..13f2cc9edd --- /dev/null +++ b/src/main/java/com/google/devtools/build/skydoc/rendering/BUILD @@ -0,0 +1,21 @@ +package( + default_visibility = ["//src:__subpackages__"], +) + +licenses(["notice"]) # Apache 2.0 + +filegroup( + name = "srcs", + srcs = glob(["**"]), +) + +java_library( + name = "rendering", + srcs = glob(["*.java"]), + deps = [ + "//src/main/java/com/google/devtools/build/lib:events", + "//src/main/java/com/google/devtools/build/lib:skylarkinterface", + "//third_party:guava", + "//third_party:jsr305", + ], +) diff --git a/src/main/java/com/google/devtools/build/skydoc/rendering/RuleInfo.java b/src/main/java/com/google/devtools/build/skydoc/rendering/RuleInfo.java new file mode 100644 index 0000000000..0d8a150dfc --- /dev/null +++ b/src/main/java/com/google/devtools/build/skydoc/rendering/RuleInfo.java @@ -0,0 +1,58 @@ +// 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 com.google.common.base.Joiner; +import com.google.common.base.Strings; +import com.google.devtools.build.lib.events.Location; +import java.util.Collection; + +/** + * Stores information about a skylark rule definition. + */ +public class RuleInfo { + + private final Location location; + private final String docString; + private final Collection<String> attrNames; + + public RuleInfo(Location location, String docString, Collection<String> attrNames) { + this.location = location; + this.docString = docString; + this.attrNames = attrNames; + } + + public Location getLocation() { + return location; + } + + public String getDocString() { + return docString; + } + + public Collection<String> getAttrNames() { + return attrNames; + } + + public String getDescription() { + StringBuilder stringBuilder = new StringBuilder(); + if (!Strings.isNullOrEmpty(docString)) { + stringBuilder.append(docString); + stringBuilder.append("\n"); + } + Joiner.on(",").appendTo(stringBuilder, attrNames); + return stringBuilder.toString(); + } +} |