Initial checkin of stardoc.bzl: a rewrite of skydoc (#105)


diff --git a/WORKSPACE b/WORKSPACE
index 581a3b2..ddbe4d5 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -11,6 +11,18 @@
     remote = "https://github.com/bazelbuild/bazel-skylib.git",
     tag = "0.2.0",
 )
+git_repository(
+    name = "io_bazel",
+    remote = "https://github.com/bazelbuild/bazel.git",
+    # TODO(cparsons): Depend on a release tag of bazel when there is
+    # a valid release containing an updated stardoc binary.
+    commit = "b749ab1f8549cdad0a574c356a57fe7181b07851",
+)
+http_archive(
+    name = "com_google_protobuf",
+    strip_prefix = "protobuf-3.5.1",
+    urls = ["https://github.com/google/protobuf/archive/v3.5.1.zip"],
+)
 
 load("@io_bazel_rules_sass//sass:sass.bzl", "sass_repositories")
 sass_repositories()
diff --git a/skylark/BUILD b/skylark/BUILD
index e37e9d1..1f9a828 100644
--- a/skylark/BUILD
+++ b/skylark/BUILD
@@ -4,11 +4,22 @@
 
 load("@bazel_skylib//:skylark_library.bzl", "skylark_library")
 load("//skylark:skylark.bzl", "skylark_doc")
+load("//skylark:stardoc.bzl", "stardoc")
 
 skylark_library(
     name = "skylark",
     srcs = ["skylark.bzl"],
-    deps = ["@bazel_skylib//:skylark_library"],
+    deps = [
+        "@bazel_skylib//:skylark_library"
+    ],
+)
+
+skylark_library(
+    name = "stardoc_lib",
+    srcs = ["stardoc.bzl"],
+    deps = [
+        "@bazel_skylib//:skylark_library",
+    ],
 )
 
 skylark_doc(
@@ -18,3 +29,11 @@
     strip_prefix = "skylark",
     deps = [":skylark"],
 )
+
+stardoc(
+    name = "stardoc_doc",
+    input = ":stardoc.bzl",
+    deps = [":stardoc_lib"],
+    symbol_names = ["stardoc"],
+    out = "stardoc_doc.md",
+)
diff --git a/skylark/stardoc.bzl b/skylark/stardoc.bzl
new file mode 100644
index 0000000..5046469
--- /dev/null
+++ b/skylark/stardoc.bzl
@@ -0,0 +1,77 @@
+# 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.
+
+"""Starlark rule for stardoc: a documentation generator tool written in Java."""
+
+load("@bazel_skylib//:skylark_library.bzl", "SkylarkLibraryInfo")
+
+def _stardoc_impl(ctx):
+    """Implementation of the stardoc rule."""
+    out_file = ctx.outputs.out
+    input_files = depset(direct = [ctx.file.input], transitive = [
+        dep[SkylarkLibraryInfo].transitive_srcs
+        for dep in ctx.attr.deps
+    ])
+    args = [
+        str(ctx.file.input.owner),
+        ctx.outputs.out.path,
+    ] + ctx.attr.symbol_names
+    stardoc = ctx.executable.stardoc
+    ctx.actions.run(
+        outputs = [out_file],
+        inputs = input_files,
+        executable = stardoc,
+        arguments = args,
+        mnemonic = "Stardoc",
+        progress_message = ("Generating Starlark doc for %s" %
+                            (ctx.label.name)),
+    )
+
+stardoc = rule(
+    _stardoc_impl,
+    doc = """
+Generates documentation for exported skylark rule definitions in a target starlark file.
+
+This rule is an experimental replacement for the existing skylark_doc rule.
+""",
+    attrs = {
+        "input": attr.label(
+            doc = "The starlark file to generate documentation for.",
+            allow_single_file = [".bzl"],
+        ),
+        "deps": attr.label_list(
+            doc = "A list of skylark_library dependencies which the input depends on.",
+            providers = [SkylarkLibraryInfo],
+        ),
+        "out": attr.output(
+            doc = "The (markdown) file to which documentation will be output.",
+            mandatory = True,
+        ),
+        "symbol_names": attr.string_list(
+            doc = """
+A list of symbol names to generate documentation for. These should correspond to
+the names of rule definitions in the input file. If this list is empty, then
+documentation for all exported rule definitions will be generated.
+""",
+            default = [],
+        ),
+        "stardoc": attr.label(
+            doc = "The location of the stardoc tool.",
+            allow_files = True,
+            default = Label("@io_bazel//src/main/java/com/google/devtools/build/skydoc"),
+            cfg = "host",
+            executable = True,
+        ),
+    },
+)
diff --git a/test/BUILD b/test/BUILD
new file mode 100644
index 0000000..50cda45
--- /dev/null
+++ b/test/BUILD
@@ -0,0 +1,14 @@
+licenses(["notice"])  # Apache 2.0
+
+sh_test(
+    name = "skydoc_self_gen_test",
+    srcs = ["diff_test_runner.sh"],
+    args = [
+        "$(location //skylark:stardoc_doc.md)",
+        "$(location :self_doc_golden.md)"
+    ],
+    data = [
+        "self_doc_golden.md",
+        "//skylark:stardoc_doc.md",
+    ],
+)
diff --git a/test/diff_test_runner.sh b/test/diff_test_runner.sh
new file mode 100755
index 0000000..0f4fa47
--- /dev/null
+++ b/test/diff_test_runner.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+#
+# 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.
+#
+# A shell test that the contents of an input file match a golden file.
+#
+# Usage: diff_test_runner.sh ACTUAL_FILE GOLDEN_FILE
+
+set -u
+
+actual_file=$1
+shift 1
+golden_file=$1
+shift 1
+
+DIFF="$(diff ${actual_file} ${golden_file})"
+
+if [ "$DIFF" != "" ]
+then
+    echo "FAIL: Actual did not match golden."
+    echo "${DIFF}"
+    exit 1
+else
+    echo "SUCCESS: Result matches golden file"
+fi
diff --git a/test/self_doc_golden.md b/test/self_doc_golden.md
new file mode 100755
index 0000000..98f1c42
--- /dev/null
+++ b/test/self_doc_golden.md
@@ -0,0 +1,81 @@
+<a name="#stardoc"></a>
+## stardoc
+
+<pre>
+stardoc(name, deps, input, out, stardoc, symbol_names)
+</pre>
+
+
+Generates documentation for exported skylark rule definitions in a target starlark file.
+
+This rule is an experimental replacement for the existing skylark_doc rule.
+
+
+### Attributes
+
+<table class="params-table">
+  <colgroup>
+    <col class="col-param" />
+    <col class="col-description" />
+  </colgroup>
+  <tbody>
+    <tr id="#stardoc_name">
+      <td><code>name</code></td>
+      <td>
+        String; required
+        <p>
+          A unique name for this rule.
+        </p>
+      </td>
+    </tr>
+    <tr id="#stardoc_deps">
+      <td><code>deps</code></td>
+      <td>
+        List of labels; optional
+        <p>
+          A list of skylark_library dependencies which the input depends on.
+        </p>
+      </td>
+    </tr>
+    <tr id="#stardoc_input">
+      <td><code>input</code></td>
+      <td>
+        Label; optional
+        <p>
+          The starlark file to generate documentation for.
+        </p>
+      </td>
+    </tr>
+    <tr id="#stardoc_out">
+      <td><code>out</code></td>
+      <td>
+        Label; required
+        <p>
+          The (markdown) file to which documentation will be output.
+        </p>
+      </td>
+    </tr>
+    <tr id="#stardoc_stardoc">
+      <td><code>stardoc</code></td>
+      <td>
+        Label; optional
+        <p>
+          The location of the stardoc tool.
+        </p>
+      </td>
+    </tr>
+    <tr id="#stardoc_symbol_names">
+      <td><code>symbol_names</code></td>
+      <td>
+        List of strings; optional
+        <p>
+          A list of symbol names to generate documentation for. These should correspond to
+the names of rule definitions in the input file. If this list is empty, then
+documentation for all exported rule definitions will be generated.
+        </p>
+      </td>
+    </tr>
+  </tbody>
+</table>
+
+