aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYifan Hong <elsk@google.com>2023-12-07 16:07:33 -0800
committerMatthias Männich <maennich@google.com>2023-12-08 15:07:09 +0000
commit16b44b4e060da38bf5613220593fc48350a0aa80 (patch)
tree67a8bb59932347f2f12a853a20c14517dcb35fc8
parent85b0f239303220d902ad919ff27d2da475fc12e2 (diff)
parent99421bbcd3f00f600d4bf3f14ef5917c5b671f8c (diff)
downloadstardoc-16b44b4e060da38bf5613220593fc48350a0aa80.tar.gz
Merge tag 'upstream/0.6.2' into main
Bug: 276493276 Change-Id: Ia35937702bbf7634a760801e6cf0c3d28d4436de
-rw-r--r--.bazelci/presubmit.yml81
-rw-r--r--.bazelignore1
-rw-r--r--.gitignore1
-rw-r--r--BUILD32
-rw-r--r--CHANGELOG.md130
-rw-r--r--METADATA4
-rw-r--r--MODULE.bazel33
-rw-r--r--WORKSPACE94
-rw-r--r--deps.bzl54
-rw-r--r--distro/BUILD3
-rw-r--r--docs/contributing.md6
-rw-r--r--docs/maintainers_guide.md104
-rw-r--r--docs/stardoc_rule.md57
-rw-r--r--legacy_maven_install.json529
-rw-r--r--maven_install.json266
-rw-r--r--rules_jvm_external.patch142
-rw-r--r--setup.bzl81
-rw-r--r--src/main/java/com/google/devtools/build/skydoc/renderer/BUILD45
-rw-r--r--src/main/java/com/google/devtools/build/skydoc/renderer/FileSystemAccessor.java45
-rw-r--r--src/main/java/com/google/devtools/build/skydoc/renderer/ProtoFileAccessor.java42
-rw-r--r--src/main/java/com/google/devtools/build/skydoc/renderer/RendererMain.java260
-rw-r--r--src/main/java/com/google/devtools/build/skydoc/renderer/RendererOptions.java83
-rw-r--r--src/main/java/com/google/devtools/build/skydoc/rendering/BUILD27
-rw-r--r--src/main/java/com/google/devtools/build/skydoc/rendering/MarkdownRenderer.java223
-rw-r--r--src/main/java/com/google/devtools/build/skydoc/rendering/MarkdownUtil.java443
-rw-r--r--src/test/java/com/google/devtools/build/skydoc/rendering/BUILD27
-rw-r--r--src/test/java/com/google/devtools/build/skydoc/rendering/MarkdownUtilTest.java84
-rw-r--r--stardoc/BUILD42
-rw-r--r--stardoc/html_tables_stardoc.bzl2
-rw-r--r--stardoc/private/BUILD18
-rw-r--r--stardoc/private/stardoc.bzl224
-rw-r--r--stardoc/proto/BUILD17
-rw-r--r--stardoc/proto/stardoc_output.proto174
-rwxr-xr-xstardoc/renderer_binary.jarbin9778587 -> 0 bytes
-rw-r--r--stardoc/stardoc.bzl307
-rwxr-xr-xstardoc/stardoc_binary.jarbin14449595 -> 13485160 bytes
-rw-r--r--stardoc/templates/html_tables/module_extension.vm56
-rw-r--r--stardoc/templates/html_tables/repository_rule.vm50
-rw-r--r--stardoc/templates/markdown_tables/aspect.vm4
-rw-r--r--stardoc/templates/markdown_tables/func.vm8
-rw-r--r--stardoc/templates/markdown_tables/header.vm2
-rw-r--r--stardoc/templates/markdown_tables/module_extension.vm34
-rw-r--r--stardoc/templates/markdown_tables/provider.vm2
-rw-r--r--stardoc/templates/markdown_tables/repository_rule.vm31
-rw-r--r--stardoc/templates/markdown_tables/rule.vm4
-rw-r--r--test/BUILD123
-rw-r--r--test/bzlmod/.bazelrc1
-rw-r--r--test/bzlmod/BUILD23
-rw-r--r--test/bzlmod/MODULE.bazel11
-rw-r--r--test/bzlmod/WORKSPACE0
-rw-r--r--test/bzlmod/WORKSPACE.bzlmod0
-rw-r--r--test/bzlmod/def.bzl31
-rw-r--r--test/bzlmod/docs.md.golden22
-rw-r--r--test/stardoc_test.bzl123
-rw-r--r--[-rwxr-xr-x]test/testdata/android_basic_test/golden.md2
-rw-r--r--test/testdata/android_basic_test/input.bzl9
-rw-r--r--[-rwxr-xr-x]test/testdata/angle_bracket_test/golden.md56
-rw-r--r--test/testdata/angle_bracket_test/input.bzl65
-rw-r--r--test/testdata/angle_bracket_test/legacy_golden.md124
-rw-r--r--[-rwxr-xr-x]test/testdata/apple_basic_test/golden.md2
-rw-r--r--[-rwxr-xr-x]test/testdata/aspect_test/golden.md18
-rw-r--r--test/testdata/aspect_test/input.bzl10
-rw-r--r--test/testdata/aspect_test/legacy_golden.md80
-rw-r--r--[-rwxr-xr-x]test/testdata/attribute_defaults_test/golden.md32
-rw-r--r--test/testdata/attribute_defaults_test/input.bzl2
-rw-r--r--test/testdata/attribute_defaults_test/legacy_golden.md74
-rw-r--r--[-rwxr-xr-x]test/testdata/attribute_types_test/golden.md10
-rw-r--r--test/testdata/attribute_types_test/input.bzl6
-rw-r--r--test/testdata/attribute_types_test/legacy_golden.md36
-rw-r--r--[-rwxr-xr-x]test/testdata/cc_api_test/golden.md2
-rw-r--r--[-rwxr-xr-x]test/testdata/config_apis_test/golden.md0
-rw-r--r--test/testdata/config_apis_test/input.bzl2
-rw-r--r--[-rwxr-xr-x]test/testdata/cpp_basic_test/golden.md2
-rw-r--r--[-rwxr-xr-x]test/testdata/filter_rules_test/golden.md28
-rw-r--r--test/testdata/filter_rules_test/input.bzl7
-rw-r--r--[-rwxr-xr-x]test/testdata/function_basic_test/golden.md30
-rw-r--r--test/testdata/function_basic_test/input.bzl21
-rw-r--r--test/testdata/function_wrap_multiple_lines_test/golden.md56
-rw-r--r--test/testdata/function_wrap_multiple_lines_test/input.bzl54
-rw-r--r--test/testdata/function_wrap_multiple_lines_test/legacy_golden.md56
-rw-r--r--test/testdata/generated_bzl_test/dep.bzl.tpl4
-rwxr-xr-xtest/testdata/generated_bzl_test/golden.md24
-rw-r--r--test/testdata/generated_bzl_test/input.bzl16
-rw-r--r--[-rwxr-xr-x]test/testdata/html_tables_template_test/golden.md2
-rw-r--r--test/testdata/html_tables_template_test/input.bzl2
-rw-r--r--[-rwxr-xr-x]test/testdata/input_template_test/golden.md2
-rw-r--r--test/testdata/input_template_test/input.bzl2
-rw-r--r--[-rwxr-xr-x]test/testdata/java_basic_test/golden.md2
-rw-r--r--test/testdata/java_basic_test/input.bzl1
-rw-r--r--test/testdata/local_repository_test/input.bzl2
-rw-r--r--[-rwxr-xr-x]test/testdata/macro_kwargs_test/golden.md4
-rw-r--r--[-rwxr-xr-x]test/testdata/misc_apis_test/golden.md10
-rw-r--r--test/testdata/misc_apis_test/legacy_golden.md76
-rw-r--r--test/testdata/module_extension_test/golden.md45
-rw-r--r--test/testdata/module_extension_test/input.bzl38
-rw-r--r--[-rwxr-xr-x]test/testdata/multi_level_namespace_test/golden.md46
-rw-r--r--test/testdata/multi_level_namespace_test_with_allowlist/golden.md (renamed from test/testdata/multi_level_namespace_test_with_whitelist/golden.md)20
-rw-r--r--test/testdata/multi_level_namespace_test_with_allowlist/input.bzl (renamed from test/testdata/multi_level_namespace_test_with_whitelist/input.bzl)4
-rw-r--r--[-rwxr-xr-x]test/testdata/multiple_files_test/golden.md0
-rw-r--r--[-rwxr-xr-x]test/testdata/multiple_rules_test/golden.md0
-rw-r--r--[-rwxr-xr-x]test/testdata/namespace_test/golden.md26
-rw-r--r--test/testdata/proto_format_test/golden.binaryproto21
-rw-r--r--test/testdata/proto_format_test/legacy_golden.binaryproto (renamed from test/testdata/proto_format_test/golden.raw)bin531 -> 527 bytes
-rw-r--r--[-rwxr-xr-x]test/testdata/provider_basic_test/golden.md9
-rw-r--r--test/testdata/provider_basic_test/input.bzl18
-rw-r--r--test/testdata/provider_basic_test/legacy_golden.md58
-rw-r--r--[-rwxr-xr-x]test/testdata/providers_for_attributes_test/golden.md12
-rw-r--r--test/testdata/pure_markdown_template_test/golden.md92
-rw-r--r--test/testdata/pure_markdown_template_test/input.bzl57
-rw-r--r--[-rwxr-xr-x]test/testdata/py_rule_test/golden.md6
-rw-r--r--[-rwxr-xr-x]test/testdata/repo_rules_test/golden.md10
-rw-r--r--test/testdata/repo_rules_test/input.bzl6
-rw-r--r--test/testdata/repo_rules_test/legacy_golden.md24
-rw-r--r--[-rwxr-xr-x]test/testdata/same_level_file_test/golden.md0
-rw-r--r--[-rwxr-xr-x]test/testdata/simple_test/golden.md2
-rw-r--r--[-rwxr-xr-x]test/testdata/struct_default_value_test/golden.md10
-rw-r--r--[-rwxr-xr-x]test/testdata/unknown_name_test/golden.md0
-rwxr-xr-xupdate-release-binary.sh9
-rwxr-xr-xupdate-stardoc-docs.sh5
-rwxr-xr-xupdate-stardoc-tests.sh69
-rw-r--r--version.bzl2
121 files changed, 5072 insertions, 654 deletions
diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml
index 8ad959e..aa36cac 100644
--- a/.bazelci/presubmit.yml
+++ b/.bazelci/presubmit.yml
@@ -1,24 +1,79 @@
---
-platforms:
- ubuntu1804:
+matrix:
+ platform:
+ - ubuntu1804
+ - ubuntu2004
+ - macos
+
+tasks:
+ build_and_test:
+ name: Build and test
+ platform: ${{ platform }}
+ build_flags:
+ - "--incompatible_disable_starlark_host_transitions"
+ build_targets:
+ - "//..."
+ test_targets:
+ - "//..."
+
+ build_and_test_windows:
+ name: Build and test - Windows
+ platform: windows
+ build_flags:
+ - "--incompatible_disable_starlark_host_transitions"
+ # Workaround for https://github.com/bazelbuild/continuous-integration/issues/1012
+ - "--noexperimental_repository_cache_hardlinks"
+ build_targets:
+ - "//..."
+ test_targets:
+ - "//..."
+
+ build_and_test_last_green:
+ name: Build and test - Bazel last green
+ platform: ${{ platform }}
+ bazel: last_green
+ build_flags:
+ - "--incompatible_disable_starlark_host_transitions"
build_targets:
- - "//..."
+ - "//..."
test_targets:
- - "//..."
- ubuntu2004:
+ - "//..."
+
+ build_and_test_last_green_windows:
+ name: Build and test - Bazel last green - Windows
+ platform: windows
+ bazel: last_green
+ build_flags:
+ - "--incompatible_disable_starlark_host_transitions"
+ # Workaround for https://github.com/bazelbuild/continuous-integration/issues/1012
+ - "--noexperimental_repository_cache_hardlinks"
build_targets:
- - "//..."
+ - "//..."
test_targets:
- - "//..."
- macos:
+ - "//..."
+
+ bzlmod:
+ name: Bzlmod example
+ platform: ${{ platform }}
+ working_directory: test/bzlmod
+ build_flags:
+ - "--incompatible_disable_starlark_host_transitions"
+ - "--enable_bzlmod"
build_targets:
- - "//..."
+ - "//..."
test_targets:
- - "//..."
- windows:
+ - "//..."
+
+ bzlmod_windows:
+ name: Bzlmod example - Windows
+ platform: windows
+ working_directory: test/bzlmod
+ build_flags:
+ - "--incompatible_disable_starlark_host_transitions"
+ - "--enable_bzlmod"
build_targets:
- - "//..."
+ - "//..."
test_targets:
- - "//..."
+ - "//..."
buildifier: latest
diff --git a/.bazelignore b/.bazelignore
new file mode 100644
index 0000000..a283e93
--- /dev/null
+++ b/.bazelignore
@@ -0,0 +1 @@
+test/bzlmod
diff --git a/.gitignore b/.gitignore
index a7f7d95..543927e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,3 +17,4 @@
/output/
/production
/.sass-cache
+/test/bzlmod/bazel-*
diff --git a/BUILD b/BUILD
index 00af466..9f3f897 100644
--- a/BUILD
+++ b/BUILD
@@ -1,9 +1,26 @@
+load("@rules_license//rules:license.bzl", "license")
+
+package(default_applicable_licenses = [":license"])
+
+license(
+ name = "license",
+ package_name = "bazelbuild/stardoc",
+ license_kinds = ["@rules_license//licenses/spdx:Apache-2.0"],
+)
+
licenses(["notice"])
-exports_files([
- "LICENSE",
- "WORKSPACE",
-])
+# Inputs for distro transformations and consistency tests.
+exports_files(
+ [
+ "LICENSE",
+ "WORKSPACE",
+ "MODULE.bazel",
+ "deps.bzl",
+ "version.bzl",
+ ],
+ visibility = ["//:__subpackages__"],
+)
filegroup(
name = "stardoc_rule_doc",
@@ -21,7 +38,14 @@ filegroup(
"CHANGELOG.md",
"CONTRIBUTORS",
"LICENSE",
+ "MODULE.bazel",
+ "maven_install.json",
+ "rules_jvm_external.patch",
+ "//src/main/java/com/google/devtools/build/skydoc/renderer:srcs",
+ "//src/main/java/com/google/devtools/build/skydoc/rendering:srcs",
+ "//src/test/java/com/google/devtools/build/skydoc/rendering:srcs",
"//stardoc:distro_srcs",
+ "//stardoc/private:distro_srcs",
"//stardoc/proto:distro_srcs",
] + glob(["*.bzl"]),
visibility = ["//:__subpackages__"],
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2118959..08d8e3d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,133 @@
+## Release 0.6.2
+
+Bugfix release: bumps `rules_jvm_external` dependency to support building with
+`--incompatible_disable_starlark_host_transitions`
+
+**Contributors**
+
+Alexandre Rostovtsev
+
+## Release 0.6.1
+
+Bugfix release: fix `rules_jvm_external` pin warnings.
+
+This release temporarily restores compatibility with Bazel 5 (manually tested).
+Note that normally we only test Stardoc with the current stable Bazel and with
+Bazel at HEAD - not with older releases. We make no promises about maintaining
+compatibility with Bazel 5.
+
+**Contributors**
+
+Alexandre Rostovtsev
+
+## Release 0.6.0
+
+**New Features**
+
+- Stardoc no longer escapes HTML tags in documentation. Feel free to
+ use HTML formatting in your docs! We now also have much-improved
+ rendering for fenced code blocks in attribute docs, and render attribute
+ default values using Markdown instead of HTML markup. (#161, #167)
+- Stardoc now dedents and trims all doc strings - not only in macros (#170).
+ This means you can have
+
+ ```bzl
+ my_rule = rule(
+ doc = """
+ This is my rule.
+
+ Here is more info about it.
+
+ ...
+ """,
+ ...
+ )
+ ```
+
+ and Stardoc will dedent and trim the doc to
+
+ ```
+ This is my rule.
+
+ Here is more info about it.
+
+ ...
+ ```
+- When using Bazel 7 or newer (or current Bazel HEAD), Stardoc will by
+ default use the native `starlark_doc_extract` rule internally (#166).
+
+ This means, in particular:
+ * correct default values for rule attributes in all cases
+ * documentation for module extensions
+ * more complete documentation for repository rules
+ * by default (this can be turned off via `render_main_repo_name = False`),
+ we will render labels in your main repo with a repo component: your
+ main module name (when using bzlmod) or WORKSPACE name (#168).
+
+ You may temporarily disable the new extractor by calling Stardoc with
+ `use_starlark_doc_extract = False`. However, after Bazel 7 is released,
+ we plan to remove this argument and always use the new extractor.
+
+**Incompatible Changes**
+
+- The Markdown renderer now uses Google EscapeVelocity instead of Apache
+ Velocity for templating. The templating engines are _almost_ compatible,
+ with the exception of escapes in string literals: if in your template you
+ had a string literal with a character escape, you would need to expand it.
+
+ For example, instead of
+
+ ```velocity
+ ${funcInfo.docString.replaceAll("\n", " ")}
+ ```
+
+ you would need
+
+ ```velocity
+ ${funcInfo.docString.replaceAll("
+ ", " ")}
+ ```
+- When using the native `starlark_doc_extract` extractor, Stardoc requires
+ two additional templates: `repository_rule_template` and
+ `module_extension_template`. If you are using custom templates, you will
+ probably want to define these, following the examples in
+ `stardoc/templates/markdown_tables`.
+- When using the native `starlark_doc_extract` extractor, Stardoc cannot
+ document generated .bzl files any more - because Bazel cannot `load()`
+ generated .bzl files.
+
+**Other Notable Changes**
+
+- The Markdown renderer's source now lives in the Stardoc repo; we build the
+ renderer from source instead of using a bundled jar. Unfortunately, if you
+ are not using bzlmod, this requires a rather complicated WORKSPACE setup;
+ see https://github.com/bazelbuild/stardoc/releases/tag/0.6.0
+
+**Contributors**
+
+Alexandre Rostovtsev, Fabian Meumertzheim
+
+## Release 0.5.6 (initially tagged as 0.5.5)
+
+Bugfix release: update `@rules_java` dependency to fix breakage with Bazel at HEAD.
+
+**Contributors**
+
+Alexandre Rostovtsev
+
+
+## Release 0.5.4
+
+**New Features**
+
+- Stardoc supports bzlmod! (#141, special thanks to Fabian Meumertzheim)
+- Stardoc output files are now exposed in stardoc() target runfiles (#139)
+
+**Contributors**
+
+Alexandre Rostovtsev, Fabian Meumertzheim, Greg Estren, Ivo List, Keith Smiley,
+lberki, Philipp Schrader
+
## Release 0.5.3
Bugfix release: fixes angle bracket escaping and a crash on labels with `@@`
diff --git a/METADATA b/METADATA
index 1b57d0d..905c64f 100644
--- a/METADATA
+++ b/METADATA
@@ -7,7 +7,7 @@ third_party {
type: GIT
value: "https://github.com/bazelbuild/stardoc"
}
- version: "0.5.3"
- last_upgrade_date { year: 2022 month: 11 day: 8 }
+ version: "0.6.2"
+ last_upgrade_date { year: 2023 month: 11 day: 8 }
license_type: NOTICE
}
diff --git a/MODULE.bazel b/MODULE.bazel
new file mode 100644
index 0000000..1363204
--- /dev/null
+++ b/MODULE.bazel
@@ -0,0 +1,33 @@
+module(
+ name = "stardoc",
+ version = "0.6.2",
+ compatibility_level = 1,
+)
+
+bazel_dep(name = "bazel_skylib", version = "1.4.2")
+bazel_dep(name = "rules_java", version = "6.3.0")
+bazel_dep(name = "rules_jvm_external", version = "5.2")
+bazel_dep(name = "rules_license", version = "0.0.7")
+bazel_dep(name = "protobuf", version = "21.7", repo_name = "com_google_protobuf")
+
+# Maven artifacts required by Stardoc; keep consistent with deps.bzl
+STARDOC_MAVEN_ARTIFACTS = [
+ "com.beust:jcommander:1.82",
+ "com.google.escapevelocity:escapevelocity:1.1",
+ "com.google.guava:guava:31.1-jre",
+ "com.google.truth:truth:1.1.3",
+ "junit:junit:4.13.2",
+]
+
+maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven")
+maven.install(
+ name = "stardoc_maven",
+ artifacts = STARDOC_MAVEN_ARTIFACTS,
+ fail_if_repin_required = True,
+ lock_file = "//:maven_install.json",
+ repositories = [
+ "https://repo1.maven.org/maven2",
+ ],
+ strict_visibility = True,
+)
+use_repo(maven, "stardoc_maven")
diff --git a/WORKSPACE b/WORKSPACE
index 048949d..5a86bf4 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -5,6 +5,22 @@ load(":setup.bzl", "stardoc_repositories")
stardoc_repositories()
+load("@rules_jvm_external//:repositories.bzl", "rules_jvm_external_deps")
+
+rules_jvm_external_deps()
+
+load("@rules_jvm_external//:setup.bzl", "rules_jvm_external_setup")
+
+rules_jvm_external_setup()
+
+load(":deps.bzl", "stardoc_external_deps")
+
+stardoc_external_deps()
+
+load("@stardoc_maven//:defs.bzl", stardoc_pinned_maven_install = "pinned_maven_install")
+
+stardoc_pinned_maven_install()
+
### INTERNAL ONLY - lines after this are not included in the release packaging.
#
# Include dependencies which are only needed for development of Stardoc here.
@@ -14,11 +30,54 @@ load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
# Needed for generating the Stardoc release binary.
git_repository(
name = "io_bazel",
- commit = "901c75e459d737220cb8e29649c1b6ba24e2221d", # Sep 27, 2022
+ commit = "1f15b87b6cf0474ade552284db70b42606f0e3ba", # 2023-08-07
remote = "https://github.com/bazelbuild/bazel.git",
- shallow_since = "1664304093 -0700",
)
+load("@rules_jvm_external//:defs.bzl", "maven_install")
+
+# Bazel's Maven dependencies - must live in @maven
+maven_install(
+ artifacts = [
+ "com.github.ben-manes.caffeine:caffeine:3.0.5",
+ "com.github.stephenc.jcip:jcip-annotations:1.0-1",
+ "com.google.auto.service:auto-service-annotations:1.0.1",
+ "com.google.auto.service:auto-service:1.0",
+ "com.google.auto.value:auto-value-annotations:1.9",
+ "com.google.auto.value:auto-value:1.8.2",
+ "com.google.auto:auto-common:1.2.1",
+ "com.google.code.findbugs:jsr305:3.0.2",
+ "com.google.code.gson:gson:2.9.0",
+ "com.google.errorprone:error_prone_annotations:2.18.0",
+ "com.google.errorprone:error_prone_type_annotations:2.18.0",
+ "com.google.flogger:flogger-system-backend:0.5.1",
+ "com.google.flogger:flogger:0.5.1",
+ "com.google.flogger:google-extensions:0.5.1",
+ "com.google.guava:failureaccess:1.0.1",
+ "com.google.guava:guava:31.1-jre",
+ "com.google.j2objc:j2objc-annotations:1.3",
+ "com.ryanharter.auto.value:auto-value-gson-extension:1.3.1",
+ "com.ryanharter.auto.value:auto-value-gson-runtime:1.3.1",
+ "com.ryanharter.auto.value:auto-value-gson-factory:1.3.1",
+ "com.squareup:javapoet:1.12.0",
+ "commons-collections:commons-collections:3.2.2",
+ "commons-lang:commons-lang:2.6",
+ "org.apache.tomcat:tomcat-annotations-api:8.0.5",
+ "org.apache.velocity:velocity:1.7",
+ "org.checkerframework:checker-qual:3.19.0",
+ ],
+ fail_if_repin_required = True,
+ maven_install_json = "//:legacy_maven_install.json",
+ repositories = [
+ "https://repo1.maven.org/maven2",
+ ],
+ strict_visibility = True,
+)
+
+load("@maven//:defs.bzl", "pinned_maven_install")
+
+pinned_maven_install()
+
# The following binds are needed for building protobuf java libraries.
bind(
name = "guava",
@@ -47,20 +106,20 @@ http_archive(
)
# Needed as a transitive dependency of @io_bazel
-git_repository(
+http_archive(
name = "rules_python",
- commit = "4b84ad270387a7c439ebdccfd530e2339601ef27",
- remote = "https://github.com/bazelbuild/rules_python.git",
- shallow_since = "1564776078 -0400",
+ sha256 = "a644da969b6824cc87f8fe7b18101a8a6c57da5db39caa6566ec6109f37d2141",
+ strip_prefix = "rules_python-0.20.0",
+ urls = ["https://github.com/bazelbuild/rules_python/releases/download/0.20.0/rules_python-0.20.0.tar.gz"],
)
# Needed for //distro:__pkg__ and as a transitive dependency of @io_bazel
http_archive(
name = "rules_pkg",
- sha256 = "8a298e832762eda1830597d64fe7db58178aa84cd5926d76d5b744d6558941c2",
+ sha256 = "eea0f59c28a9241156a47d7a8e32db9122f3d50b505fae0f33de6ce4d9b61834",
urls = [
- "https://mirror.bazel.build/github.com/bazelbuild/rules_pkg/releases/download/0.7.0/rules_pkg-0.7.0.tar.gz",
- "https://github.com/bazelbuild/rules_pkg/releases/download/0.7.0/rules_pkg-0.7.0.tar.gz",
+ "https://mirror.bazel.build/github.com/bazelbuild/rules_pkg/releases/download/0.8.0/rules_pkg-0.8.0.tar.gz",
+ "https://github.com/bazelbuild/rules_pkg/releases/download/0.8.0/rules_pkg-0.8.0.tar.gz",
],
)
@@ -71,10 +130,10 @@ rules_pkg_dependencies()
# Needed as a transitive dependency of @io_bazel
http_archive(
name = "rules_proto",
- sha256 = "9850fcf6ad40fa348e6f13b2cfef4bb4639762f804794f2bf61d988f4ba0dae9",
- strip_prefix = "rules_proto-4.0.0-3.19.2-2",
+ sha256 = "dc3fb206a2cb3441b485eb1e423165b231235a1ea9b031b4433cf7bc1fa460dd",
+ strip_prefix = "rules_proto-5.3.0-21.7",
urls = [
- "https://github.com/bazelbuild/rules_proto/archive/refs/tags/4.0.0-3.19.2-2.tar.gz",
+ "https://github.com/bazelbuild/rules_proto/archive/refs/tags/5.3.0-21.7.tar.gz",
],
)
@@ -89,3 +148,14 @@ load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_
rules_proto_dependencies()
rules_proto_toolchains()
+
+# Needed as a transitive dependency of @io_bazel
+http_archive(
+ name = "blake3",
+ build_file = "@io_bazel//third_party:blake3/blake3.BUILD",
+ sha256 = "bb529ba133c0256df49139bd403c17835edbf60d2ecd6463549c6a5fe279364d",
+ strip_prefix = "BLAKE3-1.3.3",
+ urls = [
+ "https://github.com/BLAKE3-team/BLAKE3/archive/refs/tags/1.3.3.zip",
+ ],
+)
diff --git a/deps.bzl b/deps.bzl
new file mode 100644
index 0000000..65bf7b9
--- /dev/null
+++ b/deps.bzl
@@ -0,0 +1,54 @@
+# 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.
+
+"""WORKSPACE dependency definitions for Stardoc."""
+
+load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps")
+load("@rules_jvm_external//:defs.bzl", "maven_install")
+
+# Maven artifacts required by Stardoc; keep consistent with MODULE.bazel
+STARDOC_MAVEN_ARTIFACTS = [
+ "com.beust:jcommander:1.82",
+ "com.google.escapevelocity:escapevelocity:1.1",
+ "com.google.guava:guava:31.1-jre",
+ "com.google.truth:truth:1.1.3",
+ "junit:junit:4.13.2",
+]
+
+def stardoc_external_deps():
+ """
+ Sets up Stardoc's workspace dependencies.
+
+ Requires stardoc_repositories() to be called first.
+
+ Normally should be followed up by
+
+ ```bzl
+ load("@stardoc_maven//:defs.bzl", stardoc_pinned_maven_install = "pinned_maven_install")
+
+ stardoc_pinned_maven_install()
+ ```
+ """
+ protobuf_deps()
+
+ maven_install(
+ name = "stardoc_maven",
+ artifacts = STARDOC_MAVEN_ARTIFACTS,
+ fail_if_repin_required = True,
+ maven_install_json = "@io_bazel_stardoc//:maven_install.json",
+ repositories = [
+ "https://repo1.maven.org/maven2",
+ ],
+ strict_visibility = True,
+ )
diff --git a/distro/BUILD b/distro/BUILD
index a947465..4fc0e1c 100644
--- a/distro/BUILD
+++ b/distro/BUILD
@@ -2,6 +2,7 @@ load("@io_bazel_stardoc//:version.bzl", "version")
load("@rules_pkg//:pkg.bzl", "pkg_tar")
package(
+ default_applicable_licenses = ["//:license"],
default_visibility = ["//visibility:private"],
)
@@ -14,7 +15,7 @@ genrule(
name = "distro_workspace",
srcs = ["//:WORKSPACE"],
outs = ["WORKSPACE"],
- cmd = "sed -e '/### INTERNAL ONLY/,$$d' $(location //:WORKSPACE) >$@",
+ cmd = "sed -e '/### INTERNAL ONLY/,/### END INTERNAL ONLY/d' $(location //:WORKSPACE) >$@",
)
pkg_tar(
diff --git a/docs/contributing.md b/docs/contributing.md
index b2b438d..0125737 100644
--- a/docs/contributing.md
+++ b/docs/contributing.md
@@ -11,8 +11,7 @@ submitting pull requests.
In general, we prefer contributions that fix bugs or add features (as opposed to
purely stylistic, refactoring, or "cleanup" changes). Please check with us by
opening a [GitHub Issue](https://github.com/bazelbuild/stardoc/issues) or
-emailing the [bazel-dev](https://groups.google.com/forum/#!forum/bazel-dev)
-mailing list.
+starting a [GitHub Discussion](https://github.com/bazelbuild/bazel/discussions).
## Stardoc code structure
@@ -33,8 +32,7 @@ mailing list.
plan](https://www.bazel.build/governance.html) and Stardoc's [contribution
guidelines](../CONTRIBUTING.md).
* Open an [Issue](https://github.com/bazelbuild/stardoc/issues) or discuss your
- plan or design on the [bazel-dev](https://groups.google.com/forum/#!forum/bazel-dev)
- mailing list.
+ plan or design on [Github Discussions](https://github.com/bazelbuild/bazel/discussions)
* Prepare a Git commit that implements your feature or bug fix. Don't forget to
add tests and reference the corresponding bug, if any.
* Open a [Pull Request](https://github.com/bazelbuild/stardoc/pulls) on the Stardoc
diff --git a/docs/maintainers_guide.md b/docs/maintainers_guide.md
index c4358cc..15d4337 100644
--- a/docs/maintainers_guide.md
+++ b/docs/maintainers_guide.md
@@ -1,15 +1,14 @@
# Stardoc Maintainer's Guide
-## Updating Jars
+## Updating Bundled Jar
Stardoc's source code currently lives in the Bazel source tree at
https://github.com/bazelbuild/bazel/tree/master/src/main/java/com/google/devtools/build/skydoc
-For simplicity of use and building, Stardoc bundles two pre-built jars built
-from Bazel source: `stardoc_binary.jar` (emits protobuf documentation format)
-and `renderer_binary.jar` (turns the protobuf into markdown).
+For simplicity of use and building, Stardoc bundles a pre-built jar built
+from Bazel source: `stardoc_binary.jar` (emits protobuf documentation format).
-To update the jars:
+To update the jar:
1. Update `io_bazel` repo commit in `WORKSPACE`. Update transitive deps in
`WORKSPACE` as needed.
@@ -17,7 +16,11 @@ To update the jars:
## Making a New Release
-1. Update CHANGELOG.md at the top. You may want to use the following template:
+1. Verify tests. Verify that dependencies are consistent between `setup.bzl` +
+ `WORKSPACE` and `MODULE.bazel` (but note that `MODULE.bazel` does not
+ include dependencies on `io_bazel` and its transitive deps).
+2. Update `CHANGELOG.md` at the top. You may want to use the following \
+ template:
--------------------------------------------------------------------------------
@@ -39,22 +42,26 @@ Name 1, Name 2, Name 3 (alphabetically)
--------------------------------------------------------------------------------
-2. Bump `version` in version.bzl to the new version.
-3. Ensure that the commits for steps 1 and 2 have been merged. All further
- steps must be performed on a single, known-good git commit.
-4. `bazel build //distro`
-5. Copy the `stardoc-$VERSION.tar.gz` tarball to the mirror (you'll need Bazel
+3. Bump `version` in `version.bzl` *and* `MODULE.bazel` to the new version.
+4. Ensure that the commits for steps 1-3 have been merged. All further steps
+ must be performed on a single, known-good git commit.
+5. `bazel build //distro`
+6. Copy the `stardoc-$VERSION.tar.gz` tarball to the mirror (you'll need Bazel
developer gcloud credentials; assuming you are a Bazel developer, you can
obtain them via `gcloud init`):
-```
-gsutil cp bazel-bin/distro/stardoc-$VERSION.tar.gz gs://bazel-mirror/github.com/bazelbuild/stardoc/releases/download/$VERSION/stardoc-$VERSION.tar.gz
-gsutil setmeta -h "Cache-Control: public, max-age=31536000" "gs://bazel-mirror/github.com/bazelbuild/stardoc/releases/download/$VERSION/stardoc-$VERSION.tar.gz"
-```
+ ```bash
+ gsutil cp bazel-bin/distro/stardoc-$VERSION.tar.gz gs://bazel-mirror/github.com/bazelbuild/stardoc/releases/download/$VERSION/stardoc-$VERSION.tar.gz
+ gsutil setmeta -h "Cache-Control: public, max-age=31536000" "gs://bazel-mirror/github.com/bazelbuild/stardoc/releases/download/$VERSION/stardoc-$VERSION.tar.gz"
+ ```
+
+7. Obtain checksum for release notes:
+
+ ```bash
+ sha256sum bazel-bin/distro/stardoc-$VERSION.tar.gz
+ ```
-6. Run `sha256sum bazel-bin/distro/stardoc-$VERSION.tar.gz`; you'll need the
- checksum for the release notes.
-7. Draft a new release with a new tag named $VERSION in github. Attach
+8. Draft a new release with a new tag named $VERSION in github. Attach
`stardoc-$VERSION.tar.gz` to the release. For the release notes, use the
CHANGELOG.md entry plus the following template:
@@ -64,7 +71,7 @@ gsutil setmeta -h "Cache-Control: public, max-age=31536000" "gs://bazel-mirror/g
To use Stardoc, add the following to your `WORKSPACE` file:
-```
+```starlark
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
@@ -79,10 +86,28 @@ http_archive(
load("@io_bazel_stardoc//:setup.bzl", "stardoc_repositories")
stardoc_repositories()
+
+load("@rules_jvm_external//:repositories.bzl", "rules_jvm_external_deps")
+
+rules_jvm_external_deps()
+
+load("@rules_jvm_external//:setup.bzl", "rules_jvm_external_setup")
+
+rules_jvm_external_setup()
+
+load("@io_bazel_stardoc//:deps.bzl", "stardoc_external_deps")
+
+stardoc_external_deps()
+
+load("@stardoc_maven//:defs.bzl", stardoc_pinned_maven_install = "pinned_maven_install")
+
+stardoc_pinned_maven_install()
```
-The load statement and function call after the `io_bazel_stardoc` repository
-definition ensure that this repository's dependencies are loaded.
+The sequence of function calls and load statements after the `io_bazel_stardoc`
+repository definition ensures that this repository's dependencies are loaded
+(each function call defines additional repositories for Stardoc's dependencies,
+which are then used by subsequent load statements).
**Using the rules**
@@ -90,3 +115,40 @@ See [the source](https://github.com/bazelbuild/stardoc/tree/$VERSION).
--------------------------------------------------------------------------------
+9. Obtain [Subresource Integrity](https://w3c.github.io/webappsec-subresource-integrity/#integrity-metadata-description)
+ format checksum for bzlmod:
+
+```bash
+echo -n sha256-; cat bazel-bin/distro/stardoc-$VERSION.tar.gz | openssl dgst -sha256 -binary | base64
+```
+
+10. Create a PR at [Bazel Central Registry](https://github.com/bazelbuild/bazel-central-registry)
+ to update the registry's versions of bazel_skylib and
+ bazel_skylib_gazelle_plugin.
+
+ Use https://github.com/bazelbuild/bazel-central-registry/pull/677 as the
+ model; you will need to update `modules/stardoc/metadata.json` to list the
+ new version in `versions`, and create new $VERSION subdirectories for the
+ updated module, using the latest existing version subdirectories as the
+ guide. Use Subresource Integrity checksums obtained above in the new
+ `source.json` file.
+
+ Ensure that the `MODULE.bazel` file you add in the new $VERSION
+ subdirectory exactly matches the `MODULE.bazel` file packaged in the
+ stardoc-$VERSION.tar.gz tarball - or buildkite checks will fail.
+
+11. Once the Bazel Central Registry PR is merged, insert in the release
+ description after the `WORKSPACE` setup section:
+
+--------------------------------------------------------------------------------
+
+**MODULE.bazel setup**
+
+```starlark
+bazel_dep(name = "stardoc", version = "$VERSION")
+```
+
+For compatibility with `WORKSPACE` setup, add `repo_name = "io_bazel_stardoc"`
+to the `bazel_dep` call.
+
+-------------------------------------------------------------------------------- \ No newline at end of file
diff --git a/docs/stardoc_rule.md b/docs/stardoc_rule.md
index 532855a..18bb219 100644
--- a/docs/stardoc_rule.md
+++ b/docs/stardoc_rule.md
@@ -7,34 +7,37 @@ Starlark rule for stardoc: a documentation generator tool written in Java.
## stardoc
<pre>
-stardoc(<a href="#stardoc-name">name</a>, <a href="#stardoc-aspect_template">aspect_template</a>, <a href="#stardoc-deps">deps</a>, <a href="#stardoc-format">format</a>, <a href="#stardoc-func_template">func_template</a>, <a href="#stardoc-header_template">header_template</a>, <a href="#stardoc-input">input</a>, <a href="#stardoc-out">out</a>,
- <a href="#stardoc-provider_template">provider_template</a>, <a href="#stardoc-renderer">renderer</a>, <a href="#stardoc-rule_template">rule_template</a>, <a href="#stardoc-semantic_flags">semantic_flags</a>, <a href="#stardoc-stardoc">stardoc</a>, <a href="#stardoc-symbol_names">symbol_names</a>)
+stardoc(<a href="#stardoc-name">name</a>, <a href="#stardoc-input">input</a>, <a href="#stardoc-out">out</a>, <a href="#stardoc-deps">deps</a>, <a href="#stardoc-format">format</a>, <a href="#stardoc-symbol_names">symbol_names</a>, <a href="#stardoc-semantic_flags">semantic_flags</a>, <a href="#stardoc-stardoc">stardoc</a>, <a href="#stardoc-renderer">renderer</a>,
+ <a href="#stardoc-aspect_template">aspect_template</a>, <a href="#stardoc-func_template">func_template</a>, <a href="#stardoc-header_template">header_template</a>, <a href="#stardoc-provider_template">provider_template</a>, <a href="#stardoc-rule_template">rule_template</a>,
+ <a href="#stardoc-repository_rule_template">repository_rule_template</a>, <a href="#stardoc-module_extension_template">module_extension_template</a>, <a href="#stardoc-use_starlark_doc_extract">use_starlark_doc_extract</a>,
+ <a href="#stardoc-render_main_repo_name">render_main_repo_name</a>, <a href="#stardoc-kwargs">kwargs</a>)
</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**
-
-
-| Name | Description | Type | Mandatory | Default |
-| :------------- | :------------- | :------------- | :------------- | :------------- |
-| <a id="stardoc-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
-| <a id="stardoc-aspect_template"></a>aspect_template | The input file template for generating documentation of aspects. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>//stardoc:templates/markdown_tables/aspect.vm</code> |
-| <a id="stardoc-deps"></a>deps | A list of bzl_library dependencies which the input depends on. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | <code>[]</code> |
-| <a id="stardoc-format"></a>format | The format of the output file. Valid values: 'markdown' or 'proto'. | String | optional | <code>"markdown"</code> |
-| <a id="stardoc-func_template"></a>func_template | The input file template for generating documentation of functions. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>//stardoc:templates/markdown_tables/func.vm</code> |
-| <a id="stardoc-header_template"></a>header_template | The input file template for the header of the output documentation. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>//stardoc:templates/markdown_tables/header.vm</code> |
-| <a id="stardoc-input"></a>input | The starlark file to generate documentation for. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>None</code> |
-| <a id="stardoc-out"></a>out | The (markdown) file to which documentation will be output. | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
-| <a id="stardoc-provider_template"></a>provider_template | The input file template for generating documentation of providers. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>//stardoc:templates/markdown_tables/provider.vm</code> |
-| <a id="stardoc-renderer"></a>renderer | The location of the renderer tool. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>//stardoc:renderer</code> |
-| <a id="stardoc-rule_template"></a>rule_template | The input file template for generating documentation of rules. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>//stardoc:templates/markdown_tables/rule.vm</code> |
-| <a id="stardoc-semantic_flags"></a>semantic_flags | A list of canonical flags to affect Starlark semantics for the Starlark interpretter during documentation generation. This should only be used to maintain compatibility with non-default semantic flags required to use the given Starlark symbols.<br><br>For example, if <code>//foo:bar.bzl</code> does not build except when a user would specify <code>--incompatible_foo_semantic=false</code>, then this attribute should contain "--incompatible_foo_semantic=false". | List of strings | optional | <code>[]</code> |
-| <a id="stardoc-stardoc"></a>stardoc | The location of the stardoc tool. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>//stardoc:stardoc</code> |
-| <a id="stardoc-symbol_names"></a>symbol_names | 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. | List of strings | optional | <code>[]</code> |
+Generates documentation for exported starlark rule definitions in a target starlark file.
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="stardoc-name"></a>name | The name of the stardoc target. | none |
+| <a id="stardoc-input"></a>input | The starlark file to generate documentation for (mandatory). | none |
+| <a id="stardoc-out"></a>out | The file to which documentation will be output (mandatory). | none |
+| <a id="stardoc-deps"></a>deps | A list of bzl_library dependencies which the input depends on. | `[]` |
+| <a id="stardoc-format"></a>format | The format of the output file. Valid values: 'markdown' or 'proto'. | `"markdown"` |
+| <a id="stardoc-symbol_names"></a>symbol_names | 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. | `[]` |
+| <a id="stardoc-semantic_flags"></a>semantic_flags | A list of canonical flags to affect Starlark semantics for the Starlark interpreter during documentation generation. This should only be used to maintain compatibility with non-default semantic flags required to use the given Starlark symbols.<br><br>For example, if `//foo:bar.bzl` does not build except when a user would specify `--incompatible_foo_semantic=false`, then this attribute should contain "--incompatible_foo_semantic=false". | `[]` |
+| <a id="stardoc-stardoc"></a>stardoc | The location of the legacy Stardoc extractor. Ignored when using the native `starlark_doc_extract` rule. | `Label("@io_bazel_stardoc//stardoc:prebuilt_stardoc_binary")` |
+| <a id="stardoc-renderer"></a>renderer | The location of the renderer tool. | `Label("@io_bazel_stardoc//stardoc:renderer")` |
+| <a id="stardoc-aspect_template"></a>aspect_template | The input file template for generating documentation of aspects | `Label("@io_bazel_stardoc//stardoc:templates/markdown_tables/aspect.vm")` |
+| <a id="stardoc-func_template"></a>func_template | The input file template for generating documentation of functions. | `Label("@io_bazel_stardoc//stardoc:templates/markdown_tables/func.vm")` |
+| <a id="stardoc-header_template"></a>header_template | The input file template for the header of the output documentation. | `Label("@io_bazel_stardoc//stardoc:templates/markdown_tables/header.vm")` |
+| <a id="stardoc-provider_template"></a>provider_template | The input file template for generating documentation of providers. | `Label("@io_bazel_stardoc//stardoc:templates/markdown_tables/provider.vm")` |
+| <a id="stardoc-rule_template"></a>rule_template | The input file template for generating documentation of rules. | `Label("@io_bazel_stardoc//stardoc:templates/markdown_tables/rule.vm")` |
+| <a id="stardoc-repository_rule_template"></a>repository_rule_template | The input file template for generating documentation of repository rules. This template is used only when using the native `starlark_doc_extract` rule. | `Label("@io_bazel_stardoc//stardoc:templates/markdown_tables/repository_rule.vm")` |
+| <a id="stardoc-module_extension_template"></a>module_extension_template | The input file template for generating documentation of module extensions. This template is used only when using the native `starlark_doc_extract` rule. | `Label("@io_bazel_stardoc//stardoc:templates/markdown_tables/module_extension.vm")` |
+| <a id="stardoc-use_starlark_doc_extract"></a>use_starlark_doc_extract | Use the native `starlark_doc_extract` rule if available. | `True` |
+| <a id="stardoc-render_main_repo_name"></a>render_main_repo_name | Render labels in the main repository with a repo component (either the module name or workspace name). This parameter is used only when using the native `starlark_doc_extract` rule. | `True` |
+| <a id="stardoc-kwargs"></a>kwargs | Further arguments to pass to stardoc. | none |
diff --git a/legacy_maven_install.json b/legacy_maven_install.json
new file mode 100644
index 0000000..c3f8dab
--- /dev/null
+++ b/legacy_maven_install.json
@@ -0,0 +1,529 @@
+{
+ "__AUTOGENERATED_FILE_DO_NOT_MODIFY_THIS_FILE_MANUALLY": "THERE_IS_NO_DATA_ONLY_ZUUL",
+ "__INPUT_ARTIFACTS_HASH": 1429940565,
+ "__RESOLVED_ARTIFACTS_HASH": -1447515200,
+ "artifacts": {
+ "com.github.ben-manes.caffeine:caffeine": {
+ "shasums": {
+ "jar": "8a9b54d3506a3b92ee46b217bcee79196b21ca6d52dc2967c686a205fb2f9c15"
+ },
+ "version": "3.0.5"
+ },
+ "com.github.stephenc.jcip:jcip-annotations": {
+ "shasums": {
+ "jar": "4fccff8382aafc589962c4edb262f6aa595e34f1e11e61057d1c6a96e8fc7323"
+ },
+ "version": "1.0-1"
+ },
+ "com.google.auto.service:auto-service": {
+ "shasums": {
+ "jar": "4ae44dd05b49a1109a463c0d2aaf920c24f76d1e996bb89f29481c4ff75ec526"
+ },
+ "version": "1.0"
+ },
+ "com.google.auto.service:auto-service-annotations": {
+ "shasums": {
+ "jar": "c7bec54b7b5588b5967e870341091c5691181d954cf2039f1bf0a6eeb837473b"
+ },
+ "version": "1.0.1"
+ },
+ "com.google.auto.value:auto-value": {
+ "shasums": {
+ "jar": "2067b788d4c1c96fd621ad861053a5c4d8a801cfafc77fec20d49a6e9340a745"
+ },
+ "version": "1.8.2"
+ },
+ "com.google.auto.value:auto-value-annotations": {
+ "shasums": {
+ "jar": "fa5469f4c44ee598a2d8f033ab0a9dcbc6498a0c5e0c998dfa0c2adf51358044"
+ },
+ "version": "1.9"
+ },
+ "com.google.auto:auto-common": {
+ "shasums": {
+ "jar": "f43f29fe2a6ebaf04b2598cdeec32a4e346d49a9404e990f5fc19c19f3a28d0e"
+ },
+ "version": "1.2.1"
+ },
+ "com.google.code.findbugs:jsr305": {
+ "shasums": {
+ "jar": "766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7"
+ },
+ "version": "3.0.2"
+ },
+ "com.google.code.gson:gson": {
+ "shasums": {
+ "jar": "c96d60551331a196dac54b745aa642cd078ef89b6f267146b705f2c2cbef052d"
+ },
+ "version": "2.9.0"
+ },
+ "com.google.errorprone:error_prone_annotations": {
+ "shasums": {
+ "jar": "9e6814cb71816988a4fd1b07a993a8f21bb7058d522c162b1de849e19bea54ae"
+ },
+ "version": "2.18.0"
+ },
+ "com.google.errorprone:error_prone_type_annotations": {
+ "shasums": {
+ "jar": "d2ab73bc6807277f7463391504313e47bc3465ab1916339c8e82be633a9ab375"
+ },
+ "version": "2.18.0"
+ },
+ "com.google.flogger:flogger": {
+ "shasums": {
+ "jar": "b5ecd1483e041197012786f749968a62063c1964d3ecfbf96ba92a95797bb8f5"
+ },
+ "version": "0.5.1"
+ },
+ "com.google.flogger:flogger-system-backend": {
+ "shasums": {
+ "jar": "685de33b53eb313049bbeee7f4b7a80dd09e8e754e96b048a3edab2cebb36442"
+ },
+ "version": "0.5.1"
+ },
+ "com.google.flogger:google-extensions": {
+ "shasums": {
+ "jar": "8b0862cad85b9549f355fe383c6c63816d2f19529634e033ae06d0107ab110b9"
+ },
+ "version": "0.5.1"
+ },
+ "com.google.guava:failureaccess": {
+ "shasums": {
+ "jar": "a171ee4c734dd2da837e4b16be9df4661afab72a41adaf31eb84dfdaf936ca26"
+ },
+ "version": "1.0.1"
+ },
+ "com.google.guava:guava": {
+ "shasums": {
+ "jar": "a42edc9cab792e39fe39bb94f3fca655ed157ff87a8af78e1d6ba5b07c4a00ab"
+ },
+ "version": "31.1-jre"
+ },
+ "com.google.guava:listenablefuture": {
+ "shasums": {
+ "jar": "b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99"
+ },
+ "version": "9999.0-empty-to-avoid-conflict-with-guava"
+ },
+ "com.google.j2objc:j2objc-annotations": {
+ "shasums": {
+ "jar": "21af30c92267bd6122c0e0b4d20cccb6641a37eaf956c6540ec471d584e64a7b"
+ },
+ "version": "1.3"
+ },
+ "com.ryanharter.auto.value:auto-value-gson-extension": {
+ "shasums": {
+ "jar": "261be84be30a56994e132d718a85efcd579197a2edb9426b84c5722c56955eca"
+ },
+ "version": "1.3.1"
+ },
+ "com.ryanharter.auto.value:auto-value-gson-factory": {
+ "shasums": {
+ "jar": "5a76c3d401c984999d59868f08df05a15613d1428f7764fed80b722e2a277f6c"
+ },
+ "version": "1.3.1"
+ },
+ "com.ryanharter.auto.value:auto-value-gson-runtime": {
+ "shasums": {
+ "jar": "84ee23b7989d4bf19930b5bd3d03c0f2efb9e73bcee3a0208a9d1b2e1979c049"
+ },
+ "version": "1.3.1"
+ },
+ "com.squareup:javapoet": {
+ "shasums": {
+ "jar": "2b70cdfa8c9e997b4007035a266c273c0df341f9c57c9d0b45a680ae3fd882db"
+ },
+ "version": "1.12.0"
+ },
+ "commons-collections:commons-collections": {
+ "shasums": {
+ "jar": "eeeae917917144a68a741d4c0dff66aa5c5c5fd85593ff217bced3fc8ca783b8"
+ },
+ "version": "3.2.2"
+ },
+ "commons-lang:commons-lang": {
+ "shasums": {
+ "jar": "50f11b09f877c294d56f24463f47d28f929cf5044f648661c0f0cfbae9a2f49c"
+ },
+ "version": "2.6"
+ },
+ "io.sweers.autotransient:autotransient": {
+ "shasums": {
+ "jar": "914ce84508410ee1419514925f93b1855a9f7a7b5b5d02fc07f411d2a45f1bba"
+ },
+ "version": "1.0.0"
+ },
+ "org.apache.tomcat:tomcat-annotations-api": {
+ "shasums": {
+ "jar": "748677bebb1651a313317dfd93e984ed8f8c9e345538fa8b0ab0cbb804631953"
+ },
+ "version": "8.0.5"
+ },
+ "org.apache.velocity:velocity": {
+ "shasums": {
+ "jar": "ec92dae810034f4b46dbb16ef4364a4013b0efb24a8c5dd67435cae46a290d8e"
+ },
+ "version": "1.7"
+ },
+ "org.checkerframework:checker-compat-qual": {
+ "shasums": {
+ "jar": "d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d"
+ },
+ "version": "2.5.3"
+ },
+ "org.checkerframework:checker-qual": {
+ "shasums": {
+ "jar": "a827c49183f3a632277d27a0a4673686cb341507447b9d570261094bd748aa68"
+ },
+ "version": "3.19.0"
+ }
+ },
+ "dependencies": {
+ "com.github.ben-manes.caffeine:caffeine": [
+ "com.google.errorprone:error_prone_annotations",
+ "org.checkerframework:checker-qual"
+ ],
+ "com.google.auto.service:auto-service": [
+ "com.google.auto.service:auto-service-annotations",
+ "com.google.auto:auto-common",
+ "com.google.guava:guava"
+ ],
+ "com.google.auto:auto-common": [
+ "com.google.guava:guava"
+ ],
+ "com.google.flogger:flogger": [
+ "org.checkerframework:checker-compat-qual"
+ ],
+ "com.google.flogger:flogger-system-backend": [
+ "com.google.flogger:flogger",
+ "org.checkerframework:checker-compat-qual"
+ ],
+ "com.google.flogger:google-extensions": [
+ "com.google.flogger:flogger"
+ ],
+ "com.google.guava:guava": [
+ "com.google.code.findbugs:jsr305",
+ "com.google.errorprone:error_prone_annotations",
+ "com.google.guava:failureaccess",
+ "com.google.guava:listenablefuture",
+ "com.google.j2objc:j2objc-annotations",
+ "org.checkerframework:checker-qual"
+ ],
+ "com.ryanharter.auto.value:auto-value-gson-extension": [
+ "com.google.auto.value:auto-value",
+ "com.google.auto.value:auto-value-annotations",
+ "com.google.code.gson:gson",
+ "com.ryanharter.auto.value:auto-value-gson-runtime",
+ "com.squareup:javapoet"
+ ],
+ "com.ryanharter.auto.value:auto-value-gson-factory": [
+ "com.google.auto.value:auto-value-annotations",
+ "com.google.code.gson:gson",
+ "com.ryanharter.auto.value:auto-value-gson-extension",
+ "com.squareup:javapoet"
+ ],
+ "com.ryanharter.auto.value:auto-value-gson-runtime": [
+ "com.google.code.gson:gson",
+ "io.sweers.autotransient:autotransient"
+ ],
+ "org.apache.velocity:velocity": [
+ "commons-collections:commons-collections",
+ "commons-lang:commons-lang"
+ ]
+ },
+ "packages": {
+ "com.github.ben-manes.caffeine:caffeine": [
+ "com.github.benmanes.caffeine.cache",
+ "com.github.benmanes.caffeine.cache.stats"
+ ],
+ "com.github.stephenc.jcip:jcip-annotations": [
+ "net.jcip.annotations"
+ ],
+ "com.google.auto.service:auto-service": [
+ "com.google.auto.service.processor"
+ ],
+ "com.google.auto.service:auto-service-annotations": [
+ "com.google.auto.service"
+ ],
+ "com.google.auto.value:auto-value": [
+ "autovalue.shaded.com.google$.auto.common",
+ "autovalue.shaded.com.google$.auto.service",
+ "autovalue.shaded.com.google$.common.annotations",
+ "autovalue.shaded.com.google$.common.base",
+ "autovalue.shaded.com.google$.common.collect",
+ "autovalue.shaded.com.google$.common.hash",
+ "autovalue.shaded.com.google$.common.math",
+ "autovalue.shaded.com.google$.common.primitives",
+ "autovalue.shaded.com.google$.common.reflect",
+ "autovalue.shaded.com.google$.errorprone.annotations",
+ "autovalue.shaded.com.google$.errorprone.annotations.concurrent",
+ "autovalue.shaded.com.google$.escapevelocity",
+ "autovalue.shaded.com.google$.j2objc.annotations",
+ "autovalue.shaded.com.squareup.javapoet$",
+ "autovalue.shaded.net.ltgt.gradle.incap$",
+ "autovalue.shaded.org.checkerframework$.checker.nullness.qual",
+ "autovalue.shaded.org.checkerframework$.framework.qual",
+ "com.google.auto.value.extension",
+ "com.google.auto.value.extension.memoized.processor",
+ "com.google.auto.value.extension.serializable.processor",
+ "com.google.auto.value.extension.serializable.serializer",
+ "com.google.auto.value.extension.serializable.serializer.impl",
+ "com.google.auto.value.extension.serializable.serializer.interfaces",
+ "com.google.auto.value.extension.serializable.serializer.runtime",
+ "com.google.auto.value.extension.toprettystring.processor",
+ "com.google.auto.value.processor"
+ ],
+ "com.google.auto.value:auto-value-annotations": [
+ "com.google.auto.value",
+ "com.google.auto.value.extension.memoized",
+ "com.google.auto.value.extension.serializable",
+ "com.google.auto.value.extension.toprettystring"
+ ],
+ "com.google.auto:auto-common": [
+ "com.google.auto.common"
+ ],
+ "com.google.code.findbugs:jsr305": [
+ "javax.annotation",
+ "javax.annotation.concurrent",
+ "javax.annotation.meta"
+ ],
+ "com.google.code.gson:gson": [
+ "com.google.gson",
+ "com.google.gson.annotations",
+ "com.google.gson.internal",
+ "com.google.gson.internal.bind",
+ "com.google.gson.internal.bind.util",
+ "com.google.gson.internal.reflect",
+ "com.google.gson.internal.sql",
+ "com.google.gson.reflect",
+ "com.google.gson.stream"
+ ],
+ "com.google.errorprone:error_prone_annotations": [
+ "com.google.errorprone.annotations",
+ "com.google.errorprone.annotations.concurrent"
+ ],
+ "com.google.errorprone:error_prone_type_annotations": [
+ "com.google.errorprone.annotations"
+ ],
+ "com.google.flogger:flogger": [
+ "com.google.common.flogger",
+ "com.google.common.flogger.backend",
+ "com.google.common.flogger.context",
+ "com.google.common.flogger.parameter",
+ "com.google.common.flogger.parser",
+ "com.google.common.flogger.util"
+ ],
+ "com.google.flogger:flogger-system-backend": [
+ "com.google.common.flogger.backend.system"
+ ],
+ "com.google.flogger:google-extensions": [
+ "com.google.common.flogger"
+ ],
+ "com.google.guava:failureaccess": [
+ "com.google.common.util.concurrent.internal"
+ ],
+ "com.google.guava:guava": [
+ "com.google.common.annotations",
+ "com.google.common.base",
+ "com.google.common.base.internal",
+ "com.google.common.cache",
+ "com.google.common.collect",
+ "com.google.common.escape",
+ "com.google.common.eventbus",
+ "com.google.common.graph",
+ "com.google.common.hash",
+ "com.google.common.html",
+ "com.google.common.io",
+ "com.google.common.math",
+ "com.google.common.net",
+ "com.google.common.primitives",
+ "com.google.common.reflect",
+ "com.google.common.util.concurrent",
+ "com.google.common.xml",
+ "com.google.thirdparty.publicsuffix"
+ ],
+ "com.google.j2objc:j2objc-annotations": [
+ "com.google.j2objc.annotations"
+ ],
+ "com.ryanharter.auto.value:auto-value-gson-extension": [
+ "autovaluegson.shaded.com.google.auto.common",
+ "autovaluegson.shaded.com.google.common.annotations",
+ "autovaluegson.shaded.com.google.common.base",
+ "autovaluegson.shaded.com.google.common.cache",
+ "autovaluegson.shaded.com.google.common.collect",
+ "autovaluegson.shaded.com.google.common.escape",
+ "autovaluegson.shaded.com.google.common.eventbus",
+ "autovaluegson.shaded.com.google.common.graph",
+ "autovaluegson.shaded.com.google.common.hash",
+ "autovaluegson.shaded.com.google.common.html",
+ "autovaluegson.shaded.com.google.common.io",
+ "autovaluegson.shaded.com.google.common.math",
+ "autovaluegson.shaded.com.google.common.net",
+ "autovaluegson.shaded.com.google.common.primitives",
+ "autovaluegson.shaded.com.google.common.reflect",
+ "autovaluegson.shaded.com.google.common.util.concurrent",
+ "autovaluegson.shaded.com.google.common.xml",
+ "com.ryanharter.auto.value.gson"
+ ],
+ "com.ryanharter.auto.value:auto-value-gson-factory": [
+ "autovaluegson.factory.shaded.com.google.auto.common",
+ "autovaluegson.factory.shaded.com.google.common.annotations",
+ "autovaluegson.factory.shaded.com.google.common.base",
+ "autovaluegson.factory.shaded.com.google.common.cache",
+ "autovaluegson.factory.shaded.com.google.common.collect",
+ "autovaluegson.factory.shaded.com.google.common.escape",
+ "autovaluegson.factory.shaded.com.google.common.eventbus",
+ "autovaluegson.factory.shaded.com.google.common.graph",
+ "autovaluegson.factory.shaded.com.google.common.hash",
+ "autovaluegson.factory.shaded.com.google.common.html",
+ "autovaluegson.factory.shaded.com.google.common.io",
+ "autovaluegson.factory.shaded.com.google.common.math",
+ "autovaluegson.factory.shaded.com.google.common.net",
+ "autovaluegson.factory.shaded.com.google.common.primitives",
+ "autovaluegson.factory.shaded.com.google.common.reflect",
+ "autovaluegson.factory.shaded.com.google.common.util.concurrent",
+ "autovaluegson.factory.shaded.com.google.common.xml",
+ "com.ryanharter.auto.value.gson.factory"
+ ],
+ "com.ryanharter.auto.value:auto-value-gson-runtime": [
+ "com.ryanharter.auto.value.gson",
+ "com.ryanharter.auto.value.gson.internal"
+ ],
+ "com.squareup:javapoet": [
+ "com.squareup.javapoet"
+ ],
+ "commons-collections:commons-collections": [
+ "org.apache.commons.collections",
+ "org.apache.commons.collections.bag",
+ "org.apache.commons.collections.bidimap",
+ "org.apache.commons.collections.buffer",
+ "org.apache.commons.collections.collection",
+ "org.apache.commons.collections.comparators",
+ "org.apache.commons.collections.functors",
+ "org.apache.commons.collections.iterators",
+ "org.apache.commons.collections.keyvalue",
+ "org.apache.commons.collections.list",
+ "org.apache.commons.collections.map",
+ "org.apache.commons.collections.set"
+ ],
+ "commons-lang:commons-lang": [
+ "org.apache.commons.lang",
+ "org.apache.commons.lang.builder",
+ "org.apache.commons.lang.enum",
+ "org.apache.commons.lang.enums",
+ "org.apache.commons.lang.exception",
+ "org.apache.commons.lang.math",
+ "org.apache.commons.lang.mutable",
+ "org.apache.commons.lang.reflect",
+ "org.apache.commons.lang.text",
+ "org.apache.commons.lang.time"
+ ],
+ "io.sweers.autotransient:autotransient": [
+ "io.sweers.autotransient"
+ ],
+ "org.apache.tomcat:tomcat-annotations-api": [
+ "javax.annotation",
+ "javax.annotation.security",
+ "javax.annotation.sql",
+ "javax.ejb",
+ "javax.persistence",
+ "javax.xml.ws"
+ ],
+ "org.apache.velocity:velocity": [
+ "org.apache.velocity",
+ "org.apache.velocity.anakia",
+ "org.apache.velocity.app",
+ "org.apache.velocity.app.event",
+ "org.apache.velocity.app.event.implement",
+ "org.apache.velocity.app.tools",
+ "org.apache.velocity.context",
+ "org.apache.velocity.convert",
+ "org.apache.velocity.exception",
+ "org.apache.velocity.io",
+ "org.apache.velocity.runtime",
+ "org.apache.velocity.runtime.directive",
+ "org.apache.velocity.runtime.log",
+ "org.apache.velocity.runtime.parser",
+ "org.apache.velocity.runtime.parser.node",
+ "org.apache.velocity.runtime.resource",
+ "org.apache.velocity.runtime.resource.loader",
+ "org.apache.velocity.runtime.resource.util",
+ "org.apache.velocity.runtime.visitor",
+ "org.apache.velocity.servlet",
+ "org.apache.velocity.texen",
+ "org.apache.velocity.texen.ant",
+ "org.apache.velocity.texen.util",
+ "org.apache.velocity.util",
+ "org.apache.velocity.util.introspection"
+ ],
+ "org.checkerframework:checker-compat-qual": [
+ "org.checkerframework.checker.nullness.compatqual"
+ ],
+ "org.checkerframework:checker-qual": [
+ "org.checkerframework.checker.builder.qual",
+ "org.checkerframework.checker.calledmethods.qual",
+ "org.checkerframework.checker.compilermsgs.qual",
+ "org.checkerframework.checker.fenum.qual",
+ "org.checkerframework.checker.formatter.qual",
+ "org.checkerframework.checker.guieffect.qual",
+ "org.checkerframework.checker.i18n.qual",
+ "org.checkerframework.checker.i18nformatter.qual",
+ "org.checkerframework.checker.index.qual",
+ "org.checkerframework.checker.initialization.qual",
+ "org.checkerframework.checker.interning.qual",
+ "org.checkerframework.checker.lock.qual",
+ "org.checkerframework.checker.mustcall.qual",
+ "org.checkerframework.checker.nullness.qual",
+ "org.checkerframework.checker.optional.qual",
+ "org.checkerframework.checker.propkey.qual",
+ "org.checkerframework.checker.regex.qual",
+ "org.checkerframework.checker.signature.qual",
+ "org.checkerframework.checker.signedness.qual",
+ "org.checkerframework.checker.tainting.qual",
+ "org.checkerframework.checker.units.qual",
+ "org.checkerframework.common.aliasing.qual",
+ "org.checkerframework.common.initializedfields.qual",
+ "org.checkerframework.common.reflection.qual",
+ "org.checkerframework.common.returnsreceiver.qual",
+ "org.checkerframework.common.subtyping.qual",
+ "org.checkerframework.common.util.report.qual",
+ "org.checkerframework.common.value.qual",
+ "org.checkerframework.dataflow.qual",
+ "org.checkerframework.framework.qual"
+ ]
+ },
+ "repositories": {
+ "https://repo1.maven.org/maven2/": [
+ "com.github.ben-manes.caffeine:caffeine",
+ "com.github.stephenc.jcip:jcip-annotations",
+ "com.google.auto.service:auto-service",
+ "com.google.auto.service:auto-service-annotations",
+ "com.google.auto.value:auto-value",
+ "com.google.auto.value:auto-value-annotations",
+ "com.google.auto:auto-common",
+ "com.google.code.findbugs:jsr305",
+ "com.google.code.gson:gson",
+ "com.google.errorprone:error_prone_annotations",
+ "com.google.errorprone:error_prone_type_annotations",
+ "com.google.flogger:flogger",
+ "com.google.flogger:flogger-system-backend",
+ "com.google.flogger:google-extensions",
+ "com.google.guava:failureaccess",
+ "com.google.guava:guava",
+ "com.google.guava:listenablefuture",
+ "com.google.j2objc:j2objc-annotations",
+ "com.ryanharter.auto.value:auto-value-gson-extension",
+ "com.ryanharter.auto.value:auto-value-gson-factory",
+ "com.ryanharter.auto.value:auto-value-gson-runtime",
+ "com.squareup:javapoet",
+ "commons-collections:commons-collections",
+ "commons-lang:commons-lang",
+ "io.sweers.autotransient:autotransient",
+ "org.apache.tomcat:tomcat-annotations-api",
+ "org.apache.velocity:velocity",
+ "org.checkerframework:checker-compat-qual",
+ "org.checkerframework:checker-qual"
+ ]
+ },
+ "version": "2"
+}
diff --git a/maven_install.json b/maven_install.json
new file mode 100644
index 0000000..d5755ea
--- /dev/null
+++ b/maven_install.json
@@ -0,0 +1,266 @@
+{
+ "__AUTOGENERATED_FILE_DO_NOT_MODIFY_THIS_FILE_MANUALLY": "THERE_IS_NO_DATA_ONLY_ZUUL",
+ "__INPUT_ARTIFACTS_HASH": -1307148388,
+ "__RESOLVED_ARTIFACTS_HASH": 1764595048,
+ "artifacts": {
+ "com.beust:jcommander": {
+ "shasums": {
+ "jar": "deeac157c8de6822878d85d0c7bc8467a19cc8484d37788f7804f039dde280b1"
+ },
+ "version": "1.82"
+ },
+ "com.google.auto.value:auto-value-annotations": {
+ "shasums": {
+ "jar": "37ec09b47d7ed35a99d13927db5c86fc9071f620f943ead5d757144698310852"
+ },
+ "version": "1.8.1"
+ },
+ "com.google.code.findbugs:jsr305": {
+ "shasums": {
+ "jar": "766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7"
+ },
+ "version": "3.0.2"
+ },
+ "com.google.errorprone:error_prone_annotations": {
+ "shasums": {
+ "jar": "721cb91842b46fa056847d104d5225c8b8e1e8b62263b993051e1e5a0137b7ec"
+ },
+ "version": "2.11.0"
+ },
+ "com.google.escapevelocity:escapevelocity": {
+ "shasums": {
+ "jar": "37e76e4466836dedb864fb82355cd01c3bd21325ab642d89a0f759291b171231"
+ },
+ "version": "1.1"
+ },
+ "com.google.guava:failureaccess": {
+ "shasums": {
+ "jar": "a171ee4c734dd2da837e4b16be9df4661afab72a41adaf31eb84dfdaf936ca26"
+ },
+ "version": "1.0.1"
+ },
+ "com.google.guava:guava": {
+ "shasums": {
+ "jar": "a42edc9cab792e39fe39bb94f3fca655ed157ff87a8af78e1d6ba5b07c4a00ab"
+ },
+ "version": "31.1-jre"
+ },
+ "com.google.guava:listenablefuture": {
+ "shasums": {
+ "jar": "b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99"
+ },
+ "version": "9999.0-empty-to-avoid-conflict-with-guava"
+ },
+ "com.google.j2objc:j2objc-annotations": {
+ "shasums": {
+ "jar": "21af30c92267bd6122c0e0b4d20cccb6641a37eaf956c6540ec471d584e64a7b"
+ },
+ "version": "1.3"
+ },
+ "com.google.truth:truth": {
+ "shasums": {
+ "jar": "fc0b67782289a2aabfddfdf99eff1dcd5edc890d49143fcd489214b107b8f4f3"
+ },
+ "version": "1.1.3"
+ },
+ "junit:junit": {
+ "shasums": {
+ "jar": "8e495b634469d64fb8acfa3495a065cbacc8a0fff55ce1e31007be4c16dc57d3"
+ },
+ "version": "4.13.2"
+ },
+ "org.checkerframework:checker-qual": {
+ "shasums": {
+ "jar": "3ea0dcd73b4d6cb2fb34bd7ed4dad6db327a01ebad7db05eb7894076b3d64491"
+ },
+ "version": "3.13.0"
+ },
+ "org.hamcrest:hamcrest-core": {
+ "shasums": {
+ "jar": "66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9"
+ },
+ "version": "1.3"
+ },
+ "org.ow2.asm:asm": {
+ "shasums": {
+ "jar": "cda4de455fab48ff0bcb7c48b4639447d4de859a7afc30a094a986f0936beba2"
+ },
+ "version": "9.1"
+ }
+ },
+ "dependencies": {
+ "com.google.escapevelocity:escapevelocity": [
+ "com.google.guava:guava"
+ ],
+ "com.google.guava:guava": [
+ "com.google.code.findbugs:jsr305",
+ "com.google.errorprone:error_prone_annotations",
+ "com.google.guava:failureaccess",
+ "com.google.guava:listenablefuture",
+ "com.google.j2objc:j2objc-annotations",
+ "org.checkerframework:checker-qual"
+ ],
+ "com.google.truth:truth": [
+ "com.google.auto.value:auto-value-annotations",
+ "com.google.errorprone:error_prone_annotations",
+ "com.google.guava:guava",
+ "junit:junit",
+ "org.checkerframework:checker-qual",
+ "org.ow2.asm:asm"
+ ],
+ "junit:junit": [
+ "org.hamcrest:hamcrest-core"
+ ]
+ },
+ "packages": {
+ "com.beust:jcommander": [
+ "com.beust.ah",
+ "com.beust.jcommander",
+ "com.beust.jcommander.converters",
+ "com.beust.jcommander.defaultprovider",
+ "com.beust.jcommander.internal",
+ "com.beust.jcommander.parser",
+ "com.beust.jcommander.validators"
+ ],
+ "com.google.auto.value:auto-value-annotations": [
+ "com.google.auto.value",
+ "com.google.auto.value.extension.memoized",
+ "com.google.auto.value.extension.serializable",
+ "com.google.auto.value.extension.toprettystring"
+ ],
+ "com.google.code.findbugs:jsr305": [
+ "javax.annotation",
+ "javax.annotation.concurrent",
+ "javax.annotation.meta"
+ ],
+ "com.google.errorprone:error_prone_annotations": [
+ "com.google.errorprone.annotations",
+ "com.google.errorprone.annotations.concurrent"
+ ],
+ "com.google.escapevelocity:escapevelocity": [
+ "com.google.escapevelocity"
+ ],
+ "com.google.guava:failureaccess": [
+ "com.google.common.util.concurrent.internal"
+ ],
+ "com.google.guava:guava": [
+ "com.google.common.annotations",
+ "com.google.common.base",
+ "com.google.common.base.internal",
+ "com.google.common.cache",
+ "com.google.common.collect",
+ "com.google.common.escape",
+ "com.google.common.eventbus",
+ "com.google.common.graph",
+ "com.google.common.hash",
+ "com.google.common.html",
+ "com.google.common.io",
+ "com.google.common.math",
+ "com.google.common.net",
+ "com.google.common.primitives",
+ "com.google.common.reflect",
+ "com.google.common.util.concurrent",
+ "com.google.common.xml",
+ "com.google.thirdparty.publicsuffix"
+ ],
+ "com.google.j2objc:j2objc-annotations": [
+ "com.google.j2objc.annotations"
+ ],
+ "com.google.truth:truth": [
+ "com.google.common.truth"
+ ],
+ "junit:junit": [
+ "junit.extensions",
+ "junit.framework",
+ "junit.runner",
+ "junit.textui",
+ "org.junit",
+ "org.junit.experimental",
+ "org.junit.experimental.categories",
+ "org.junit.experimental.max",
+ "org.junit.experimental.results",
+ "org.junit.experimental.runners",
+ "org.junit.experimental.theories",
+ "org.junit.experimental.theories.internal",
+ "org.junit.experimental.theories.suppliers",
+ "org.junit.function",
+ "org.junit.internal",
+ "org.junit.internal.builders",
+ "org.junit.internal.management",
+ "org.junit.internal.matchers",
+ "org.junit.internal.requests",
+ "org.junit.internal.runners",
+ "org.junit.internal.runners.model",
+ "org.junit.internal.runners.rules",
+ "org.junit.internal.runners.statements",
+ "org.junit.matchers",
+ "org.junit.rules",
+ "org.junit.runner",
+ "org.junit.runner.manipulation",
+ "org.junit.runner.notification",
+ "org.junit.runners",
+ "org.junit.runners.model",
+ "org.junit.runners.parameterized",
+ "org.junit.validator"
+ ],
+ "org.checkerframework:checker-qual": [
+ "org.checkerframework.checker.builder.qual",
+ "org.checkerframework.checker.calledmethods.qual",
+ "org.checkerframework.checker.compilermsgs.qual",
+ "org.checkerframework.checker.fenum.qual",
+ "org.checkerframework.checker.formatter.qual",
+ "org.checkerframework.checker.guieffect.qual",
+ "org.checkerframework.checker.i18n.qual",
+ "org.checkerframework.checker.i18nformatter.qual",
+ "org.checkerframework.checker.index.qual",
+ "org.checkerframework.checker.initialization.qual",
+ "org.checkerframework.checker.interning.qual",
+ "org.checkerframework.checker.lock.qual",
+ "org.checkerframework.checker.nullness.qual",
+ "org.checkerframework.checker.optional.qual",
+ "org.checkerframework.checker.propkey.qual",
+ "org.checkerframework.checker.regex.qual",
+ "org.checkerframework.checker.signature.qual",
+ "org.checkerframework.checker.signedness.qual",
+ "org.checkerframework.checker.tainting.qual",
+ "org.checkerframework.checker.units.qual",
+ "org.checkerframework.common.aliasing.qual",
+ "org.checkerframework.common.initializedfields.qual",
+ "org.checkerframework.common.reflection.qual",
+ "org.checkerframework.common.returnsreceiver.qual",
+ "org.checkerframework.common.subtyping.qual",
+ "org.checkerframework.common.util.report.qual",
+ "org.checkerframework.common.value.qual",
+ "org.checkerframework.dataflow.qual",
+ "org.checkerframework.framework.qual"
+ ],
+ "org.hamcrest:hamcrest-core": [
+ "org.hamcrest",
+ "org.hamcrest.core",
+ "org.hamcrest.internal"
+ ],
+ "org.ow2.asm:asm": [
+ "org.objectweb.asm",
+ "org.objectweb.asm.signature"
+ ]
+ },
+ "repositories": {
+ "https://repo1.maven.org/maven2/": [
+ "com.beust:jcommander",
+ "com.google.auto.value:auto-value-annotations",
+ "com.google.code.findbugs:jsr305",
+ "com.google.errorprone:error_prone_annotations",
+ "com.google.escapevelocity:escapevelocity",
+ "com.google.guava:failureaccess",
+ "com.google.guava:guava",
+ "com.google.guava:listenablefuture",
+ "com.google.j2objc:j2objc-annotations",
+ "com.google.truth:truth",
+ "junit:junit",
+ "org.checkerframework:checker-qual",
+ "org.hamcrest:hamcrest-core",
+ "org.ow2.asm:asm"
+ ]
+ },
+ "version": "2"
+}
diff --git a/rules_jvm_external.patch b/rules_jvm_external.patch
new file mode 100644
index 0000000..8344889
--- /dev/null
+++ b/rules_jvm_external.patch
@@ -0,0 +1,142 @@
+commit 569fe4da2530d7b1356265d7cc62ca74f93ec7e5
+Author: Yun Peng <pcloudy@google.com>
+Date: Thu Jan 5 16:37:29 2023 +0800
+
+ Add targets to make it easier to vendor the `@maven` repository
+
+ This change is required to support Bazel's offline bootstrap build.
+ More context in https://github.com/bazelbuild/bazel/pull/17112
+
+ Instead of checking in jar files in Bazel's source tree, Bazel wants to use rules_jvm_external
+ to fetch jars dependencies. However, to support Bazel's bootstrap build,
+ we need to patch rules_jvm_external for vendoring the @maven repository.
+
+ - Generate a BUILD.vendor file to be used in the vendored `@maven` repository.
+ Added a jvm_import and a filegroup rule for each downloaded jar artifact.
+ The filegroup rule is required by the bootstrap Java toolchain used in Bazel's
+ bootstrap build. The bootstrap Java toolchain cannot depend on a jvm_import target.
+ Because the jvm_import rule depends on a java_binary tool "AddJarManifestEntry",
+ which requires a Java toolchain. Depending on the jar via a filegroup rule helps
+ avoid this cyclic dependency.
+ - Added a filegroup rule to collect all sources needed for vendoring `@maven`,
+ including BUILD.vendor, WORKSPACE and jar files.
+
+diff --git a/coursier.bzl b/coursier.bzl
+index a71507a..90b4cb0 100644
+--- a/coursier.bzl
++++ b/coursier.bzl
+@@ -49,6 +49,12 @@ bzl_library(
+ )
+ """
+
++_BUILD_VENDOR = """
++load("@rules_jvm_external//private/rules:jvm_import.bzl", "jvm_import")
++
++{vendor_targets}
++"""
++
+ DEFAULT_AAR_IMPORT_LABEL = "@build_bazel_rules_android//android:rules.bzl"
+
+ _AAR_IMPORT_STATEMENT = """\
+@@ -473,7 +479,7 @@ def _pinned_coursier_fetch_impl(repository_ctx):
+ )
+
+ repository_ctx.report_progress("Generating BUILD targets..")
+- (generated_imports, jar_versionless_target_labels) = parser.generate_imports(
++ (generated_imports, jar_versionless_target_labels, generated_vendor_targets) = parser.generate_imports(
+ repository_ctx = repository_ctx,
+ dependencies = importer.get_artifacts(maven_install_json_content),
+ explicit_artifacts = {
+@@ -512,6 +518,14 @@ def _pinned_coursier_fetch_impl(repository_ctx):
+ executable = False,
+ )
+
++ repository_ctx.file(
++ "BUILD.vendor",
++ (_BUILD_VENDOR).format(
++ vendor_targets = generated_vendor_targets,
++ ),
++ executable = False,
++ )
++
+ _add_outdated_files(repository_ctx, artifacts, repositories)
+
+ # Generate a compatibility layer of external repositories for all jar artifacts.
+@@ -1036,7 +1050,7 @@ def _coursier_fetch_impl(repository_ctx):
+ )
+
+ repository_ctx.report_progress("Generating BUILD targets..")
+- (generated_imports, jar_versionless_target_labels) = parser.generate_imports(
++ (generated_imports, jar_versionless_target_labels, _) = parser.generate_imports(
+ repository_ctx = repository_ctx,
+ dependencies = v2_lock_file.get_artifacts(lock_file_contents),
+ explicit_artifacts = {
+diff --git a/private/dependency_tree_parser.bzl b/private/dependency_tree_parser.bzl
+index 8eea757..0a53528 100644
+--- a/private/dependency_tree_parser.bzl
++++ b/private/dependency_tree_parser.bzl
+@@ -107,6 +107,9 @@ def _generate_imports(repository_ctx, dependencies, explicit_artifacts, neverlin
+ for jetify_include_artifact in repository_ctx.attr.jetify_include_list:
+ jetify_include_dict[jetify_include_artifact] = None
+
++ artifact_paths = []
++ vendor_targets = []
++
+ # Iterate through the list of artifacts, and generate the target declaration strings.
+ for artifact in dependencies:
+ artifact_path = artifact["file"]
+@@ -347,6 +350,7 @@ def _generate_imports(repository_ctx, dependencies, explicit_artifacts, neverlin
+ target_import_string.append(")")
+
+ all_imports.append("\n".join(target_import_string))
++ vendor_targets.append("\n".join(target_import_string))
+
+ # 10. Create a versionless alias target
+ #
+@@ -357,6 +361,9 @@ def _generate_imports(repository_ctx, dependencies, explicit_artifacts, neverlin
+ versioned_target_alias_label = escape(strip_packaging_and_classifier(artifact["coordinates"]))
+ all_imports.append("alias(\n\tname = \"%s\",\n\tactual = \"%s\",\n%s)" %
+ (versioned_target_alias_label, target_label, alias_visibility))
++ file_group_target_string = "filegroup(\n\tname = \"%s\",\n\tsrcs = [\"%s\"],\n%s)" % (target_label + "_file", artifact_path, alias_visibility)
++ all_imports.append(file_group_target_string)
++ vendor_targets.append(file_group_target_string)
+
+ # 11. If using maven_install.json, use a genrule to copy the file from the http_file
+ # repository into this repository.
+@@ -370,6 +377,9 @@ def _generate_imports(repository_ctx, dependencies, explicit_artifacts, neverlin
+ if repository_ctx.attr.maven_install_json:
+ all_imports.append(_genrule_copy_artifact_from_http_file(artifact, default_visibilities))
+
++ # 12. collect the artifact_path for the filegroup rule collecting all necessary sources for vendoring
++ artifact_paths.append("\"%s\"" % artifact_path)
++
+ else: # artifact_path == None:
+ # Special case for certain artifacts that only come with a POM file.
+ # Such artifacts "aggregate" their dependencies, so they don't have
+@@ -421,7 +431,10 @@ def _generate_imports(repository_ctx, dependencies, explicit_artifacts, neverlin
+ all_imports.append("alias(\n\tname = \"%s\",\n\tactual = \"%s\",\n%s)" %
+ (versioned_target_alias_label, target_label, alias_visibility))
+
+- return ("\n".join(all_imports), jar_versionless_target_labels)
++ all_imports.append("filegroup(\n\tname = \"srcs\",\n\tsrcs = [\n\t\t%s,\n\t],\n\tvisibility = [\"//visibility:public\"],\n)" %
++ (",\n\t\t".join(["\"BUILD.vendor\"", "\"defs.bzl\"", "\"WORKSPACE\""] + artifact_paths)))
++
++ return ("\n".join(all_imports), jar_versionless_target_labels, "\n".join(vendor_targets))
+
+ parser = struct(
+ generate_imports = _generate_imports,
+diff --git a/private/tools/java/com/github/bazelbuild/rules_jvm_external/BUILD b/private/tools/java/com/github/bazelbuild/rules_jvm_external/BUILD
+index 63ce118..84e0417 100644
+--- a/private/tools/java/com/github/bazelbuild/rules_jvm_external/BUILD
++++ b/private/tools/java/com/github/bazelbuild/rules_jvm_external/BUILD
+@@ -1,10 +1,6 @@
+ java_library(
+ name = "rules_jvm_external",
+ srcs = glob(["*.java"]),
+- javacopts = [
+- "--release",
+- "8",
+- ],
+ visibility = [
+ "//private/tools/java:__subpackages__",
+ "//tests/com:__subpackages__",
diff --git a/setup.bzl b/setup.bzl
index dd39565..d9baa7a 100644
--- a/setup.bzl
+++ b/setup.bzl
@@ -12,31 +12,84 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-"""Repository external dependency resolution functions."""
+"""WORKSPACE prerequisites for Stardoc."""
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
-
-def _include_if_not_defined(repo_rule, name, **kwargs):
- if not native.existing_rule(name):
- repo_rule(name = name, **kwargs)
+load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
def stardoc_repositories():
- """Adds the external repositories used by the Starlark rules."""
- _include_if_not_defined(
+ """Adds the external repositories for rules used by Stardoc."""
+ maybe(
http_archive,
name = "bazel_skylib",
urls = [
- "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.2.1/bazel-skylib-1.2.1.tar.gz",
- "https://github.com/bazelbuild/bazel-skylib/releases/download/1.2.1/bazel-skylib-1.2.1.tar.gz",
+ "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.4.2/bazel-skylib-1.4.2.tar.gz",
+ "https://github.com/bazelbuild/bazel-skylib/releases/download/1.4.2/bazel-skylib-1.4.2.tar.gz",
+ ],
+ sha256 = "66ffd9315665bfaafc96b52278f57c7e2dd09f5ede279ea6d39b2be471e7e3aa",
+ )
+
+ maybe(
+ http_archive,
+ name = "com_google_protobuf",
+ sha256 = "75be42bd736f4df6d702a0e4e4d30de9ee40eac024c4b845d17ae4cc831fe4ae",
+ strip_prefix = "protobuf-21.7",
+ urls = [
+ "https://mirror.bazel.build/github.com/protocolbuffers/protobuf/archive/v21.7.tar.gz",
+ "https://github.com/protocolbuffers/protobuf/archive/v21.7.tar.gz",
],
- sha256 = "f7be3474d42aae265405a592bb7da8e171919d74c16f082a5457840f06054728",
)
- _include_if_not_defined(
+
+ maybe(
http_archive,
name = "rules_java",
urls = [
- "https://mirror.bazel.build/github.com/bazelbuild/rules_java/releases/download/4.0.0/rules_java-4.0.0.tar.gz",
- "https://github.com/bazelbuild/rules_java/releases/download/4.0.0/rules_java-4.0.0.tar.gz",
+ "https://mirror.bazel.build/github.com/bazelbuild/rules_java/releases/download/6.3.0/rules_java-6.3.0.tar.gz",
+ "https://github.com/bazelbuild/rules_java/releases/download/6.3.0/rules_java-6.3.0.tar.gz",
],
- sha256 = "34b41ec683e67253043ab1a3d1e8b7c61e4e8edefbcad485381328c934d072fe",
+ sha256 = "29ba147c583aaf5d211686029842c5278e12aaea86f66bd4a9eb5e525b7f2701",
+ )
+
+ RULES_JVM_EXTERNAL_TAG = "5.2"
+ RULES_JVM_EXTERNAL_SHA = "f86fd42a809e1871ca0aabe89db0d440451219c3ce46c58da240c7dcdc00125f"
+ maybe(
+ http_archive,
+ name = "rules_jvm_external",
+ patch_args = ["-p1"],
+ patches = ["@io_bazel_stardoc//:rules_jvm_external.patch"],
+ strip_prefix = "rules_jvm_external-%s" % RULES_JVM_EXTERNAL_TAG,
+ sha256 = RULES_JVM_EXTERNAL_SHA,
+ url = "https://github.com/bazelbuild/rules_jvm_external/releases/download/%s/rules_jvm_external-%s.tar.gz" % (RULES_JVM_EXTERNAL_TAG, RULES_JVM_EXTERNAL_TAG),
+ )
+
+ maybe(
+ http_archive,
+ name = "rules_license",
+ urls = [
+ "https://mirror.bazel.build/github.com/bazelbuild/rules_license/releases/download/0.0.7/rules_license-0.0.7.tar.gz",
+ "https://github.com/bazelbuild/rules_license/releases/download/0.0.7/rules_license-0.0.7.tar.gz",
+ ],
+ sha256 = "4531deccb913639c30e5c7512a054d5d875698daeb75d8cf90f284375fe7c360",
+ )
+
+ # Transitive dep of com_google_protobuf. Unfortunately, protobuf_deps()
+ # pulls in a dep that's too old.
+ maybe(
+ http_archive,
+ name = "rules_proto",
+ sha256 = "dc3fb206a2cb3441b485eb1e423165b231235a1ea9b031b4433cf7bc1fa460dd",
+ strip_prefix = "rules_proto-5.3.0-21.7",
+ urls = [
+ "https://github.com/bazelbuild/rules_proto/archive/refs/tags/5.3.0-21.7.tar.gz",
+ ],
+ )
+
+ # Transitive dep of com_google_protobuf. Unfortunately, protobuf_deps()
+ # pulls in a dep that's too old.
+ maybe(
+ http_archive,
+ name = "rules_python",
+ sha256 = "a644da969b6824cc87f8fe7b18101a8a6c57da5db39caa6566ec6109f37d2141",
+ strip_prefix = "rules_python-0.20.0",
+ url = "https://github.com/bazelbuild/rules_python/releases/download/0.20.0/rules_python-0.20.0.tar.gz",
)
diff --git a/src/main/java/com/google/devtools/build/skydoc/renderer/BUILD b/src/main/java/com/google/devtools/build/skydoc/renderer/BUILD
new file mode 100644
index 0000000..deab52e
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/skydoc/renderer/BUILD
@@ -0,0 +1,45 @@
+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
new file mode 100644
index 0000000..3e424d8
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/skydoc/renderer/FileSystemAccessor.java
@@ -0,0 +1,45 @@
+// 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
new file mode 100644
index 0000000..3b75d9b
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/skydoc/renderer/ProtoFileAccessor.java
@@ -0,0 +1,42 @@
+// 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
new file mode 100644
index 0000000..39b11df
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/skydoc/renderer/RendererMain.java
@@ -0,0 +1,260 @@
+// 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
new file mode 100644
index 0000000..52ed165
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/skydoc/renderer/RendererOptions.java
@@ -0,0 +1,83 @@
+// 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
new file mode 100644
index 0000000..014af3b
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/skydoc/rendering/BUILD
@@ -0,0 +1,27 @@
+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
new file mode 100644
index 0000000..2ff4a4e
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/skydoc/rendering/MarkdownRenderer.java
@@ -0,0 +1,223 @@
+// 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
new file mode 100644
index 0000000..afb2b5e
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/skydoc/rendering/MarkdownUtil.java
@@ -0,0 +1,443 @@
+// Copyright 2018 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.skydoc.rendering;
+
+import static com.google.common.collect.ImmutableList.toImmutableList;
+import static java.util.Comparator.naturalOrder;
+import static java.util.stream.Collectors.joining;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.AspectInfo;
+import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.AttributeInfo;
+import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.AttributeType;
+import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.FunctionParamInfo;
+import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.ModuleExtensionInfo;
+import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.ModuleExtensionTagClassInfo;
+import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.ProviderInfo;
+import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.ProviderNameGroup;
+import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.RepositoryRuleInfo;
+import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.RuleInfo;
+import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.StarlarkFunctionInfo;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/** Contains a number of utility methods for markdown rendering. */
+public final class MarkdownUtil {
+ private final String extensionBzlFile;
+
+ private static final int MAX_LINE_LENGTH = 100;
+
+ public MarkdownUtil(String extensionBzlFile) {
+ this.extensionBzlFile = extensionBzlFile;
+ }
+
+ /**
+ * Formats the input string so that it is displayable in a Markdown table cell. This performs the
+ * following operations:
+ *
+ * <ul>
+ * <li>Trims the string of leading/trailing whitespace.
+ * <li>Escapes pipe characters ({@code |}) as {@code \|}.
+ * <li>Transforms Markdown code blocks ({@code ```}) into HTML preformatted code blocks, and
+ * transforms newlines within those code blocks into character entities
+ * <li>Transforms remaining 'new paragraph' patterns (two or more sequential newline characters)
+ * into line break HTML tags.
+ * <li>Turns remaining newlines into spaces (as they generally indicate intended line wrap).
+ * </ul>
+ *
+ * TODO(https://github.com/bazelbuild/stardoc/issues/118): also format Markdown lists as HTML.
+ */
+ public static String markdownCellFormat(String docString) {
+ return new MarkdownCellFormatter(docString).format();
+ }
+
+ // See https://github.github.com/gfm
+ private static final class MarkdownCellFormatter {
+ // Lines of the input docstring, without newline terminators.
+ private final ImmutableList<String> lines;
+ // Index of the current line in lines, 0-based.
+ int currentLine;
+ // Formatted result.
+ StringBuilder result;
+
+ private static final Pattern CODE_BLOCK_OPENING_FENCE =
+ Pattern.compile("^ {0,3}(?<fence>```+|~~~+) *(?<lang>\\w*)[^`~]*$");
+
+ MarkdownCellFormatter(String docString) {
+ lines = docString.trim().replace("|", "\\|").lines().collect(toImmutableList());
+ currentLine = 0;
+ result = new StringBuilder();
+ }
+
+ /** Consumes the input and yields the formatted result. */
+ String format() {
+ boolean prefixContentWithSpace = false;
+ for (; currentLine < lines.size(); currentLine++) {
+ if (formatParagraphBreak()) {
+ prefixContentWithSpace = false;
+ continue;
+ }
+ if (prefixContentWithSpace) {
+ result.append(" ");
+ }
+ prefixContentWithSpace = true;
+ if (formatFencedCodeBlock()) {
+ continue;
+ }
+ result.append(lines.get(currentLine));
+ }
+ return result.toString();
+ }
+
+ /**
+ * If a fenced code block begins at {@link #currentLine}, render to {@link #result}, update
+ * {@link #currentLine} to point to the closing fence, and return true.
+ */
+ private boolean formatFencedCodeBlock() {
+ // See https://github.github.com/gfm/#fenced-code-blocks
+ Matcher opening = CODE_BLOCK_OPENING_FENCE.matcher(lines.get(currentLine));
+ if (!opening.matches()) {
+ return false;
+ }
+ Pattern closingFence = Pattern.compile("^ {0,3}" + opening.group("fence") + " *$");
+ for (int closingLine = currentLine + 1; closingLine < lines.size(); closingLine++) {
+ if (closingFence.matcher(lines.get(closingLine)).matches()) {
+ // We found the closing fence: format the block's contents as HTML.
+ String language = opening.group("lang");
+ if (language != null && !language.isEmpty()) {
+ result.append("<pre><code class=\"language-").append(language).append("\">");
+ } else {
+ result.append("<pre><code>");
+ }
+ int firstContentLine = currentLine + 1;
+ for (int i = firstContentLine; i < closingLine; i++) {
+ if (i > firstContentLine) {
+ result.append(newlineEscape("\n"));
+ }
+ result.append(htmlEscape(lines.get(i)));
+ }
+ result.append("</code></pre>");
+ currentLine = closingLine;
+ return true;
+ }
+ }
+ // We did not find the closing fence.
+ return false;
+ }
+
+ /**
+ * If blank lines appear at {@link #currentLine}, render to {@link #result}, update {@link
+ * #currentLine} to point to the last line of the break, and return true.
+ */
+ private boolean formatParagraphBreak() {
+ int numEmptyLines = 0;
+ for (int i = currentLine; i < lines.size(); i++) {
+ if (lines.get(i).isEmpty()) {
+ numEmptyLines++;
+ } else {
+ break;
+ }
+ }
+ if (numEmptyLines > 0) {
+ result.append("<br><br>");
+ currentLine += numEmptyLines - 1;
+ return true;
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Return a string that escapes angle brackets for HTML.
+ *
+ * <p>For example: 'Information with <brackets>.' becomes 'Information with &lt;brackets&gt;'.
+ */
+ public static String htmlEscape(String docString) {
+ return docString.replace("<", "&lt;").replace(">", "&gt;");
+ }
+
+ /** Returns a string that escapes newlines with HTML entities. */
+ private static String newlineEscape(String docString) {
+ return docString.replace("\n", "&#10;");
+ }
+
+ private static final Pattern CONSECUTIVE_BACKTICKS = Pattern.compile("`+");
+
+ /**
+ * Returns a Markdown code span (e.g. {@code `return foo;`}) that contains the given literal text,
+ * which may itself contain backticks.
+ *
+ * <p>For example:
+ *
+ * <ul>
+ * <li>{@code markdownCodeSpan("foo")} returns {@code "`foo`"}
+ * <li>{@code markdownCodeSpan("fo`o")} returns {@code "``fo`o``"}
+ * <li>{@code markdownCodeSpan("`foo`")} returns {@code "`` foo` ``""}
+ * </ul>
+ */
+ public static String markdownCodeSpan(String code) {
+ // https://github.github.com/gfm/#code-span
+ int numConsecutiveBackticks =
+ CONSECUTIVE_BACKTICKS
+ .matcher(code)
+ .results()
+ .map(match -> match.end() - match.start())
+ .max(naturalOrder())
+ .orElse(0);
+ String padding = code.startsWith("`") || code.endsWith("`") ? " " : "";
+ return String.format(
+ "%1$s%2$s%3$s%2$s%1$s", "`".repeat(numConsecutiveBackticks + 1), padding, code);
+ }
+
+ /**
+ * Return a string representing the rule summary for the given rule with the given name.
+ *
+ * <p>For example: 'my_rule(foo, bar)'. The summary will contain hyperlinks for each attribute.
+ */
+ @SuppressWarnings("unused") // Used by markdown template.
+ public String ruleSummary(String ruleName, RuleInfo ruleInfo) {
+ ImmutableList<String> attributeNames =
+ ruleInfo.getAttributeList().stream().map(AttributeInfo::getName).collect(toImmutableList());
+ return summary(ruleName, attributeNames);
+ }
+
+ /**
+ * Return a string representing the summary for the given provider with the given name.
+ *
+ * <p>For example: 'MyInfo(foo, bar)'. The summary will contain hyperlinks for each field.
+ */
+ @SuppressWarnings("unused") // Used by markdown template.
+ public String providerSummary(String providerName, ProviderInfo providerInfo) {
+ ImmutableList<String> fieldNames =
+ providerInfo.getFieldInfoList().stream()
+ .map(field -> field.getName())
+ .collect(toImmutableList());
+ return summary(providerName, fieldNames);
+ }
+
+ /**
+ * Return a string representing the aspect summary for the given aspect with the given name.
+ *
+ * <p>For example: 'my_aspect(foo, bar)'. The summary will contain hyperlinks for each attribute.
+ */
+ @SuppressWarnings("unused") // Used by markdown template.
+ public String aspectSummary(String aspectName, AspectInfo aspectInfo) {
+ ImmutableList<String> attributeNames =
+ aspectInfo.getAttributeList().stream()
+ .map(AttributeInfo::getName)
+ .collect(toImmutableList());
+ return summary(aspectName, attributeNames);
+ }
+
+ /**
+ * Return a string representing the repository rule summary for the given repository rule with the
+ * given name.
+ *
+ * <p>For example: 'my_repo_rule(foo, bar)'. The summary will contain hyperlinks for each
+ * attribute.
+ */
+ @SuppressWarnings("unused") // Used by markdown template.
+ public String repositoryRuleSummary(String ruleName, RepositoryRuleInfo ruleInfo) {
+ ImmutableList<String> attributeNames =
+ ruleInfo.getAttributeList().stream().map(AttributeInfo::getName).collect(toImmutableList());
+ return summary(ruleName, attributeNames);
+ }
+
+ /**
+ * Return a string representing the module extension summary for the given module extension with
+ * the given name.
+ *
+ * <p>For example:
+ *
+ * <pre>
+ * my_ext = use_extension("//some:file.bzl", "my_ext")
+ * my_ext.tag1(foo, bar)
+ * my_ext.tag2(baz)
+ * </pre>
+ *
+ * <p>The summary will contain hyperlinks for each attribute.
+ */
+ @SuppressWarnings("unused") // Used by markdown template.
+ public String moduleExtensionSummary(String extensionName, ModuleExtensionInfo extensionInfo) {
+ StringBuilder summaryBuilder = new StringBuilder();
+ summaryBuilder.append(
+ String.format(
+ "%s = use_extension(\"%s\", \"%s\")", extensionName, extensionBzlFile, extensionName));
+ for (ModuleExtensionTagClassInfo tagClass : extensionInfo.getTagClassList()) {
+ ImmutableList<String> attributeNames =
+ tagClass.getAttributeList().stream()
+ .map(AttributeInfo::getName)
+ .collect(toImmutableList());
+ summaryBuilder
+ .append("\n")
+ .append(
+ summary(
+ String.format("%s.%s", extensionName, tagClass.getTagName()), attributeNames));
+ }
+ return summaryBuilder.toString();
+ }
+
+ /**
+ * Return a string representing the summary for the given user-defined function.
+ *
+ * <p>For example: 'my_func(foo, bar)'. The summary will contain hyperlinks for each parameter.
+ */
+ @SuppressWarnings("unused") // Used by markdown template.
+ public String funcSummary(StarlarkFunctionInfo funcInfo) {
+ ImmutableList<String> paramNames =
+ funcInfo.getParameterList().stream()
+ .map(FunctionParamInfo::getName)
+ .collect(toImmutableList());
+ return summary(funcInfo.getFunctionName(), paramNames);
+ }
+
+ private static String summary(String functionName, ImmutableList<String> paramNames) {
+ ImmutableList<ImmutableList<String>> paramLines =
+ wrap(functionName, paramNames, MAX_LINE_LENGTH);
+ List<String> paramLinksLines = new ArrayList<>();
+ for (List<String> params : paramLines) {
+ String paramLinksLine =
+ params.stream()
+ .map(param -> String.format("<a href=\"#%s-%s\">%s</a>", functionName, param, param))
+ .collect(joining(", "));
+ paramLinksLines.add(paramLinksLine);
+ }
+ String paramList =
+ Joiner.on(",\n" + " ".repeat(functionName.length() + 1)).join(paramLinksLines);
+ return String.format("%s(%s)", functionName, paramList);
+ }
+
+ /**
+ * Wraps the given function parameter names to be able to construct a function summary that stays
+ * within the provided line length limit.
+ *
+ * @param functionName the function name.
+ * @param paramNames the function parameter names.
+ * @param maxLineLength the maximal line length.
+ * @return the lines with the wrapped parameter names.
+ */
+ private static ImmutableList<ImmutableList<String>> wrap(
+ String functionName, ImmutableList<String> paramNames, int maxLineLength) {
+ ImmutableList.Builder<ImmutableList<String>> paramLines = ImmutableList.builder();
+ ImmutableList.Builder<String> linesBuilder = new ImmutableList.Builder<>();
+ int leading = functionName.length();
+ int length = leading;
+ int punctuation = 2; // cater for left parenthesis/space before and comma after parameter
+ for (String paramName : paramNames) {
+ length += paramName.length() + punctuation;
+ if (length > maxLineLength) {
+ paramLines.add(linesBuilder.build());
+ length = leading + paramName.length();
+ linesBuilder = new ImmutableList.Builder<>();
+ }
+ linesBuilder.add(paramName);
+ }
+ paramLines.add(linesBuilder.build());
+ return paramLines.build();
+ }
+
+ /**
+ * Returns a string describing the given attribute's type. The description consists of a hyperlink
+ * if there is a relevant hyperlink to Bazel documentation available.
+ */
+ public String attributeTypeString(AttributeInfo attrInfo) {
+ String typeLink;
+ switch (attrInfo.getType()) {
+ case LABEL:
+ case LABEL_LIST:
+ case OUTPUT:
+ typeLink = "https://bazel.build/concepts/labels";
+ break;
+ case NAME:
+ typeLink = "https://bazel.build/concepts/labels#target-names";
+ break;
+ case STRING_DICT:
+ case STRING_LIST_DICT:
+ case LABEL_STRING_DICT:
+ typeLink = "https://bazel.build/rules/lib/dict";
+ break;
+ default:
+ typeLink = null;
+ break;
+ }
+ if (typeLink == null) {
+ return attributeTypeDescription(attrInfo.getType());
+ } else {
+ return String.format(
+ "<a href=\"%s\">%s</a>", typeLink, attributeTypeDescription(attrInfo.getType()));
+ }
+ }
+
+ public String mandatoryString(AttributeInfo attrInfo) {
+ return attrInfo.getMandatory() ? "required" : "optional";
+ }
+
+ /**
+ * Returns "required" if providing a value for this parameter is mandatory. Otherwise, returns
+ * "optional".
+ */
+ public String mandatoryString(FunctionParamInfo paramInfo) {
+ return paramInfo.getMandatory() ? "required" : "optional";
+ }
+
+ /**
+ * Return a string explaining what providers an attribute requires. Adds hyperlinks to providers.
+ */
+ public String attributeProviders(AttributeInfo attributeInfo) {
+ List<ProviderNameGroup> providerNames = attributeInfo.getProviderNameGroupList();
+ List<String> finalProviderNames = new ArrayList<>();
+ for (ProviderNameGroup providerNameList : providerNames) {
+ List<String> providers = providerNameList.getProviderNameList();
+ finalProviderNames.add(Joiner.on(", ").join(providers));
+ }
+ return Joiner.on("; or ").join(finalProviderNames);
+ }
+
+ private static String attributeTypeDescription(AttributeType attributeType) {
+ switch (attributeType) {
+ case NAME:
+ return "Name";
+ case INT:
+ return "Integer";
+ case STRING:
+ return "String";
+ case STRING_LIST:
+ return "List of strings";
+ case INT_LIST:
+ return "List of integers";
+ case BOOLEAN:
+ return "Boolean";
+ case LABEL_STRING_DICT:
+ return "Dictionary: Label -> String";
+ case STRING_DICT:
+ return "Dictionary: String -> String";
+ case STRING_LIST_DICT:
+ return "Dictionary: String -> List of strings";
+ case LABEL:
+ case OUTPUT:
+ return "Label";
+ case LABEL_LIST:
+ case OUTPUT_LIST:
+ return "List of labels";
+ case UNKNOWN:
+ case UNRECOGNIZED:
+ throw new IllegalArgumentException("Unhandled type " + attributeType);
+ }
+ throw new IllegalArgumentException("Unhandled type " + attributeType);
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/skydoc/rendering/BUILD b/src/test/java/com/google/devtools/build/skydoc/rendering/BUILD
new file mode 100644
index 0000000..2b89f20
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/skydoc/rendering/BUILD
@@ -0,0 +1,27 @@
+load("@rules_java//java:defs.bzl", "java_test")
+
+package(
+ default_applicable_licenses = ["//:license"],
+ default_visibility = [
+ "//src:__subpackages__",
+ "//stardoc:__subpackages__",
+ ],
+)
+
+filegroup(
+ name = "srcs",
+ testonly = 0,
+ srcs = glob(["*"]),
+ visibility = ["//:__pkg__"],
+)
+
+java_test(
+ name = "MarkdownUtilTest",
+ size = "small",
+ srcs = ["MarkdownUtilTest.java"],
+ deps = [
+ "//src/main/java/com/google/devtools/build/skydoc/rendering",
+ "@stardoc_maven//:com_google_truth_truth",
+ "@stardoc_maven//:junit_junit",
+ ],
+)
diff --git a/src/test/java/com/google/devtools/build/skydoc/rendering/MarkdownUtilTest.java b/src/test/java/com/google/devtools/build/skydoc/rendering/MarkdownUtilTest.java
new file mode 100644
index 0000000..4c37a38
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/skydoc/rendering/MarkdownUtilTest.java
@@ -0,0 +1,84 @@
+// 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.rendering;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests for MarkdownUtil. */
+@RunWith(JUnit4.class)
+public class MarkdownUtilTest {
+
+ MarkdownUtil util = new MarkdownUtil("//:test.bzl");
+
+ @Test
+ public void markdownCodeSpan() {
+ assertThat(MarkdownUtil.markdownCodeSpan("")).isEqualTo("``");
+ assertThat(MarkdownUtil.markdownCodeSpan("foo bar ")).isEqualTo("`foo bar `");
+ }
+
+ @Test
+ public void markdownCodeSpan_backticks() {
+ assertThat(MarkdownUtil.markdownCodeSpan("foo`bar")).isEqualTo("``foo`bar``");
+ assertThat(MarkdownUtil.markdownCodeSpan("foo``bar")).isEqualTo("```foo``bar```");
+ assertThat(MarkdownUtil.markdownCodeSpan("foo`bar```baz``quz"))
+ .isEqualTo("````foo`bar```baz``quz````");
+ }
+
+ @Test
+ public void markdownCodeSpan_backticksPadding() {
+ assertThat(MarkdownUtil.markdownCodeSpan("`foo")).isEqualTo("`` `foo ``");
+ assertThat(MarkdownUtil.markdownCodeSpan("``foo")).isEqualTo("``` ``foo ```");
+ assertThat(MarkdownUtil.markdownCodeSpan("foo`")).isEqualTo("`` foo` ``");
+ assertThat(MarkdownUtil.markdownCodeSpan("foo``")).isEqualTo("``` foo`` ```");
+ }
+
+ @Test
+ public void markdownCellFormat_pipes() {
+ assertThat(MarkdownUtil.markdownCellFormat("foo|bar")).isEqualTo("foo\\|bar");
+ assertThat(MarkdownUtil.markdownCellFormat("|\\|foobar||")).isEqualTo("\\|\\\\|foobar\\|\\|");
+ }
+
+ @Test
+ public void markdownCellFormat_newlines() {
+ assertThat(MarkdownUtil.markdownCellFormat("\nfoo\nbar\n\nbaz\r\n\r\n\r\nqux\r\n"))
+ .isEqualTo("foo bar<br><br>baz<br><br>qux");
+ // Newline escapes are not expanded
+ assertThat(MarkdownUtil.markdownCellFormat("hello\\r\\nworld")).isEqualTo("hello\\r\\nworld");
+ }
+
+ @Test
+ public void markdownCellFormat_codeBlocks() {
+ assertThat(MarkdownUtil.markdownCellFormat("```\nhello();\n```"))
+ .isEqualTo("<pre><code>hello();</code></pre>");
+ assertThat(MarkdownUtil.markdownCellFormat("```\nhello();\n```\nor\n~~~\nbye();\n~~~"))
+ .isEqualTo("<pre><code>hello();</code></pre> or <pre><code>bye();</code></pre>");
+ assertThat(MarkdownUtil.markdownCellFormat("```bash\ncat foo.txt | cmd > /dev/null\n```"))
+ .isEqualTo(
+ "<pre><code class=\"language-bash\">cat foo.txt \\| cmd &gt; /dev/null</code></pre>");
+ assertThat(MarkdownUtil.markdownCellFormat("````\n```\n```\n````"))
+ .isEqualTo("<pre><code>```&#10;```</code></pre>");
+ }
+
+ @Test
+ public void markdownCellFormat_inlineMarkup() {
+ assertThat(MarkdownUtil.markdownCellFormat("<b>bold</b> <i>italic</i>"))
+ .isEqualTo("<b>bold</b> <i>italic</i>");
+ assertThat(MarkdownUtil.markdownCellFormat("**bold** _italic_")).isEqualTo("**bold** _italic_");
+ }
+}
diff --git a/stardoc/BUILD b/stardoc/BUILD
index 3e82ca9..159ca0e 100644
--- a/stardoc/BUILD
+++ b/stardoc/BUILD
@@ -2,9 +2,12 @@ load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
load("//stardoc:stardoc.bzl", "stardoc")
load("@rules_java//java:defs.bzl", "java_binary", "java_import")
-licenses(["notice"]) # Apache 2.0
+licenses(["notice"])
-package(default_visibility = ["//visibility:public"])
+package(
+ default_applicable_licenses = ["//:license"],
+ default_visibility = ["//visibility:public"],
+)
exports_files(glob(["templates/**"]))
@@ -22,7 +25,9 @@ bzl_library(
srcs = ["stardoc.bzl"],
visibility = ["//visibility:public"],
deps = [
- "@bazel_skylib//:bzl_library",
+ "//stardoc/private:stardoc_lib",
+ "@bazel_skylib//rules:copy_file",
+ "@rules_java//java:rules",
],
)
@@ -47,14 +52,6 @@ stardoc(
java_binary(
name = "stardoc",
- jvm_flags = [
- # quiet warnings from com.google.protobuf.UnsafeUtil,
- # see: https://github.com/google/protobuf/issues/3781
- # TODO(cparsons): Remove once Stardoc has the fix.
- "-XX:+IgnoreUnrecognizedVMOptions",
- "--add-opens=java.base/java.nio=ALL-UNNAMED",
- "--add-opens=java.base/java.lang=ALL-UNNAMED",
- ],
main_class = "com.google.devtools.build.skydoc.SkydocMain",
runtime_deps = [
":prebuilt_stardoc_binary",
@@ -64,29 +61,12 @@ java_binary(
java_import(
name = "prebuilt_stardoc_binary",
jars = ["stardoc_binary.jar"],
- visibility = ["//visibility:private"],
+ visibility = ["//visibility:public"],
)
-java_binary(
+alias(
name = "renderer",
- jvm_flags = [
- # quiet warnings from com.google.protobuf.UnsafeUtil,
- # see: https://github.com/google/protobuf/issues/3781
- # TODO(cparsons): Remove once Stardoc has the fix.
- "-XX:+IgnoreUnrecognizedVMOptions",
- "--add-opens=java.base/java.nio=ALL-UNNAMED",
- "--add-opens=java.base/java.lang=ALL-UNNAMED",
- ],
- main_class = "com.google.devtools.build.skydoc.renderer.RendererMain",
- runtime_deps = [
- ":prebuilt_renderer_binary",
- ],
-)
-
-java_import(
- name = "prebuilt_renderer_binary",
- jars = ["renderer_binary.jar"],
- visibility = ["//visibility:private"],
+ actual = "//src/main/java/com/google/devtools/build/skydoc/renderer",
)
# Sources needed for release tarball.
diff --git a/stardoc/html_tables_stardoc.bzl b/stardoc/html_tables_stardoc.bzl
index 0fef7f8..e2487a5 100644
--- a/stardoc/html_tables_stardoc.bzl
+++ b/stardoc/html_tables_stardoc.bzl
@@ -33,5 +33,7 @@ def html_tables_stardoc(name, **kwargs):
header_template = Label("//stardoc:templates/html_tables/header.vm"),
provider_template = Label("//stardoc:templates/html_tables/provider.vm"),
rule_template = Label("//stardoc:templates/html_tables/rule.vm"),
+ repository_rule_template = Label("//stardoc:templates/html_tables/repository_rule.vm"),
+ module_extension_template = Label("//stardoc:templates/html_tables/module_extension.vm"),
**kwargs
)
diff --git a/stardoc/private/BUILD b/stardoc/private/BUILD
new file mode 100644
index 0000000..e3561b1
--- /dev/null
+++ b/stardoc/private/BUILD
@@ -0,0 +1,18 @@
+load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
+
+bzl_library(
+ name = "stardoc_lib",
+ srcs = ["stardoc.bzl"],
+ visibility = ["//stardoc:__pkg__"],
+)
+
+# Sources needed for release tarball.
+filegroup(
+ name = "distro_srcs",
+ srcs = [
+ "BUILD",
+ ] + glob([
+ "*.bzl",
+ ]),
+ visibility = ["//:__pkg__"],
+)
diff --git a/stardoc/private/stardoc.bzl b/stardoc/private/stardoc.bzl
new file mode 100644
index 0000000..16d1122
--- /dev/null
+++ b/stardoc/private/stardoc.bzl
@@ -0,0 +1,224 @@
+# 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."""
+
+def _renderer_action_run(ctx, out_file, proto_file):
+ """Helper for declaring the markdown renderer action"""
+ renderer_args = ctx.actions.args()
+ renderer_args.add("--input=" + str(proto_file.path))
+ renderer_args.add("--output=" + str(ctx.outputs.out.path))
+ renderer_args.add("--aspect_template=" + str(ctx.file.aspect_template.path))
+ renderer_args.add("--header_template=" + str(ctx.file.header_template.path))
+ renderer_args.add("--func_template=" + str(ctx.file.func_template.path))
+ renderer_args.add("--provider_template=" + str(ctx.file.provider_template.path))
+ renderer_args.add("--rule_template=" + str(ctx.file.rule_template.path))
+ renderer_args.add("--repository_rule_template=" + str(ctx.file.repository_rule_template.path))
+ renderer_args.add("--module_extension_template=" + str(ctx.file.module_extension_template.path))
+ renderer = ctx.executable.renderer
+ ctx.actions.run(
+ outputs = [out_file],
+ inputs = [
+ proto_file,
+ ctx.file.aspect_template,
+ ctx.file.header_template,
+ ctx.file.func_template,
+ ctx.file.provider_template,
+ ctx.file.rule_template,
+ ctx.file.repository_rule_template,
+ ctx.file.module_extension_template,
+ ],
+ executable = renderer,
+ arguments = [renderer_args],
+ mnemonic = "Renderer",
+ progress_message = ("Converting proto format of %s to markdown format" %
+ (ctx.label.name)),
+ )
+
+def _stardoc_impl(ctx):
+ """Implementation of the stardoc rule."""
+ for semantic_flag in ctx.attr.semantic_flags:
+ if not semantic_flag.startswith("--"):
+ fail("semantic_flags entry '%s' must start with '--'" % semantic_flag)
+ out_file = ctx.outputs.out
+ stardoc_args = ctx.actions.args()
+ stardoc_args.add("--input=" + str(ctx.file.input.owner))
+ stardoc_args.add("--workspace_name=" + ctx.workspace_name)
+ stardoc_args.add_all(
+ ctx.attr.symbol_names,
+ format_each = "--symbols=%s",
+ omit_if_empty = True,
+ )
+ stardoc_args.add_all(ctx.attr.semantic_flags)
+ stardoc = ctx.executable.stardoc
+
+ if ctx.attr.format == "proto":
+ stardoc_args.add("--output=" + out_file.path)
+ ctx.actions.run(
+ outputs = [out_file],
+ executable = stardoc,
+ arguments = [stardoc_args],
+ mnemonic = "Stardoc",
+ progress_message = ("Generating proto for Starlark doc for %s" %
+ (ctx.label.name)),
+ )
+ elif ctx.attr.format == "markdown":
+ proto_file = ctx.actions.declare_file(ctx.label.name + ".raw", sibling = out_file)
+ stardoc_args.add("--output=" + proto_file.path)
+ ctx.actions.run(
+ outputs = [proto_file],
+ executable = stardoc,
+ arguments = [stardoc_args],
+ mnemonic = "Stardoc",
+ progress_message = ("Generating proto for Starlark doc for %s" %
+ (ctx.label.name)),
+ )
+ _renderer_action_run(ctx, out_file = out_file, proto_file = proto_file)
+
+ # Work around default outputs not getting captured by sh_binary:
+ # https://github.com/bazelbuild/bazel/issues/15043.
+ # See discussion in https://github.com/bazelbuild/stardoc/pull/139.
+ outputs = [out_file]
+ return [DefaultInfo(files = depset(outputs), runfiles = ctx.runfiles(files = outputs))]
+
+_common_renderer_attrs = {
+ "out": attr.output(
+ doc = "The (markdown) file to which documentation will be output.",
+ mandatory = True,
+ ),
+ "renderer": attr.label(
+ doc = "The location of the renderer tool.",
+ allow_files = True,
+ cfg = "exec",
+ executable = True,
+ mandatory = True,
+ ),
+ "aspect_template": attr.label(
+ doc = "The input file template for generating documentation of aspects.",
+ allow_single_file = [".vm"],
+ mandatory = True,
+ ),
+ "header_template": attr.label(
+ doc = "The input file template for the header of the output documentation.",
+ allow_single_file = [".vm"],
+ mandatory = True,
+ ),
+ "func_template": attr.label(
+ doc = "The input file template for generating documentation of functions.",
+ allow_single_file = [".vm"],
+ mandatory = True,
+ ),
+ "provider_template": attr.label(
+ doc = "The input file template for generating documentation of providers.",
+ allow_single_file = [".vm"],
+ mandatory = True,
+ ),
+ "rule_template": attr.label(
+ doc = "The input file template for generating documentation of rules.",
+ allow_single_file = [".vm"],
+ mandatory = True,
+ ),
+ "repository_rule_template": attr.label(
+ doc = "The input file template for generating documentation of repository rules." +
+ " This template is not used when rendering the output of the legacy extractor.",
+ allow_single_file = [".vm"],
+ mandatory = True,
+ ),
+ "module_extension_template": attr.label(
+ doc = "The input file template for generating documentation of module extensions." +
+ " This template is not used when rendering the output of the legacy extractor.",
+ allow_single_file = [".vm"],
+ mandatory = True,
+ ),
+}
+
+# TODO(arostovtsev): replace with ... attrs = { ... } | _common_renderer_attrs
+# in rule definition below after we drop support for Bazel 5.
+_stardoc_attrs = {
+ "input": attr.label(
+ doc = "The starlark file to generate documentation for.",
+ allow_single_file = [".bzl"],
+ mandatory = True,
+ ),
+ "format": attr.string(
+ doc = "The format of the output file. Valid values: 'markdown' or 'proto'.",
+ values = ["markdown", "proto"],
+ 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.
+""",
+ mandatory = True,
+ ),
+ "semantic_flags": attr.string_list(
+ doc = """
+A list of canonical flags to affect Starlark semantics for the Starlark interpretter
+during documentation generation. This should only be used to maintain compatibility with
+non-default semantic flags required to use the given Starlark symbols.
+
+For example, if `//foo:bar.bzl` does not build except when a user would specify
+`--incompatible_foo_semantic=false`, then this attribute should contain
+"--incompatible_foo_semantic=false".
+""",
+ mandatory = True,
+ ),
+ "stardoc": attr.label(
+ doc = "The location of the stardoc tool.",
+ allow_files = True,
+ cfg = "exec",
+ executable = True,
+ mandatory = True,
+ ),
+}
+_stardoc_attrs.update(_common_renderer_attrs.items())
+
+stardoc = rule(
+ _stardoc_impl,
+ doc = """
+Generates documentation for starlark skylark rule definitions in a target starlark file.
+""",
+ attrs = _stardoc_attrs,
+)
+
+def _stardoc_markdown_renderer_impl(ctx):
+ out_file = ctx.outputs.out
+ _renderer_action_run(ctx, out_file = out_file, proto_file = ctx.file.src)
+
+ # Work around default outputs not getting captured by sh_binary:
+ # https://github.com/bazelbuild/bazel/issues/15043.
+ # See discussion in https://github.com/bazelbuild/stardoc/pull/139.
+ outputs = [out_file]
+ return [DefaultInfo(files = depset(outputs), runfiles = ctx.runfiles(files = outputs))]
+
+# TODO(arostovtsev): replace with ... attrs = { ... } | _common_renderer_attrs
+# in rule definition below after we drop support for Bazel 5.
+_stardoc_markdown_renderer_attrs = {
+ "src": attr.label(
+ doc = "The .binaryproto file from which to generate documentation.",
+ allow_single_file = [".binaryproto"],
+ mandatory = True,
+ ),
+}
+_stardoc_markdown_renderer_attrs.update(_common_renderer_attrs.items())
+
+stardoc_markdown_renderer = rule(
+ _stardoc_markdown_renderer_impl,
+ doc = """
+Generates markdown documentation for starlark rule definitions from the corresponding binary proto.
+""",
+ attrs = _stardoc_markdown_renderer_attrs,
+)
diff --git a/stardoc/proto/BUILD b/stardoc/proto/BUILD
index ff06c3b..4e9619b 100644
--- a/stardoc/proto/BUILD
+++ b/stardoc/proto/BUILD
@@ -1,6 +1,11 @@
+load("@rules_java//java:defs.bzl", "java_proto_library")
+
licenses(["notice"])
-package(default_visibility = ["//visibility:public"])
+package(
+ default_applicable_licenses = ["//:license"],
+ default_visibility = ["//visibility:public"],
+)
exports_files(["stardoc_output.proto"])
@@ -12,3 +17,13 @@ filegroup(
] + glob(["*.proto"]),
visibility = ["//:__pkg__"],
)
+
+proto_library(
+ name = "stardoc_output_proto",
+ srcs = ["stardoc_output.proto"],
+)
+
+java_proto_library(
+ name = "stardoc_output_java_proto",
+ deps = [":stardoc_output_proto"],
+)
diff --git a/stardoc/proto/stardoc_output.proto b/stardoc/proto/stardoc_output.proto
index e35e714..7176213 100644
--- a/stardoc/proto/stardoc_output.proto
+++ b/stardoc/proto/stardoc_output.proto
@@ -12,6 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
+// Vendored from src/main/java/com/google/devtools/build/skydoc/rendering/proto/stardoc_output.proto
+// in the Bazel source tree at commit e33c2d14728aea6914b165fe11f08ff4982196ca
+//
// Protos for Stardoc data.
//
// Stardoc collects information about Starlark functions, providers, and rules.
@@ -23,9 +26,9 @@ package stardoc_output;
option java_package = "com.google.devtools.build.skydoc.rendering.proto";
option java_outer_classname = "StardocOutputProtos";
-// The root output proto of Stardoc. A single invocation of Stardoc will output
-// exactly one instance of this proto, representing all documentation for
-// the input Starlark file.
+// The root output proto of Stardoc. An invocation of Stardoc on a single file
+// will output exactly one instance of this proto, representing all
+// documentation for the input Starlark file.
message ModuleInfo {
repeated RuleInfo rule_info = 1;
@@ -37,6 +40,15 @@ message ModuleInfo {
// The docstring present at the top of the input Starlark file.
string module_docstring = 5;
+
+ // The display form of the label of the module file (as seen from the
+ // starlark_doc_extract or Stardoc target's repo). Unset when there is no
+ // module file (e.g. when the module is a REPL, or in Bazel's internal tests).
+ string file = 6;
+
+ repeated ModuleExtensionInfo module_extension_info = 7;
+
+ repeated RepositoryRuleInfo repository_rule_info = 8;
}
// Representation of a Starlark rule attribute type. These generally
@@ -63,7 +75,8 @@ enum AttributeType {
// Representation of a Starlark rule definition.
message RuleInfo {
- // The name of the rule.
+ // The name under which the rule is made accessible to a user of this module,
+ // including any structs it is nested in, for example "foo.foo_library".
string rule_name = 1;
// The documentation string of the rule.
@@ -71,11 +84,22 @@ message RuleInfo {
// The attributes of the rule.
repeated AttributeInfo attribute = 3;
+
+ // The module where and the name under which the rule was originally declared.
+ //
+ // Note: legacy Stardoc (0.5.x and earlier) does not set this field.
+ OriginKey origin_key = 4;
+
+ // The list of providers that the rule's implementation must return. Unset if
+ // the rule lists no advertised providers.
+ //
+ // Note: legacy Stardoc (0.5.x and earlier) does not set this field.
+ ProviderNameGroup advertised_providers = 5;
}
-// Representation of a Starlark rule attribute definition, comprised of an
-// attribute name, and a schema defined by a call to one of the 'attr' module
-// methods enumerated at
+// Representation of a Starlark rule, repository rule, or module extension tag
+// attribute definition, comprised of an attribute name, and a schema defined by
+// a call to one of the 'attr' module methods enumerated at
// https://bazel.build/rules/lib/attr
message AttributeInfo {
// The name of the attribute.
@@ -95,26 +119,46 @@ message AttributeInfo {
// The target(s) in this attribute must define all the providers of at least
// one of the ProviderNameGroups in this list. If the Attribute Type is not a
// label, a label list, or a label-keyed string dictionary, the field will be
- // left empty.
+ // left empty. For attributes of a repository rule or a module extension tag,
+ // this attribute is meaningless and may be ignored.
+ // TODO(b/290788853): ensure this field is always empty for attributes of a
+ // repository rule or a module extension tag.
repeated ProviderNameGroup provider_name_group = 5;
// The string representation of the default value of this attribute.
string default_value = 6;
}
-// Representation of a set of providers that a rule attribute may be required to
-// have.
+// Representation of a set of providers.
message ProviderNameGroup {
- // The names of the providers that must be given by any dependency appearing
- // in this attribute. The name will be "Unknown Provider" if the name is
- // unidentifiable, for example, if the provider is part of a namespace.
- // TODO(kendalllane): Fix documentation of providers from namespaces.
+ // The names of the providers.
+ //
+ // This field is only intended for rendering human-readable output.
+ // Please use origin_key (a list of the same length and in the same order as
+ // this field) for cross-references and tooling.
+ //
+ // Note: legacy Stardoc (0.5.x and earlier) is unable to extract the name in
+ // some circumstances (for example, if the provider is nested in a struct),
+ // and in that case, the provider name will be "Unknown Provider".
repeated string provider_name = 1;
+
+ // A list of unambiguous references to providers, of the same length and in
+ // the same order as the provider_name list.
+ //
+ // For provider symbols, this means modules where and the names under which
+ // the providers were originally declared.
+ //
+ // For legacy struct providers, origin_key.file is unset.
+ //
+ // Note: legacy Stardoc (0.5.x and earlier) does not set this field.
+ repeated OriginKey origin_key = 2;
}
// Representation of Starlark function definition.
message StarlarkFunctionInfo {
- // The name of the function.
+ // The name under which the function is made accessible to a user of this
+ // module, including any structs it is nested in, for example
+ // "foo.frobnicate".
string function_name = 1;
// The parameters for the function.
@@ -129,6 +173,12 @@ message StarlarkFunctionInfo {
// The deprecation for the function.
FunctionDeprecationInfo deprecated = 5;
+
+ // The module where and the name under which the function was originally
+ // declared.
+ //
+ // Note: legacy Stardoc (0.5.x and earlier) does not set this field.
+ OriginKey origin_key = 6;
}
// Representation of a Starlark function parameter definition.
@@ -174,7 +224,8 @@ message ProviderFieldInfo {
// Representation of a Starlark provider definition.
message ProviderInfo {
- // The name of the provider.
+ // The name under which the provider is made accessible to a user of this
+ // module, including any structs it is nested in, for example "foo.FooInfo".
string provider_name = 1;
// The description of the provider.
@@ -182,11 +233,19 @@ message ProviderInfo {
// The fields of the provider.
repeated ProviderFieldInfo field_info = 3;
+
+ // The module where and the name under which the provider was originally
+ // declared.
+ //
+ // Note: legacy Stardoc (0.5.x and earlier) does not set this field.
+ OriginKey origin_key = 4;
}
// Representation of a Starlark aspect definition.
message AspectInfo {
- // The name of the aspect.
+ // The name under which the aspect is made accessible to a user of this
+ // module, including any structs it is nested in, for example
+ // "foo.foo_aspect".
string aspect_name = 1;
// The documentation string of the aspect.
@@ -197,4 +256,85 @@ message AspectInfo {
// The attributes of the aspect.
repeated AttributeInfo attribute = 4;
+
+ // The module where and the name under which the aspect was originally
+ // declared.
+ //
+ // Note: legacy Stardoc (0.5.x and earlier) does not set this field.
+ OriginKey origin_key = 5;
+}
+
+// Representation of a Bazel module extension, i.e. the object returned by
+// calling `module_extension(...)`.
+//
+// Note: legacy Stardoc (0.5.x and earlier) does not emit this message.
+message ModuleExtensionInfo {
+ // The name under which the extension is made accessible to a user of this
+ // Starlark module.
+ string extension_name = 1;
+
+ // The documentation string of the extension.
+ string doc_string = 2;
+
+ // The tag classes of the extension.
+ repeated ModuleExtensionTagClassInfo tag_class = 3;
+
+ // The Starlark module where the Bazel module extension was originally
+ // declared; origin_key.name is currently never set.
+ // TODO(arostovtsev): attempt to retrieve the name under which the module
+ // extension was originally declared if it was declared as a global.
+ OriginKey origin_key = 4;
+}
+
+// Representation of a Bazel module extension tag class.
+message ModuleExtensionTagClassInfo {
+ // The name of the tag for this tag class.
+ string tag_name = 1;
+
+ // The documentation string of the tag class.
+ string doc_string = 2;
+
+ // The tag class's attributes.
+ repeated AttributeInfo attribute = 3;
+}
+
+// Representation of a Bazel repository rule, i.e. the object returned by
+// calling `repository_rule(...)`.
+//
+// Note: legacy Stardoc (0.5.x and earlier) does not emit this message, instead
+// using RuleInfo.
+message RepositoryRuleInfo {
+ // The name under which the repository rule is made accessible to a user of
+ // this Starlark module.
+ string rule_name = 1;
+
+ // The documentation string of the repository rule.
+ string doc_string = 2;
+
+ // The attributes of the repository rule.
+ repeated AttributeInfo attribute = 3;
+
+ // Environment variables that this repository rule depends on.
+ repeated string environ = 4;
+
+ // The Starlark module where and the name under which the repository rule was
+ // originally declared.
+ OriginKey origin_key = 5;
+}
+
+// Representation of the origin of a rule, provider, aspect, or function.
+// Intended to be used for building unambiguous cross-references: for example,
+// between an element of a ProviderNameGroup required by a rule attribute and
+// its corresponding ProviderInfo.
+message OriginKey {
+ // The name under which the entity was originally exported. Unset when the
+ // entity was not exported in its module.
+ string name = 1;
+
+ // The display form of the label of the module file in which the entity was
+ // originally declared (as seen from the starlark_doc_extract or Stardoc
+ // target's repo), or "<native>" for Bazel's built-in entities implemented in
+ // Java. Unset when there is no module file (such as for legacy struct
+ // providers, when the module is a REPL, or in Bazel's internal tests).
+ string file = 2;
}
diff --git a/stardoc/renderer_binary.jar b/stardoc/renderer_binary.jar
deleted file mode 100755
index d822ecc..0000000
--- a/stardoc/renderer_binary.jar
+++ /dev/null
Binary files differ
diff --git a/stardoc/stardoc.bzl b/stardoc/stardoc.bzl
index f5693fc..6a3fbe7 100644
--- a/stardoc/stardoc.bzl
+++ b/stardoc/stardoc.bzl
@@ -14,184 +14,147 @@
"""Starlark rule for stardoc: a documentation generator tool written in Java."""
-load("@bazel_skylib//:bzl_library.bzl", "StarlarkLibraryInfo")
+load("@rules_java//java:defs.bzl", "java_binary")
+load("@bazel_skylib//rules:copy_file.bzl", "copy_file")
+load("//stardoc/private:stardoc.bzl", "stardoc_markdown_renderer", _stardoc = "stardoc")
-def _root_from_file(f):
- """Given a file, returns the root path of that file."""
- return f.root.path or "."
+def stardoc(
+ *,
+ name,
+ input,
+ out,
+ deps = [],
+ format = "markdown",
+ symbol_names = [],
+ semantic_flags = [],
+ stardoc = Label("//stardoc:prebuilt_stardoc_binary"),
+ renderer = Label("//stardoc:renderer"),
+ aspect_template = Label("//stardoc:templates/markdown_tables/aspect.vm"),
+ func_template = Label("//stardoc:templates/markdown_tables/func.vm"),
+ header_template = Label("//stardoc:templates/markdown_tables/header.vm"),
+ provider_template = Label("//stardoc:templates/markdown_tables/provider.vm"),
+ rule_template = Label("//stardoc:templates/markdown_tables/rule.vm"),
+ repository_rule_template = Label("//stardoc:templates/markdown_tables/repository_rule.vm"),
+ module_extension_template = Label("//stardoc:templates/markdown_tables/module_extension.vm"),
+ use_starlark_doc_extract = True,
+ render_main_repo_name = True,
+ **kwargs):
+ """Generates documentation for exported starlark rule definitions in a target starlark file.
-def _stardoc_impl(ctx):
- """Implementation of the stardoc rule."""
- for semantic_flag in ctx.attr.semantic_flags:
- if not semantic_flag.startswith("--"):
- fail("semantic_flags entry '%s' must start with '--'" % semantic_flag)
- out_file = ctx.outputs.out
- input_files = depset(direct = [ctx.file.input], transitive = [
- dep[StarlarkLibraryInfo].transitive_srcs
- for dep in ctx.attr.deps
- ])
- stardoc_args = ctx.actions.args()
- stardoc_args.add("--input=" + str(ctx.file.input.owner))
- stardoc_args.add("--workspace_name=" + ctx.workspace_name)
- stardoc_args.add_all(
- ctx.attr.symbol_names,
- format_each = "--symbols=%s",
- omit_if_empty = True,
- )
+ Args:
+ name: The name of the stardoc target.
+ input: The starlark file to generate documentation for (mandatory).
+ out: The file to which documentation will be output (mandatory).
+ deps: A list of bzl_library dependencies which the input depends on.
+ format: The format of the output file. Valid values: 'markdown' or 'proto'.
+ symbol_names: 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.
+ semantic_flags: A list of canonical flags to affect Starlark semantics for the Starlark interpreter during
+ documentation generation. This should only be used to maintain compatibility with non-default semantic flags
+ required to use the given Starlark symbols.
- # TODO(cparsons): Note that use of dep_roots alone does not guarantee
- # the correct file is loaded. If two files exist under the same path
- # but are under different roots, it is possible that Stardoc loads the
- # one that is not explicitly an input to this action (if sandboxing is
- # disabled). The correct way to resolve this is to explicitly specify
- # the full set of transitive dependency Starlark files as action args
- # (maybe using a param file), but this requires some work.
- stardoc_args.add_all(
- input_files,
- format_each = "--dep_roots=%s",
- map_each = _root_from_file,
- omit_if_empty = True,
- uniquify = True,
- )
+ For example, if `//foo:bar.bzl` does not build except when a user would specify
+ `--incompatible_foo_semantic=false`, then this attribute should contain
+ "--incompatible_foo_semantic=false".
+ stardoc: The location of the legacy Stardoc extractor. Ignored when using the native `starlark_doc_extract` rule.
+ renderer: The location of the renderer tool.
+ aspect_template: The input file template for generating documentation of aspects
+ header_template: The input file template for the header of the output documentation.
+ func_template: The input file template for generating documentation of functions.
+ provider_template: The input file template for generating documentation of providers.
+ rule_template: The input file template for generating documentation of rules.
+ repository_rule_template: The input file template for generating documentation of repository rules.
+ This template is used only when using the native `starlark_doc_extract` rule.
+ module_extension_template: The input file template for generating documentation of module extensions.
+ This template is used only when using the native `starlark_doc_extract` rule.
+ render_main_repo_name: Render labels in the main repository with a repo component (either
+ the module name or workspace name). This parameter is used only when using the native
+ `starlark_doc_extract` rule.
+ use_starlark_doc_extract: Use the native `starlark_doc_extract` rule if available.
+ **kwargs: Further arguments to pass to stardoc.
+ """
- # Needed in case some files are referenced across local repository
- # namespace. For example, consider a file under a nested local repository @bar
- # rooted under ./foo/bar/WORKSPACE. Consider a stardoc target 'lib_doc' under
- # foo/bar/BUILD to document foo/bar/lib.bzl.
- # The stardoc target references @bar//:lib.bzl (which appears just as :lib.bzl), but the
- # actual build is taking place in the root repository, thus the source file
- # is present under external/bar/lib.bzl.
- stardoc_args.add(
- "--dep_roots=external/" + ctx.workspace_name,
- )
- stardoc_args.add_all(ctx.attr.semantic_flags)
- stardoc = ctx.executable.stardoc
+ if format not in ["markdown", "proto"]:
+ fail("`format` must be \"markdown\" or \"proto\"")
- if ctx.attr.format == "proto":
- stardoc_args.add("--output=" + out_file.path)
- ctx.actions.run(
- outputs = [out_file],
- inputs = input_files,
- executable = stardoc,
- arguments = [stardoc_args],
- mnemonic = "Stardoc",
- progress_message = ("Generating Starlark doc for %s" %
- (ctx.label.name)),
- )
- elif ctx.attr.format == "markdown":
- proto_file = ctx.actions.declare_file(ctx.label.name + ".raw", sibling = out_file)
- stardoc_args.add("--output=" + proto_file.path)
- ctx.actions.run(
- outputs = [proto_file],
- inputs = input_files,
- executable = stardoc,
- arguments = [stardoc_args],
- mnemonic = "Stardoc",
- progress_message = ("Generating proto for Starlark doc for %s" %
- (ctx.label.name)),
- )
- renderer_args = ctx.actions.args()
- renderer_args.add("--input=" + str(proto_file.path))
- renderer_args.add("--output=" + str(ctx.outputs.out.path))
- renderer_args.add("--aspect_template=" + str(ctx.file.aspect_template.path))
- renderer_args.add("--header_template=" + str(ctx.file.header_template.path))
- renderer_args.add("--func_template=" + str(ctx.file.func_template.path))
- renderer_args.add("--provider_template=" + str(ctx.file.provider_template.path))
- renderer_args.add("--rule_template=" + str(ctx.file.rule_template.path))
- renderer = ctx.executable.renderer
- ctx.actions.run(
- outputs = [out_file],
- inputs = [proto_file, ctx.file.aspect_template, ctx.file.header_template, ctx.file.func_template, ctx.file.provider_template, ctx.file.rule_template],
- executable = renderer,
- arguments = [renderer_args],
- mnemonic = "Renderer",
- progress_message = ("Converting proto format of %s to markdown format" %
- (ctx.label.name)),
+ auxiliary_target_kwargs = {
+ "tags": ["manual"],
+ "visibility": ["//visibility:private"],
+ }
+ if "testonly" in kwargs:
+ auxiliary_target_kwargs["testonly"] = kwargs["testonly"]
+
+ if use_starlark_doc_extract and hasattr(native, "starlark_doc_extract"):
+ # Use native.starlark_doc_extract as extractor
+ if format == "proto" and Label(name + ".binaryproto") == Label(out):
+ extractor_is_main_target = True
+ extractor_name = name
+ else:
+ extractor_is_main_target = False
+ extractor_name = name + ".extract"
+
+ proto_name = extractor_name + ".binaryproto"
+
+ native.starlark_doc_extract(
+ name = extractor_name,
+ src = input,
+ deps = deps,
+ render_main_repo_name = render_main_repo_name,
+ symbol_names = symbol_names,
+ **(kwargs if extractor_is_main_target else auxiliary_target_kwargs)
)
-stardoc = rule(
- _stardoc_impl,
- doc = """
-Generates documentation for exported skylark rule definitions in a target starlark file.
+ if format == "markdown":
+ stardoc_markdown_renderer(
+ name = name,
+ src = proto_name,
+ out = out,
+ renderer = renderer,
+ aspect_template = aspect_template,
+ func_template = func_template,
+ header_template = header_template,
+ provider_template = provider_template,
+ rule_template = rule_template,
+ repository_rule_template = repository_rule_template,
+ module_extension_template = module_extension_template,
+ **kwargs
+ )
+ elif format == "proto" and not extractor_is_main_target:
+ copy_file(
+ name = name,
+ src = proto_name,
+ out = out,
+ **kwargs
+ )
+
+ else:
+ # Use legacy extractor
+ stardoc_with_runfiles_name = name + "_stardoc"
-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 bzl_library dependencies which the input depends on.",
- providers = [StarlarkLibraryInfo],
- ),
- "format": attr.string(
- doc = "The format of the output file. Valid values: 'markdown' or 'proto'.",
- default = "markdown",
- values = ["markdown", "proto"],
- ),
- "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 = [],
- ),
- "semantic_flags": attr.string_list(
- doc = """
-A list of canonical flags to affect Starlark semantics for the Starlark interpretter
-during documentation generation. This should only be used to maintain compatibility with
-non-default semantic flags required to use the given Starlark symbols.
+ java_binary(
+ name = stardoc_with_runfiles_name,
+ main_class = "com.google.devtools.build.skydoc.SkydocMain",
+ runtime_deps = [stardoc],
+ data = [input] + deps,
+ **auxiliary_target_kwargs
+ )
-For example, if `//foo:bar.bzl` does not build except when a user would specify
-`--incompatible_foo_semantic=false`, then this attribute should contain
-"--incompatible_foo_semantic=false".
-""",
- default = [],
- ),
- "stardoc": attr.label(
- doc = "The location of the stardoc tool.",
- allow_files = True,
- default = Label("//stardoc:stardoc"),
- cfg = "exec",
- executable = True,
- ),
- "renderer": attr.label(
- doc = "The location of the renderer tool.",
- allow_files = True,
- default = Label("//stardoc:renderer"),
- cfg = "exec",
- executable = True,
- ),
- "aspect_template": attr.label(
- doc = "The input file template for generating documentation of aspects.",
- allow_single_file = [".vm"],
- default = Label("//stardoc:templates/markdown_tables/aspect.vm"),
- ),
- "header_template": attr.label(
- doc = "The input file template for the header of the output documentation.",
- allow_single_file = [".vm"],
- default = Label("//stardoc:templates/markdown_tables/header.vm"),
- ),
- "func_template": attr.label(
- doc = "The input file template for generating documentation of functions.",
- allow_single_file = [".vm"],
- default = Label("//stardoc:templates/markdown_tables/func.vm"),
- ),
- "provider_template": attr.label(
- doc = "The input file template for generating documentation of providers.",
- allow_single_file = [".vm"],
- default = Label("//stardoc:templates/markdown_tables/provider.vm"),
- ),
- "rule_template": attr.label(
- doc = "The input file template for generating documentation of rules.",
- allow_single_file = [".vm"],
- default = Label("//stardoc:templates/markdown_tables/rule.vm"),
- ),
- },
-)
+ _stardoc(
+ name = name,
+ input = input,
+ out = out,
+ format = format,
+ symbol_names = symbol_names,
+ semantic_flags = semantic_flags,
+ stardoc = stardoc_with_runfiles_name,
+ renderer = renderer,
+ aspect_template = aspect_template,
+ func_template = func_template,
+ header_template = header_template,
+ provider_template = provider_template,
+ rule_template = rule_template,
+ repository_rule_template = repository_rule_template,
+ module_extension_template = module_extension_template,
+ **kwargs
+ )
diff --git a/stardoc/stardoc_binary.jar b/stardoc/stardoc_binary.jar
index 47b6874..91eb294 100755
--- a/stardoc/stardoc_binary.jar
+++ b/stardoc/stardoc_binary.jar
Binary files differ
diff --git a/stardoc/templates/html_tables/module_extension.vm b/stardoc/templates/html_tables/module_extension.vm
new file mode 100644
index 0000000..1cbc32e
--- /dev/null
+++ b/stardoc/templates/html_tables/module_extension.vm
@@ -0,0 +1,56 @@
+<a id="${extensionName}"></a>
+
+#[[##]]# ${extensionName}
+
+<pre>
+${util.moduleExtensionSummary($extensionName, $extensionInfo)}
+</pre>
+#if (!$extensionInfo.docString.isEmpty())
+
+${extensionInfo.docString}
+#end
+
+#if (!$extensionInfo.getTagClassList().isEmpty())
+
+**TAG CLASSES**
+#foreach ($tagClass in $extensionInfo.getTagClassList())
+
+<a id="${extensionName}.${tagClass.tagName}"></a>
+
+#[[###]]# ${tagClass.tagName}
+#if (!$tagClass.docString.isEmpty())
+
+${tagClass.docString}
+#end
+
+**Attributes**
+
+#if (!$tagClass.getAttributeList().isEmpty())
+<table class="params-table">
+<colgroup>
+<col class="col-param" />
+<col class="col-description" />
+</colgroup>
+<tbody>
+#foreach ($attribute in $tagClass.getAttributeList())
+<tr id="${extensionName}.${tagClass.tagName}-${attribute.name}">
+<td><code>${attribute.name}</code></td>
+<td>
+
+${util.attributeTypeString($attribute)}; ${util.mandatoryString($attribute)}
+
+#if (!$attribute.docString.isEmpty())
+<p>
+
+${attribute.docString.trim()}
+
+</p>
+#end
+</td>
+</tr>
+#end
+</tbody>
+</table>
+#end
+#end
+#end
diff --git a/stardoc/templates/html_tables/repository_rule.vm b/stardoc/templates/html_tables/repository_rule.vm
new file mode 100644
index 0000000..6594130
--- /dev/null
+++ b/stardoc/templates/html_tables/repository_rule.vm
@@ -0,0 +1,50 @@
+<a id="${ruleName}"></a>
+
+#[[##]]# ${ruleName}
+
+<pre>
+${util.repositoryRuleSummary($ruleName, $ruleInfo)}
+</pre>
+#if (!$ruleInfo.docString.isEmpty())
+
+${ruleInfo.docString}
+#end
+
+**ATTRIBUTES**
+
+#if (!$ruleInfo.getAttributeList().isEmpty())
+<table class="params-table">
+<colgroup>
+<col class="col-param" />
+<col class="col-description" />
+</colgroup>
+<tbody>
+#foreach ($attribute in $ruleInfo.getAttributeList())
+<tr id="${ruleName}-${attribute.name}">
+<td><code>${attribute.name}</code></td>
+<td>
+
+${util.attributeTypeString($attribute)}; ${util.mandatoryString($attribute)}
+
+#if (!$attribute.docString.isEmpty())
+<p>
+
+${attribute.docString.trim()}
+
+</p>
+#end
+</td>
+</tr>
+#end
+</tbody>
+</table>
+#end
+#if (!$ruleInfo.getEnvironList().isEmpty())
+
+**ENVIRONMENT VARIABLES**
+
+This repository rule depends on the following environment variables:
+#foreach ($var in $ruleInfo.getEnvironList())
+* ${util.markdownCodeSpan($var)}
+#end
+#end
diff --git a/stardoc/templates/markdown_tables/aspect.vm b/stardoc/templates/markdown_tables/aspect.vm
index aa9f13b..36aa47a 100644
--- a/stardoc/templates/markdown_tables/aspect.vm
+++ b/stardoc/templates/markdown_tables/aspect.vm
@@ -6,7 +6,7 @@
${util.aspectSummary($aspectName, $aspectInfo)}
</pre>
-${util.htmlEscape($aspectInfo.getDocString())}
+$aspectInfo.getDocString()
**ASPECT ATTRIBUTES**
@@ -27,6 +27,6 @@ ${util.htmlEscape($aspectInfo.getDocString())}
| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
#foreach ($attribute in $aspectInfo.getAttributeList())
-| <a id="${aspectName}-${attribute.name}"></a>$attribute.name | #if(!$attribute.docString.isEmpty()) ${util.markdownCellFormat($attribute.docString)} #else - #end | ${util.attributeTypeString($attribute)} | ${util.mandatoryString($attribute)} | #if(!$attribute.defaultValue.isEmpty()) <code>${util.htmlEscape($attribute.defaultValue)}</code> #end |
+| <a id="${aspectName}-${attribute.name}"></a>$attribute.name | #if(!$attribute.docString.isEmpty()) ${util.markdownCellFormat($attribute.docString)} #else - #end | ${util.attributeTypeString($attribute)} | ${util.mandatoryString($attribute)} | #if(!$attribute.defaultValue.isEmpty()) ${util.markdownCodeSpan($attribute.defaultValue)} #end |
#end
#end
diff --git a/stardoc/templates/markdown_tables/func.vm b/stardoc/templates/markdown_tables/func.vm
index 5275d08..e53b81a 100644
--- a/stardoc/templates/markdown_tables/func.vm
+++ b/stardoc/templates/markdown_tables/func.vm
@@ -6,7 +6,7 @@
${util.funcSummary($funcInfo)}
</pre>
-${util.htmlEscape($funcInfo.docString)}
+${funcInfo.docString}
#if (!$funcInfo.getParameterList().isEmpty())
**PARAMETERS**
@@ -15,18 +15,18 @@ ${util.htmlEscape($funcInfo.docString)}
| Name | Description | Default Value |
| :------------- | :------------- | :------------- |
#foreach ($param in $funcInfo.getParameterList())
-| <a id="${funcInfo.functionName}-${param.name}"></a>$param.name | #if(!$param.docString.isEmpty()) ${util.markdownCellFormat($param.docString)} #else <p align="center"> - </p> #end | #if(!$param.getDefaultValue().isEmpty()) <code>${util.htmlEscape($param.getDefaultValue())}</code> #else none #end|
+| <a id="${funcInfo.functionName}-${param.name}"></a>$param.name | #if(!$param.docString.isEmpty()) ${util.markdownCellFormat($param.docString)} #else <p align="center"> - </p> #end | #if(!$param.getDefaultValue().isEmpty()) ${util.markdownCodeSpan($param.defaultValue)} #else none #end|
#end
#end
#if (!$funcInfo.getReturn().docString.isEmpty())
**RETURNS**
-${util.htmlEscape($funcInfo.getReturn().docString)}
+${funcInfo.getReturn().docString}
#end
#if (!$funcInfo.getDeprecated().docString.isEmpty())
**DEPRECATED**
-${util.htmlEscape($funcInfo.getDeprecated().docString)}
+${funcInfo.getDeprecated().docString}
#end
diff --git a/stardoc/templates/markdown_tables/header.vm b/stardoc/templates/markdown_tables/header.vm
index 2b47292..5556ad6 100644
--- a/stardoc/templates/markdown_tables/header.vm
+++ b/stardoc/templates/markdown_tables/header.vm
@@ -1,3 +1,3 @@
<!-- Generated with Stardoc: http://skydoc.bazel.build -->
-${util.htmlEscape($moduleDocstring)}
+${moduleDocstring}
diff --git a/stardoc/templates/markdown_tables/module_extension.vm b/stardoc/templates/markdown_tables/module_extension.vm
new file mode 100644
index 0000000..0ef7367
--- /dev/null
+++ b/stardoc/templates/markdown_tables/module_extension.vm
@@ -0,0 +1,34 @@
+<a id="${extensionName}"></a>
+
+#[[##]]# ${extensionName}
+
+<pre>
+${util.moduleExtensionSummary($extensionName, $extensionInfo)}
+</pre>
+#if (!$extensionInfo.docString.isEmpty())
+
+${extensionInfo.docString}
+#end
+
+#if (!$extensionInfo.getTagClassList().isEmpty())
+
+**TAG CLASSES**
+#foreach ($tagClass in $extensionInfo.getTagClassList())
+
+<a id="${extensionName}.${tagClass.tagName}"></a>
+
+#[[###]]# ${tagClass.tagName}
+#if (!$tagClass.docString.isEmpty())
+
+${tagClass.docString}
+#end
+
+**Attributes**
+
+| Name | Description | Type | Mandatory | Default |
+| :------------- | :------------- | :------------- | :------------- | :------------- |
+#foreach ($attribute in $tagClass.getAttributeList())
+| <a id="${extensionName}.${tagClass.tagName}-${attribute.name}"></a>$attribute.name | #if(!$attribute.docString.isEmpty()) ${util.markdownCellFormat($attribute.docString)} #else - #end | ${util.attributeTypeString($attribute)} | ${util.mandatoryString($attribute)} | #if(!$attribute.defaultValue.isEmpty()) ${util.markdownCodeSpan($attribute.defaultValue)} #end |
+#end
+#end
+#end
diff --git a/stardoc/templates/markdown_tables/provider.vm b/stardoc/templates/markdown_tables/provider.vm
index 7ab4c60..0a866db 100644
--- a/stardoc/templates/markdown_tables/provider.vm
+++ b/stardoc/templates/markdown_tables/provider.vm
@@ -6,7 +6,7 @@
${util.providerSummary($providerName, $providerInfo)}
</pre>
-${util.htmlEscape($providerInfo.docString)}
+${providerInfo.docString}
**FIELDS**
diff --git a/stardoc/templates/markdown_tables/repository_rule.vm b/stardoc/templates/markdown_tables/repository_rule.vm
new file mode 100644
index 0000000..ed4a2a9
--- /dev/null
+++ b/stardoc/templates/markdown_tables/repository_rule.vm
@@ -0,0 +1,31 @@
+<a id="${ruleName}"></a>
+
+#[[##]]# ${ruleName}
+
+<pre>
+${util.repositoryRuleSummary($ruleName, $ruleInfo)}
+</pre>
+#if (!$ruleInfo.docString.isEmpty())
+
+${ruleInfo.docString}
+#end
+
+**ATTRIBUTES**
+
+#if (!$ruleInfo.getAttributeList().isEmpty())
+
+| Name | Description | Type | Mandatory | Default |
+| :------------- | :------------- | :------------- | :------------- | :------------- |
+#foreach ($attribute in $ruleInfo.getAttributeList())
+| <a id="${ruleName}-${attribute.name}"></a>$attribute.name | #if(!$attribute.docString.isEmpty()) ${util.markdownCellFormat($attribute.docString)} #else - #end | ${util.attributeTypeString($attribute)} | ${util.mandatoryString($attribute)} | #if(!$attribute.defaultValue.isEmpty()) ${util.markdownCodeSpan($attribute.defaultValue)} #end |
+#end
+#end
+#if (!$ruleInfo.getEnvironList().isEmpty())
+
+**ENVIRONMENT VARIABLES**
+
+This repository rule depends on the following environment variables:
+#foreach ($var in $ruleInfo.getEnvironList())
+* ${util.markdownCodeSpan($var)}
+#end
+#end
diff --git a/stardoc/templates/markdown_tables/rule.vm b/stardoc/templates/markdown_tables/rule.vm
index 06d9a1f..0b73239 100644
--- a/stardoc/templates/markdown_tables/rule.vm
+++ b/stardoc/templates/markdown_tables/rule.vm
@@ -6,7 +6,7 @@
${util.ruleSummary($ruleName, $ruleInfo)}
</pre>
-${util.htmlEscape($ruleInfo.docString)}
+${ruleInfo.docString}
**ATTRIBUTES**
@@ -15,6 +15,6 @@ ${util.htmlEscape($ruleInfo.docString)}
| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
#foreach ($attribute in $ruleInfo.getAttributeList())
-| <a id="${ruleName}-${attribute.name}"></a>$attribute.name | #if(!$attribute.docString.isEmpty()) ${util.markdownCellFormat($attribute.docString)} #else - #end | ${util.attributeTypeString($attribute)} | ${util.mandatoryString($attribute)} | #if(!$attribute.defaultValue.isEmpty())<code>${util.htmlEscape($attribute.defaultValue)}</code>#end |
+| <a id="${ruleName}-${attribute.name}"></a>$attribute.name | #if(!$attribute.docString.isEmpty()) ${util.markdownCellFormat($attribute.docString)} #else - #end | ${util.attributeTypeString($attribute)} | ${util.mandatoryString($attribute)} | #if(!$attribute.defaultValue.isEmpty()) ${util.markdownCodeSpan($attribute.defaultValue)} #end |
#end
#end
diff --git a/test/BUILD b/test/BUILD
index c97b5a4..c4f59e3 100644
--- a/test/BUILD
+++ b/test/BUILD
@@ -1,18 +1,15 @@
-load(":stardoc_test.bzl", "stardoc_test")
+load(":stardoc_test.bzl", "self_gen_test", "stardoc_test")
+load("@bazel_skylib//rules:diff_test.bzl", "diff_test")
+
+package(default_applicable_licenses = ["//:license"])
licenses(["notice"]) # Apache 2.0
-sh_test(
+self_gen_test(
name = "stardoc_self_gen_test",
- srcs = ["diff_test_runner.sh"],
- args = [
- "$(location //stardoc:stardoc_doc.md)",
- "$(location //:stardoc_rule_doc)",
- ],
- data = [
- "//:stardoc_rule_doc",
- "//stardoc:stardoc_doc.md",
- ],
+ golden_file = "//stardoc:stardoc_doc.md",
+ require_starlark_doc_extract = True,
+ stardoc_doc = "//:stardoc_rule_doc",
)
exports_files(["testdata/fakedeps/dep.bzl"])
@@ -32,13 +29,15 @@ stardoc_test(
name = "angle_bracket_test",
golden_file = "testdata/angle_bracket_test/golden.md",
input_file = "testdata/angle_bracket_test/input.bzl",
+ legacy_golden_file = "testdata/angle_bracket_test/legacy_golden.md",
)
stardoc_test(
name = "proto_format_test",
format = "proto",
- golden_file = "testdata/proto_format_test/golden.raw",
+ golden_file = "testdata/proto_format_test/golden.binaryproto",
input_file = "testdata/proto_format_test/input.bzl",
+ legacy_golden_file = "testdata/proto_format_test/legacy_golden.binaryproto",
)
stardoc_test(
@@ -58,6 +57,14 @@ stardoc_test(
name = "repo_rules_test",
golden_file = "testdata/repo_rules_test/golden.md",
input_file = "testdata/repo_rules_test/input.bzl",
+ legacy_golden_file = "testdata/repo_rules_test/legacy_golden.md",
+)
+
+stardoc_test(
+ name = "module_extension_test",
+ golden_file = "testdata/module_extension_test/golden.md",
+ input_file = "testdata/module_extension_test/input.bzl",
+ test_legacy_extractor = False,
)
stardoc_test(
@@ -127,12 +134,14 @@ stardoc_test(
name = "misc_apis_test",
golden_file = "testdata/misc_apis_test/golden.md",
input_file = "testdata/misc_apis_test/input.bzl",
+ legacy_golden_file = "testdata/misc_apis_test/legacy_golden.md",
)
stardoc_test(
name = "attribute_types_test",
golden_file = "testdata/attribute_types_test/golden.md",
input_file = "testdata/attribute_types_test/input.bzl",
+ legacy_golden_file = "testdata/attribute_types_test/legacy_golden.md",
symbol_names = ["my_rule"],
)
@@ -142,7 +151,7 @@ stardoc_test(
input_file = "testdata/filter_rules_test/input.bzl",
symbol_names = [
"my_rule",
- "whitelisted_dep_rule",
+ "allowlisted_dep_rule",
],
deps = [
"testdata/filter_rules_test/dep.bzl",
@@ -153,6 +162,7 @@ stardoc_test(
name = "provider_basic_test",
golden_file = "testdata/provider_basic_test/golden.md",
input_file = "testdata/provider_basic_test/input.bzl",
+ legacy_golden_file = "testdata/provider_basic_test/legacy_golden.md",
)
stardoc_test(
@@ -162,13 +172,20 @@ stardoc_test(
)
stardoc_test(
+ name = "function_wrap_multiple_lines_test",
+ golden_file = "testdata/function_wrap_multiple_lines_test/golden.md",
+ input_file = "testdata/function_wrap_multiple_lines_test/input.bzl",
+ legacy_golden_file = "testdata/function_wrap_multiple_lines_test/legacy_golden.md",
+)
+
+stardoc_test(
name = "namespace_test",
golden_file = "testdata/namespace_test/golden.md",
input_file = "testdata/namespace_test/input.bzl",
)
stardoc_test(
- name = "namespace_test_with_whitelist",
+ name = "namespace_test_with_allowlist",
golden_file = "testdata/namespace_test/golden.md",
input_file = "testdata/namespace_test/input.bzl",
symbol_names = [
@@ -183,9 +200,9 @@ stardoc_test(
)
stardoc_test(
- name = "multi_level_namespace_test_with_whitelist",
- golden_file = "testdata/multi_level_namespace_test_with_whitelist/golden.md",
- input_file = "testdata/multi_level_namespace_test_with_whitelist/input.bzl",
+ name = "multi_level_namespace_test_with_allowlist",
+ golden_file = "testdata/multi_level_namespace_test_with_allowlist/golden.md",
+ input_file = "testdata/multi_level_namespace_test_with_allowlist/input.bzl",
symbol_names = [
"my_namespace",
"other_namespace.foo.nothing",
@@ -199,6 +216,12 @@ stardoc_test(
)
stardoc_test(
+ name = "pure_markdown_template_test",
+ golden_file = "testdata/pure_markdown_template_test/golden.md",
+ input_file = "testdata/pure_markdown_template_test/input.bzl",
+)
+
+stardoc_test(
name = "py_rule_test",
golden_file = "testdata/py_rule_test/golden.md",
input_file = "testdata/py_rule_test/input.bzl",
@@ -215,6 +238,7 @@ stardoc_test(
name = "aspect_test",
golden_file = "testdata/aspect_test/golden.md",
input_file = "testdata/aspect_test/input.bzl",
+ legacy_golden_file = "testdata/aspect_test/legacy_golden.md",
)
stardoc_test(
@@ -237,6 +261,7 @@ stardoc_test(
name = "attribute_defaults_test",
golden_file = "testdata/attribute_defaults_test/golden.md",
input_file = "testdata/attribute_defaults_test/input.bzl",
+ legacy_golden_file = "testdata/attribute_defaults_test/legacy_golden.md",
)
stardoc_test(
@@ -245,22 +270,6 @@ stardoc_test(
input_file = "testdata/config_apis_test/input.bzl",
)
-genrule(
- name = "generate_bzl_test_dep",
- srcs = ["testdata/generated_bzl_test/dep.bzl.tpl"],
- outs = ["testdata/generated_bzl_test/dep.bzl"],
- cmd = "cp $< $@",
-)
-
-stardoc_test(
- name = "generated_bzl_test",
- golden_file = "testdata/generated_bzl_test/golden.md",
- input_file = "testdata/generated_bzl_test/input.bzl",
- deps = [
- "testdata/generated_bzl_test/dep.bzl",
- ],
-)
-
sh_test(
name = "local_repository_test_e2e_test",
srcs = ["diff_test_runner.sh"],
@@ -273,3 +282,51 @@ sh_test(
"@local_repository_test//:output.md",
],
)
+
+# Consistency tests for WORKSPACE-related .bzl files vs. MODULE.bazel
+
+genrule(
+ name = "stardoc_maven_artifacts_in_deps_bzl",
+ srcs = ["//:deps.bzl"],
+ outs = ["stardoc_maven_artifacts_in_deps_bzl.txt"],
+ # Remove all lines except those from 'STARDOC_MAVEN_ARTIFACTS = [' to next ']'
+ cmd = "sed -e '/STARDOC_MAVEN_ARTIFACTS = \\[/,/\\]/!d' $< >$@",
+)
+
+genrule(
+ name = "stardoc_maven_artifacts_in_module_bazel",
+ srcs = ["//:MODULE.bazel"],
+ outs = ["stardoc_maven_artifacts_in_module_bazel.txt"],
+ # Remove all lines except those from 'STARDOC_MAVEN_ARTIFACTS = [' to next ']'
+ cmd = "sed -e '/STARDOC_MAVEN_ARTIFACTS = \\[/,/\\]/!d' $< >$@",
+)
+
+diff_test(
+ name = "stardoc_maven_artifacts_consistency_test",
+ failure_message = "STARDOC_MAVEN_ARTIFACTS in deps.bzl and MODULE.bazel are inconsistent",
+ file1 = "stardoc_maven_artifacts_in_deps_bzl",
+ file2 = "stardoc_maven_artifacts_in_module_bazel",
+)
+
+genrule(
+ name = "stardoc_version_in_version_bzl",
+ srcs = ["//:version.bzl"],
+ outs = ["stardoc_version_in_version_bzl.txt"],
+ # Find first line starting containing 'version = ' and extract the string value
+ cmd = "grep -m 1 'version = ' $< | sed -e 's/.*version = \\(\".*\"\\).*/\\1/' >$@",
+)
+
+genrule(
+ name = "stardoc_version_in_module_bazel",
+ srcs = ["//:MODULE.bazel"],
+ outs = ["stardoc_version_in_module_bazel.txt"],
+ # Find first line starting containing 'version = ' and extract the string value
+ cmd = "grep -m 1 'version = ' $< | sed -e 's/.*version = \\(\".*\"\\).*/\\1/' >$@",
+)
+
+diff_test(
+ name = "stardoc_version_consistency_test",
+ failure_message = "version in version.bzl and MODULE.bazel is inconsistent",
+ file1 = "stardoc_version_in_version_bzl",
+ file2 = "stardoc_version_in_module_bazel",
+)
diff --git a/test/bzlmod/.bazelrc b/test/bzlmod/.bazelrc
new file mode 100644
index 0000000..3ce91d2
--- /dev/null
+++ b/test/bzlmod/.bazelrc
@@ -0,0 +1 @@
+common --enable_bzlmod
diff --git a/test/bzlmod/BUILD b/test/bzlmod/BUILD
new file mode 100644
index 0000000..91fd15a
--- /dev/null
+++ b/test/bzlmod/BUILD
@@ -0,0 +1,23 @@
+load("@my_skylib//rules:diff_test.bzl", "diff_test")
+load("@stardoc//stardoc:stardoc.bzl", "stardoc")
+load(":def.bzl", "write_host_constraints")
+
+write_host_constraints(
+ name = "host_constraints",
+)
+
+stardoc(
+ name = "docs",
+ out = "docs.md",
+ input = "def.bzl",
+ deps = [
+ "@local_config_platform//:constraints.bzl",
+ "@my_skylib//rules:write_file",
+ ],
+)
+
+diff_test(
+ name = "docs_test",
+ file1 = "docs.md",
+ file2 = "docs.md.golden",
+)
diff --git a/test/bzlmod/MODULE.bazel b/test/bzlmod/MODULE.bazel
new file mode 100644
index 0000000..2c6b694
--- /dev/null
+++ b/test/bzlmod/MODULE.bazel
@@ -0,0 +1,11 @@
+bazel_dep(name = "stardoc", version = "")
+local_path_override(
+ module_name = "stardoc",
+ path = "../..",
+)
+
+bazel_dep(
+ name = "bazel_skylib",
+ version = "1.4.0",
+ repo_name = "my_skylib",
+)
diff --git a/test/bzlmod/WORKSPACE b/test/bzlmod/WORKSPACE
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/bzlmod/WORKSPACE
diff --git a/test/bzlmod/WORKSPACE.bzlmod b/test/bzlmod/WORKSPACE.bzlmod
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/bzlmod/WORKSPACE.bzlmod
diff --git a/test/bzlmod/def.bzl b/test/bzlmod/def.bzl
new file mode 100644
index 0000000..8970cca
--- /dev/null
+++ b/test/bzlmod/def.bzl
@@ -0,0 +1,31 @@
+# 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.
+
+"""A simple macro used to test stardoc."""
+
+load("@my_skylib//rules:write_file.bzl", "write_file")
+load("@local_config_platform//:constraints.bzl", "HOST_CONSTRAINTS")
+
+def write_host_constraints(name):
+ """Emits the constraints of the host platform to a file.
+
+ Args:
+ name: The name of the target. The output file will be named
+ `<name>.txt`.
+ """
+ write_file(
+ name = name,
+ content = HOST_CONSTRAINTS,
+ out = name + ".txt",
+ )
diff --git a/test/bzlmod/docs.md.golden b/test/bzlmod/docs.md.golden
new file mode 100644
index 0000000..3b671cc
--- /dev/null
+++ b/test/bzlmod/docs.md.golden
@@ -0,0 +1,22 @@
+<!-- Generated with Stardoc: http://skydoc.bazel.build -->
+
+A simple macro used to test stardoc.
+
+<a id="write_host_constraints"></a>
+
+## write_host_constraints
+
+<pre>
+write_host_constraints(<a href="#write_host_constraints-name">name</a>)
+</pre>
+
+Emits the constraints of the host platform to a file.
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="write_host_constraints-name"></a>name | The name of the target. The output file will be named `<name>.txt`. | none |
+
+
diff --git a/test/stardoc_test.bzl b/test/stardoc_test.bzl
index 8a18b52..d782643 100644
--- a/test/stardoc_test.bzl
+++ b/test/stardoc_test.bzl
@@ -21,21 +21,27 @@ def stardoc_test(
name,
input_file,
golden_file,
+ legacy_golden_file = None,
+ test_legacy_extractor = True,
deps = [],
test = "default",
**kwargs):
"""Convenience macro for stardoc e2e test suites.
- Each invocation creates four targets:
+ Each invocation creates multiple targets:
1. A sh_test target which verifies that stardoc-built-from-source, when run on an input file,
- creates output matching the contents of a golden file, named "{name}_e2e_test".
- 2. A `stardoc` target which will generate a new golden file given an input file
- with stardoc-built-from-source. This target should be used to regenerate
- the golden file when updating stardoc, named "regenerate_{name}_golden".
+ creates output matching the contents of a golden file, named "{name}_e2e_legacy_test".
+ 2. A `stardoc` target which will generate a new golden file given an input file with the
+ legacy extractor built from Bazel source. This target should be used to regenerate the
+ legacy golden file when updating stardoc, named "regenerate_{name}_legacy_golden".
3 & 4. Targets identical to (1) and (2) except they use the prebuilt-stardoc jar, and
- are named "{name}_e2e_jar_test" and "regenerate_with_jar_{name}_golden".
- 5. A bzl_library target for convenient wrapping of input bzl files, named "{name}_lib".
+ are named "{name}_e2e_jar_legacy_test" and "regenerate_with_jar_{name}_legacy_golden".
+ 5 & 6. Only if the host Bazel supports the `native.starlark_doc_extract` rule: Targets
+ identical to (1) and (2) except they use starlark_doc_extract, and are named "{name}_e2e_test"
+ and "regenerate_{name}_golden". The latter target should be used to regenerate the golden
+ file when updating Stardoc.
+ 7. A bzl_library target for convenient wrapping of input bzl files, named "{name}_lib".
Args:
name: A unique name to qualify the created targets.
@@ -43,38 +49,60 @@ def stardoc_test(
in this test.
golden_file: The label string of the golden file containing the documentation when stardoc
is run on the input file.
+ legacy_golden_file: The label string of the golden file when using the legacy documentation
+ extractor. If `legacy_golden_file` is not set, `golden_file` will be used for both extractors.
+ test_legacy_extractor: Whether to create legacy extractor test targets.
deps: A list of label strings of starlark file dependencies of the input_file.
test: The type of test (default or html_tables).
**kwargs: A dictionary of input template names mapped to template file path for which documentation is generated.
"""
+ if legacy_golden_file == None:
+ legacy_golden_file = golden_file
+
bzl_library(
name = "%s_lib" % name,
srcs = [input_file],
deps = deps,
)
- _create_test_targets(
- test_name = "%s_e2e_test" % name,
- genrule_name = "regenerate_%s_golden" % name,
- lib_name = "%s_lib" % name,
- input_file = input_file,
- golden_file = golden_file,
- stardoc_bin = "@io_bazel//src/main/java/com/google/devtools/build/skydoc",
- renderer_bin = "@io_bazel//src/main/java/com/google/devtools/build/skydoc/renderer",
- test = test,
- **kwargs
- )
- _create_test_targets(
- test_name = "%s_e2e_jar_test" % name,
- genrule_name = "regenerate_with_jar_%s_golden" % name,
- lib_name = "%s_lib" % name,
- input_file = input_file,
- golden_file = golden_file,
- stardoc_bin = "@io_bazel//src/main/java/com/google/devtools/build/skydoc",
- renderer_bin = "@io_bazel//src/main/java/com/google/devtools/build/skydoc/renderer",
- test = test,
- **kwargs
- )
+
+ if test_legacy_extractor:
+ _create_test_targets(
+ test_name = "%s_e2e_legacy_test" % name,
+ genrule_name = "regenerate_%s_legacy_golden" % name,
+ lib_name = "%s_lib" % name,
+ input_file = input_file,
+ golden_file = legacy_golden_file,
+ stardoc_bin = "@io_bazel//src/main/java/com/google/devtools/build/skydoc:skydoc_deploy.jar",
+ test = test,
+ use_starlark_doc_extract = False,
+ **kwargs
+ )
+
+ _create_test_targets(
+ test_name = "%s_e2e_jar_legacy_test" % name,
+ genrule_name = "regenerate_with_jar_%s_legacy_golden" % name,
+ lib_name = "%s_lib" % name,
+ input_file = input_file,
+ golden_file = legacy_golden_file,
+ stardoc_bin = "@io_bazel//src/main/java/com/google/devtools/build/skydoc:skydoc_deploy.jar",
+ test = test,
+ use_starlark_doc_extract = False,
+ **kwargs
+ )
+
+ if hasattr(native, "starlark_doc_extract"):
+ _create_test_targets(
+ test_name = "%s_e2e_test" % name,
+ genrule_name = "regenerate_%s_golden" % name,
+ lib_name = "%s_lib" % name,
+ input_file = input_file,
+ golden_file = golden_file,
+ stardoc_bin = None,
+ test = test,
+ use_starlark_doc_extract = True,
+ **kwargs
+ )
def _create_test_targets(
test_name,
@@ -83,7 +111,6 @@ def _create_test_targets(
input_file,
golden_file,
stardoc_bin,
- renderer_bin,
test,
**kwargs):
actual_generated_doc = "%s.out" % genrule_name
@@ -107,7 +134,6 @@ def _create_test_targets(
out = actual_generated_doc,
input = input_file,
deps = [lib_name],
- renderer = renderer_bin,
stardoc = stardoc_bin,
**kwargs
)
@@ -117,9 +143,42 @@ def _create_test_targets(
out = actual_generated_doc,
input = input_file,
deps = [lib_name],
- renderer = renderer_bin,
stardoc = stardoc_bin,
**kwargs
)
else:
fail("parameter 'test' must either be 'default' or 'html_tables', but was " + test)
+
+def self_gen_test(
+ name,
+ stardoc_doc,
+ golden_file,
+ require_starlark_doc_extract,
+ **kwargs):
+ """
+ A wrapper around `diff_test_runner.sh` for testing Stardoc's own generated documentation.
+
+ Args:
+ name: A unique name for the test target.
+ stardoc_doc: The Stardoc output being tested.
+ golden_file: Expected Stardoc output.
+ require_starlark_doc_extract: If true, and the native `starlark_doc_extract` rule is not available,
+ then no test target will not be created.
+ **kwargs: Additional arguments for the test.
+ """
+ if require_starlark_doc_extract and not hasattr(native, "starlark_doc_extract"):
+ return
+
+ native.sh_test(
+ name = name,
+ srcs = ["diff_test_runner.sh"],
+ args = [
+ "$(location %s)" % golden_file,
+ "$(location %s)" % stardoc_doc,
+ ],
+ data = [
+ golden_file,
+ stardoc_doc,
+ ],
+ **kwargs
+ )
diff --git a/test/testdata/android_basic_test/golden.md b/test/testdata/android_basic_test/golden.md
index 0962201..b22186d 100755..100644
--- a/test/testdata/android_basic_test/golden.md
+++ b/test/testdata/android_basic_test/golden.md
@@ -19,7 +19,7 @@ This rule does android-related things.
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="android_related_rule-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
| <a id="android_related_rule-first"></a>first | - | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
-| <a id="android_related_rule-fourth"></a>fourth | - | Boolean | optional | <code>False</code> |
+| <a id="android_related_rule-fourth"></a>fourth | - | Boolean | optional | `False` |
| <a id="android_related_rule-second"></a>second | - | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | required | |
| <a id="android_related_rule-third"></a>third | - | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
diff --git a/test/testdata/android_basic_test/input.bzl b/test/testdata/android_basic_test/input.bzl
index 970b674..0462c98 100644
--- a/test/testdata/android_basic_test/input.bzl
+++ b/test/testdata/android_basic_test/input.bzl
@@ -2,14 +2,7 @@
# buildifier: disable=function-docstring
# buildifier: disable=unused-variable
def exercise_the_api():
- _var1 = android_common.create_device_broker_info("")
- _var2 = ApkInfo
- _var3 = AndroidInstrumentationInfo
- _var4 = AndroidDeviceBrokerInfo
- _var5 = AndroidResourcesInfo
- _var6 = AndroidNativeLibsInfo
- _var7 = AndroidSdkInfo
- _var8 = android_data
+ _ignore = android_common.create_device_broker_info("")
exercise_the_api()
diff --git a/test/testdata/angle_bracket_test/golden.md b/test/testdata/angle_bracket_test/golden.md
index 1c31dd2..06496b2 100755..100644
--- a/test/testdata/angle_bracket_test/golden.md
+++ b/test/testdata/angle_bracket_test/golden.md
@@ -1,19 +1,26 @@
<!-- Generated with Stardoc: http://skydoc.bazel.build -->
-Input file to test &lt;angle bracket bugs&gt;
+Input file to test angle bracket bug (https://github.com/bazelbuild/skydoc/issues/186)
-See https://github.com/bazelbuild/skydoc/issues/186
-and https://github.com/bazelbuild/stardoc/issues/132
+See https://github.com/bazelbuild/skydoc/issues/186,
+https://github.com/bazelbuild/stardoc/issues/132,
+and https://github.com/bazelbuild/stardoc/issues/137.
+
+<b>HTML formatting</b> can be used in docstrings, just as in regular Markdown.
+Literal angle brackets can be obtained by escaping them with a backslash, where
+the backslash itself must be escaped for use in a Starlark docstring
+(`\\<` becomes \<), or by using HTML entities (`&lt;` becomes &lt;).
+Angle brackets are also preserved in inline code blocks (`#include <vector>`).
<a id="my_anglebrac"></a>
## my_anglebrac
<pre>
-my_anglebrac(<a href="#my_anglebrac-name">name</a>, <a href="#my_anglebrac-useless">useless</a>)
+my_anglebrac(<a href="#my_anglebrac-name">name</a>, <a href="#my_anglebrac-also_useless">also_useless</a>, <a href="#my_anglebrac-useless">useless</a>)
</pre>
-Rule with &lt;brackets&gt;
+Rule with \<brackets>
**ATTRIBUTES**
@@ -21,7 +28,8 @@ Rule with &lt;brackets&gt;
| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="my_anglebrac-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
-| <a id="my_anglebrac-useless"></a>useless | Args with some tags: &lt;tag1&gt;, &lt;tag2&gt; | String | optional | <code>"Find &lt;brackets&gt;"</code> |
+| <a id="my_anglebrac-also_useless"></a>also_useless | Args with some formatted tags: `<tag>` and <pre><code class="language-xml">&lt;tag2&gt;x&lt;/tag2&gt;</code></pre> | String | optional | `"1<<5"` |
+| <a id="my_anglebrac-useless"></a>useless | Args with some tags: \<tag1>, \<tag2> | String | optional | `"Find \\<brackets>"` |
<a id="bracketuse"></a>
@@ -32,14 +40,14 @@ Rule with &lt;brackets&gt;
bracketuse(<a href="#bracketuse-foo">foo</a>, <a href="#bracketuse-bar">bar</a>, <a href="#bracketuse-baz">baz</a>)
</pre>
-Information with &lt;brackets&gt;
+Information with \<brackets>
**FIELDS**
| Name | Description |
| :------------- | :------------- |
-| <a id="bracketuse-foo"></a>foo | A string representing &lt;foo&gt; |
+| <a id="bracketuse-foo"></a>foo | A string representing \<foo> |
| <a id="bracketuse-bar"></a>bar | A string representing bar |
| <a id="bracketuse-baz"></a>baz | A string representing baz |
@@ -49,12 +57,19 @@ Information with &lt;brackets&gt;
## bracket_function
<pre>
-bracket_function(<a href="#bracket_function-param">param</a>)
+bracket_function(<a href="#bracket_function-param">param</a>, <a href="#bracket_function-md_string">md_string</a>)
</pre>
-Dummy docstring with &lt;brackets&gt;.
+Dummy docstring with \<brackets>.
+
+This rule runs checks on `<angle brackets>`.
-This rule runs checks on &lt;angle brackets&gt;.
+Sometimes, we have such things on their own, but they may
+also appear in code blocks, like
+
+```starlark
+foo = "<thing>"
+```
**PARAMETERS**
@@ -62,15 +77,16 @@ This rule runs checks on &lt;angle brackets&gt;.
| Name | Description | Default Value |
| :------------- | :------------- | :------------- |
-| <a id="bracket_function-param"></a>param | an arg with **formatted** docstring, &lt;default&gt; by default. | <code>"&lt;default&gt;"</code> |
+| <a id="bracket_function-param"></a>param | an arg with **formatted** docstring, `<default>` by default. | `"<default>"` |
+| <a id="bracket_function-md_string"></a>md_string | A markdown string. | ``"foo `1<<10` bar"`` |
**RETURNS**
-some &lt;angled&gt; brackets
+some \<angled> brackets
**DEPRECATED**
-deprecated for &lt;reasons&gt;
+deprecated for \<reasons> as well as `<reasons>`.
<a id="bracket_aspect"></a>
@@ -81,7 +97,13 @@ deprecated for &lt;reasons&gt;
bracket_aspect(<a href="#bracket_aspect-name">name</a>, <a href="#bracket_aspect-brackets">brackets</a>)
</pre>
-Aspect with &lt;brackets&gt;
+Aspect.
+
+Sometimes, we want a code block like
+```starlark
+foo = "<brackets>"
+```
+which includes angle brackets.
**ASPECT ATTRIBUTES**
@@ -96,7 +118,7 @@ Aspect with &lt;brackets&gt;
| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
-| <a id="bracket_aspect-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
-| <a id="bracket_aspect-brackets"></a>brackets | Attribute with &lt;brackets&gt; | String | optional | <code>"&lt;default&gt;"</code> |
+| <a id="bracket_aspect-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
+| <a id="bracket_aspect-brackets"></a>brackets | Attribute with \<brackets> | String | optional | `"<default>"` |
diff --git a/test/testdata/angle_bracket_test/input.bzl b/test/testdata/angle_bracket_test/input.bzl
index 4df0e1f..0915215 100644
--- a/test/testdata/angle_bracket_test/input.bzl
+++ b/test/testdata/angle_bracket_test/input.bzl
@@ -1,29 +1,45 @@
-"""Input file to test <angle bracket bugs>
+"""Input file to test angle bracket bug (https://github.com/bazelbuild/skydoc/issues/186)
-See https://github.com/bazelbuild/skydoc/issues/186
-and https://github.com/bazelbuild/stardoc/issues/132"""
+See https://github.com/bazelbuild/skydoc/issues/186,
+https://github.com/bazelbuild/stardoc/issues/132,
+and https://github.com/bazelbuild/stardoc/issues/137.
-def bracket_function(param = "<default>"):
- """Dummy docstring with <brackets>.
+<b>HTML formatting</b> can be used in docstrings, just as in regular Markdown.
+Literal angle brackets can be obtained by escaping them with a backslash, where
+the backslash itself must be escaped for use in a Starlark docstring
+(`\\\\<` becomes \\<), or by using HTML entities (`&lt;` becomes &lt;).
+Angle brackets are also preserved in inline code blocks (`#include <vector>`).
+"""
- This rule runs checks on <angle brackets>.
+def bracket_function(param = "<default>", md_string = "foo `1<<10` bar"):
+ """Dummy docstring with \\<brackets>.
+
+ This rule runs checks on `<angle brackets>`.
+
+ Sometimes, we have such things on their own, but they may
+ also appear in code blocks, like
+
+ ```starlark
+ foo = "<thing>"
+ ```
Args:
- param: an arg with **formatted** docstring, <default> by default.
+ param: an arg with **formatted** docstring, `<default>` by default.
+ md_string: A markdown string.
Returns:
- some <angled> brackets
+ some \\<angled> brackets
Deprecated:
- deprecated for <reasons>
+ deprecated for \\<reasons> as well as `<reasons>`.
"""
- return param
+ return param or md_string
# buildifier: disable=unsorted-dict-items
bracketuse = provider(
- doc = "Information with <brackets>",
+ doc = "Information with \\<brackets>",
fields = {
- "foo": "A string representing <foo>",
+ "foo": "A string representing \\<foo>",
"bar": "A string representing bar",
"baz": "A string representing baz",
},
@@ -35,11 +51,19 @@ def _rule_impl(ctx):
my_anglebrac = rule(
implementation = _rule_impl,
- doc = "Rule with <brackets>",
+ doc = "Rule with \\<brackets>",
attrs = {
"useless": attr.string(
- doc = "Args with some tags: <tag1>, <tag2>",
- default = "Find <brackets>",
+ doc = "Args with some tags: \\<tag1>, \\<tag2>",
+ default = "Find \\<brackets>",
+ ),
+ "also_useless": attr.string(
+ doc = """Args with some formatted tags: `<tag>` and
+```xml
+<tag2>x</tag2>
+```
+""",
+ default = "1<<5",
),
},
)
@@ -50,11 +74,18 @@ def _bracket_aspect_impl(ctx):
bracket_aspect = aspect(
implementation = _bracket_aspect_impl,
- doc = "Aspect with <brackets>",
+ doc = """Aspect.
+
+Sometimes, we want a code block like
+```starlark
+foo = "<brackets>"
+```
+which includes angle brackets.
+""",
attr_aspects = ["deps"],
attrs = {
"brackets": attr.string(
- doc = "Attribute with <brackets>",
+ doc = "Attribute with \\<brackets>",
default = "<default>",
),
},
diff --git a/test/testdata/angle_bracket_test/legacy_golden.md b/test/testdata/angle_bracket_test/legacy_golden.md
new file mode 100644
index 0000000..42f8fc6
--- /dev/null
+++ b/test/testdata/angle_bracket_test/legacy_golden.md
@@ -0,0 +1,124 @@
+<!-- Generated with Stardoc: http://skydoc.bazel.build -->
+
+Input file to test angle bracket bug (https://github.com/bazelbuild/skydoc/issues/186)
+
+See https://github.com/bazelbuild/skydoc/issues/186,
+https://github.com/bazelbuild/stardoc/issues/132,
+and https://github.com/bazelbuild/stardoc/issues/137.
+
+<b>HTML formatting</b> can be used in docstrings, just as in regular Markdown.
+Literal angle brackets can be obtained by escaping them with a backslash, where
+the backslash itself must be escaped for use in a Starlark docstring
+(`\\<` becomes \<), or by using HTML entities (`&lt;` becomes &lt;).
+Angle brackets are also preserved in inline code blocks (`#include <vector>`).
+
+<a id="my_anglebrac"></a>
+
+## my_anglebrac
+
+<pre>
+my_anglebrac(<a href="#my_anglebrac-name">name</a>, <a href="#my_anglebrac-also_useless">also_useless</a>, <a href="#my_anglebrac-useless">useless</a>)
+</pre>
+
+Rule with \<brackets>
+
+**ATTRIBUTES**
+
+
+| Name | Description | Type | Mandatory | Default |
+| :------------- | :------------- | :------------- | :------------- | :------------- |
+| <a id="my_anglebrac-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
+| <a id="my_anglebrac-also_useless"></a>also_useless | Args with some formatted tags: `<tag>` and <pre><code class="language-xml">&lt;tag2&gt;x&lt;/tag2&gt;</code></pre> | String | optional | `"1<<5"` |
+| <a id="my_anglebrac-useless"></a>useless | Args with some tags: \<tag1>, \<tag2> | String | optional | `"Find \<brackets>"` |
+
+
+<a id="bracketuse"></a>
+
+## bracketuse
+
+<pre>
+bracketuse(<a href="#bracketuse-foo">foo</a>, <a href="#bracketuse-bar">bar</a>, <a href="#bracketuse-baz">baz</a>)
+</pre>
+
+Information with \<brackets>
+
+**FIELDS**
+
+
+| Name | Description |
+| :------------- | :------------- |
+| <a id="bracketuse-foo"></a>foo | A string representing \<foo> |
+| <a id="bracketuse-bar"></a>bar | A string representing bar |
+| <a id="bracketuse-baz"></a>baz | A string representing baz |
+
+
+<a id="bracket_function"></a>
+
+## bracket_function
+
+<pre>
+bracket_function(<a href="#bracket_function-param">param</a>, <a href="#bracket_function-md_string">md_string</a>)
+</pre>
+
+Dummy docstring with \<brackets>.
+
+This rule runs checks on `<angle brackets>`.
+
+Sometimes, we have such things on their own, but they may
+also appear in code blocks, like
+
+```starlark
+foo = "<thing>"
+```
+
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="bracket_function-param"></a>param | an arg with **formatted** docstring, `<default>` by default. | `"<default>"` |
+| <a id="bracket_function-md_string"></a>md_string | A markdown string. | ``"foo `1<<10` bar"`` |
+
+**RETURNS**
+
+some \<angled> brackets
+
+**DEPRECATED**
+
+deprecated for \<reasons> as well as `<reasons>`.
+
+
+<a id="bracket_aspect"></a>
+
+## bracket_aspect
+
+<pre>
+bracket_aspect(<a href="#bracket_aspect-name">name</a>, <a href="#bracket_aspect-brackets">brackets</a>)
+</pre>
+
+Aspect.
+
+Sometimes, we want a code block like
+```starlark
+foo = "<brackets>"
+```
+which includes angle brackets.
+
+**ASPECT ATTRIBUTES**
+
+
+| Name | Type |
+| :------------- | :------------- |
+| deps| String |
+
+
+**ATTRIBUTES**
+
+
+| Name | Description | Type | Mandatory | Default |
+| :------------- | :------------- | :------------- | :------------- | :------------- |
+| <a id="bracket_aspect-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
+| <a id="bracket_aspect-brackets"></a>brackets | Attribute with \<brackets> | String | optional | `"<default>"` |
+
+
diff --git a/test/testdata/apple_basic_test/golden.md b/test/testdata/apple_basic_test/golden.md
index 5a9eb6e..b9e7a5b 100755..100644
--- a/test/testdata/apple_basic_test/golden.md
+++ b/test/testdata/apple_basic_test/golden.md
@@ -19,7 +19,7 @@ This rule does apple-related things.
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="apple_related_rule-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
| <a id="apple_related_rule-first"></a>first | - | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
-| <a id="apple_related_rule-fourth"></a>fourth | - | Boolean | optional | <code>False</code> |
+| <a id="apple_related_rule-fourth"></a>fourth | - | Boolean | optional | `False` |
| <a id="apple_related_rule-second"></a>second | - | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | required | |
| <a id="apple_related_rule-third"></a>third | - | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
diff --git a/test/testdata/aspect_test/golden.md b/test/testdata/aspect_test/golden.md
index 92e62cc..e1ef986 100755..100644
--- a/test/testdata/aspect_test/golden.md
+++ b/test/testdata/aspect_test/golden.md
@@ -28,7 +28,9 @@ my_aspect_impl(<a href="#my_aspect_impl-ctx">ctx</a>)
my_aspect(<a href="#my_aspect-name">name</a>, <a href="#my_aspect-first">first</a>, <a href="#my_aspect-second">second</a>)
</pre>
-This is my aspect. It does stuff.
+This is my aspect.
+
+It does stuff.
**ASPECT ATTRIBUTES**
@@ -44,9 +46,9 @@ This is my aspect. It does stuff.
| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
-| <a id="my_aspect-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
-| <a id="my_aspect-first"></a>first | - | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
-| <a id="my_aspect-second"></a>second | - | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | required | |
+| <a id="my_aspect-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
+| <a id="my_aspect-first"></a>first | - | Boolean | required | |
+| <a id="my_aspect-second"></a>second | - | String | required | |
<a id="other_aspect"></a>
@@ -62,17 +64,13 @@ This is another aspect.
**ASPECT ATTRIBUTES**
-| Name | Type |
-| :------------- | :------------- |
-| *| String |
-
**ATTRIBUTES**
| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
-| <a id="other_aspect-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
-| <a id="other_aspect-third"></a>third | - | Integer | required | |
+| <a id="other_aspect-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
+| <a id="other_aspect-third"></a>third | - | Integer | required | |
diff --git a/test/testdata/aspect_test/input.bzl b/test/testdata/aspect_test/input.bzl
index 72e35a5..38ddde0 100644
--- a/test/testdata/aspect_test/input.bzl
+++ b/test/testdata/aspect_test/input.bzl
@@ -6,11 +6,15 @@ def my_aspect_impl(ctx):
my_aspect = aspect(
implementation = my_aspect_impl,
- doc = "This is my aspect. It does stuff.",
+ doc = """
+ This is my aspect.
+
+ It does stuff.
+ """,
attr_aspects = ["deps", "attr_aspect"],
attrs = {
- "first": attr.label(mandatory = True, allow_single_file = True),
- "second": attr.string_dict(mandatory = True),
+ "first": attr.bool(mandatory = True),
+ "second": attr.string(mandatory = True),
},
)
diff --git a/test/testdata/aspect_test/legacy_golden.md b/test/testdata/aspect_test/legacy_golden.md
new file mode 100644
index 0000000..283689a
--- /dev/null
+++ b/test/testdata/aspect_test/legacy_golden.md
@@ -0,0 +1,80 @@
+<!-- Generated with Stardoc: http://skydoc.bazel.build -->
+
+The input file for the aspect test
+
+<a id="my_aspect_impl"></a>
+
+## my_aspect_impl
+
+<pre>
+my_aspect_impl(<a href="#my_aspect_impl-ctx">ctx</a>)
+</pre>
+
+
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="my_aspect_impl-ctx"></a>ctx | <p align="center"> - </p> | none |
+
+
+<a id="my_aspect"></a>
+
+## my_aspect
+
+<pre>
+my_aspect(<a href="#my_aspect-name">name</a>, <a href="#my_aspect-first">first</a>, <a href="#my_aspect-second">second</a>)
+</pre>
+
+This is my aspect.
+
+It does stuff.
+
+**ASPECT ATTRIBUTES**
+
+
+| Name | Type |
+| :------------- | :------------- |
+| deps| String |
+| attr_aspect| String |
+
+
+**ATTRIBUTES**
+
+
+| Name | Description | Type | Mandatory | Default |
+| :------------- | :------------- | :------------- | :------------- | :------------- |
+| <a id="my_aspect-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
+| <a id="my_aspect-first"></a>first | - | Boolean | required | |
+| <a id="my_aspect-second"></a>second | - | String | required | |
+
+
+<a id="other_aspect"></a>
+
+## other_aspect
+
+<pre>
+other_aspect(<a href="#other_aspect-name">name</a>, <a href="#other_aspect-third">third</a>)
+</pre>
+
+This is another aspect.
+
+**ASPECT ATTRIBUTES**
+
+
+| Name | Type |
+| :------------- | :------------- |
+| *| String |
+
+
+**ATTRIBUTES**
+
+
+| Name | Description | Type | Mandatory | Default |
+| :------------- | :------------- | :------------- | :------------- | :------------- |
+| <a id="other_aspect-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
+| <a id="other_aspect-third"></a>third | - | Integer | required | |
+
+
diff --git a/test/testdata/attribute_defaults_test/golden.md b/test/testdata/attribute_defaults_test/golden.md
index ae62b4c..64adeab 100755..100644
--- a/test/testdata/attribute_defaults_test/golden.md
+++ b/test/testdata/attribute_defaults_test/golden.md
@@ -18,16 +18,16 @@ This is my rule. It does stuff.
| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="my_rule-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
-| <a id="my_rule-a"></a>a | Some bool | Boolean | optional | <code>False</code> |
-| <a id="my_rule-b"></a>b | Some int | Integer | optional | <code>2</code> |
-| <a id="my_rule-c"></a>c | Some int_list | List of integers | optional | <code>[0, 1]</code> |
-| <a id="my_rule-d"></a>d | Some label | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>//foo:bar</code> |
-| <a id="my_rule-e"></a>e | Some label_keyed_string_dict | <a href="https://bazel.build/rules/lib/dict">Dictionary: Label -> String</a> | optional | <code>{"//foo:bar": "hello", "//bar:baz": "goodbye"}</code> |
-| <a id="my_rule-f"></a>f | Some label_list | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | <code>["//foo:bar", "//bar:baz"]</code> |
-| <a id="my_rule-g"></a>g | Some string | String | optional | <code>""</code> |
-| <a id="my_rule-h"></a>h | Some string_dict | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | optional | <code>{"animal": "bunny", "color": "orange"}</code> |
-| <a id="my_rule-i"></a>i | Some string_list | List of strings | optional | <code>["cat", "dog"]</code> |
-| <a id="my_rule-j"></a>j | Some string_list_dict | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> List of strings</a> | optional | <code>{"animal": ["cat", "bunny"], "color": ["blue", "orange"]}</code> |
+| <a id="my_rule-a"></a>a | Some bool | Boolean | optional | `False` |
+| <a id="my_rule-b"></a>b | Some int | Integer | optional | `2` |
+| <a id="my_rule-c"></a>c | Some int_list | List of integers | optional | `[0, 1]` |
+| <a id="my_rule-d"></a>d | Some label | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `"@io_bazel_stardoc//foo:bar"` |
+| <a id="my_rule-e"></a>e | Some label_keyed_string_dict | <a href="https://bazel.build/rules/lib/dict">Dictionary: Label -> String</a> | optional | `{"@io_bazel_stardoc//foo:bar": "hello", "@io_bazel_stardoc//bar:baz": "goodbye"}` |
+| <a id="my_rule-f"></a>f | Some label_list | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `["@io_bazel_stardoc//foo:bar", "@io_bazel_stardoc//bar:baz"]` |
+| <a id="my_rule-g"></a>g | Some string | String | optional | `""` |
+| <a id="my_rule-h"></a>h | Some string_dict | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | optional | `{"animal": "bunny", "color": "orange"}` |
+| <a id="my_rule-i"></a>i | Some string_list | List of strings | optional | `["cat", "dog"]` |
+| <a id="my_rule-j"></a>j | Some string_list_dict | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> List of strings</a> | optional | `{"animal": ["cat", "bunny"], "color": ["blue", "orange"]}` |
| <a id="my_rule-k"></a>k | Some bool | Boolean | required | |
| <a id="my_rule-l"></a>l | Some int | Integer | required | |
| <a id="my_rule-m"></a>m | Some int_list | List of integers | required | |
@@ -38,9 +38,9 @@ This is my rule. It does stuff.
| <a id="my_rule-r"></a>r | Some string_dict | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | required | |
| <a id="my_rule-s"></a>s | Some string_list | List of strings | required | |
| <a id="my_rule-t"></a>t | Some string_list_dict | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> List of strings</a> | required | |
-| <a id="my_rule-u"></a>u | - | String | optional | <code>""</code> |
-| <a id="my_rule-v"></a>v | - | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>None</code> |
-| <a id="my_rule-w"></a>w | - | Integer | optional | <code>0</code> |
+| <a id="my_rule-u"></a>u | - | String | optional | `""` |
+| <a id="my_rule-v"></a>v | - | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
+| <a id="my_rule-w"></a>w | - | Integer | optional | `0` |
<a id="my_aspect"></a>
@@ -67,8 +67,8 @@ This is my aspect. It does stuff.
| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
-| <a id="my_aspect-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
-| <a id="my_aspect-y"></a>y | some string | String | optional | <code>"why"</code> |
-| <a id="my_aspect-z"></a>z | - | String | required | |
+| <a id="my_aspect-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
+| <a id="my_aspect-y"></a>y | some string | String | optional | `"why"` |
+| <a id="my_aspect-z"></a>z | - | String | required | |
diff --git a/test/testdata/attribute_defaults_test/input.bzl b/test/testdata/attribute_defaults_test/input.bzl
index 3b531b3..9812790 100644
--- a/test/testdata/attribute_defaults_test/input.bzl
+++ b/test/testdata/attribute_defaults_test/input.bzl
@@ -14,7 +14,7 @@ my_aspect = aspect(
doc = "This is my aspect. It does stuff.",
attr_aspects = ["deps", "attr_aspect"],
attrs = {
- "_x": attr.label(mandatory = True),
+ "_x": attr.label(mandatory = True, default = "//foo:bar"),
"y": attr.string(default = "why", doc = "some string"),
"z": attr.string(mandatory = True),
},
diff --git a/test/testdata/attribute_defaults_test/legacy_golden.md b/test/testdata/attribute_defaults_test/legacy_golden.md
new file mode 100644
index 0000000..4eaf4b9
--- /dev/null
+++ b/test/testdata/attribute_defaults_test/legacy_golden.md
@@ -0,0 +1,74 @@
+<!-- Generated with Stardoc: http://skydoc.bazel.build -->
+
+A golden test to verify attribute default values.
+
+<a id="my_rule"></a>
+
+## my_rule
+
+<pre>
+my_rule(<a href="#my_rule-name">name</a>, <a href="#my_rule-a">a</a>, <a href="#my_rule-b">b</a>, <a href="#my_rule-c">c</a>, <a href="#my_rule-d">d</a>, <a href="#my_rule-e">e</a>, <a href="#my_rule-f">f</a>, <a href="#my_rule-g">g</a>, <a href="#my_rule-h">h</a>, <a href="#my_rule-i">i</a>, <a href="#my_rule-j">j</a>, <a href="#my_rule-k">k</a>, <a href="#my_rule-l">l</a>, <a href="#my_rule-m">m</a>, <a href="#my_rule-n">n</a>, <a href="#my_rule-o">o</a>, <a href="#my_rule-p">p</a>, <a href="#my_rule-q">q</a>, <a href="#my_rule-r">r</a>, <a href="#my_rule-s">s</a>, <a href="#my_rule-t">t</a>, <a href="#my_rule-u">u</a>, <a href="#my_rule-v">v</a>, <a href="#my_rule-w">w</a>)
+</pre>
+
+This is my rule. It does stuff.
+
+**ATTRIBUTES**
+
+
+| Name | Description | Type | Mandatory | Default |
+| :------------- | :------------- | :------------- | :------------- | :------------- |
+| <a id="my_rule-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
+| <a id="my_rule-a"></a>a | Some bool | Boolean | optional | `False` |
+| <a id="my_rule-b"></a>b | Some int | Integer | optional | `2` |
+| <a id="my_rule-c"></a>c | Some int_list | List of integers | optional | `[0, 1]` |
+| <a id="my_rule-d"></a>d | Some label | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `//foo:bar` |
+| <a id="my_rule-e"></a>e | Some label_keyed_string_dict | <a href="https://bazel.build/rules/lib/dict">Dictionary: Label -> String</a> | optional | `{"//foo:bar": "hello", "//bar:baz": "goodbye"}` |
+| <a id="my_rule-f"></a>f | Some label_list | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `["//foo:bar", "//bar:baz"]` |
+| <a id="my_rule-g"></a>g | Some string | String | optional | `""` |
+| <a id="my_rule-h"></a>h | Some string_dict | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | optional | `{"animal": "bunny", "color": "orange"}` |
+| <a id="my_rule-i"></a>i | Some string_list | List of strings | optional | `["cat", "dog"]` |
+| <a id="my_rule-j"></a>j | Some string_list_dict | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> List of strings</a> | optional | `{"animal": ["cat", "bunny"], "color": ["blue", "orange"]}` |
+| <a id="my_rule-k"></a>k | Some bool | Boolean | required | |
+| <a id="my_rule-l"></a>l | Some int | Integer | required | |
+| <a id="my_rule-m"></a>m | Some int_list | List of integers | required | |
+| <a id="my_rule-n"></a>n | Some label | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
+| <a id="my_rule-o"></a>o | Some label_keyed_string_dict | <a href="https://bazel.build/rules/lib/dict">Dictionary: Label -> String</a> | required | |
+| <a id="my_rule-p"></a>p | Some label_list | <a href="https://bazel.build/concepts/labels">List of labels</a> | required | |
+| <a id="my_rule-q"></a>q | Some string | String | required | |
+| <a id="my_rule-r"></a>r | Some string_dict | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | required | |
+| <a id="my_rule-s"></a>s | Some string_list | List of strings | required | |
+| <a id="my_rule-t"></a>t | Some string_list_dict | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> List of strings</a> | required | |
+| <a id="my_rule-u"></a>u | - | String | optional | `""` |
+| <a id="my_rule-v"></a>v | - | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
+| <a id="my_rule-w"></a>w | - | Integer | optional | `0` |
+
+
+<a id="my_aspect"></a>
+
+## my_aspect
+
+<pre>
+my_aspect(<a href="#my_aspect-name">name</a>, <a href="#my_aspect-y">y</a>, <a href="#my_aspect-z">z</a>)
+</pre>
+
+This is my aspect. It does stuff.
+
+**ASPECT ATTRIBUTES**
+
+
+| Name | Type |
+| :------------- | :------------- |
+| deps| String |
+| attr_aspect| String |
+
+
+**ATTRIBUTES**
+
+
+| Name | Description | Type | Mandatory | Default |
+| :------------- | :------------- | :------------- | :------------- | :------------- |
+| <a id="my_aspect-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
+| <a id="my_aspect-y"></a>y | some string | String | optional | `"why"` |
+| <a id="my_aspect-z"></a>z | - | String | required | |
+
+
diff --git a/test/testdata/attribute_types_test/golden.md b/test/testdata/attribute_types_test/golden.md
index 9a988c1..1412f2f 100755..100644
--- a/test/testdata/attribute_types_test/golden.md
+++ b/test/testdata/attribute_types_test/golden.md
@@ -10,7 +10,9 @@
my_rule(<a href="#my_rule-name">name</a>, <a href="#my_rule-a">a</a>, <a href="#my_rule-b">b</a>, <a href="#my_rule-c">c</a>, <a href="#my_rule-d">d</a>, <a href="#my_rule-e">e</a>, <a href="#my_rule-f">f</a>, <a href="#my_rule-g">g</a>, <a href="#my_rule-h">h</a>, <a href="#my_rule-i">i</a>, <a href="#my_rule-j">j</a>, <a href="#my_rule-k">k</a>, <a href="#my_rule-l">l</a>)
</pre>
-This is my rule. It does stuff.
+This is my rule.
+
+It does stuff.
**ATTRIBUTES**
@@ -24,11 +26,11 @@ This is my rule. It does stuff.
| <a id="my_rule-d"></a>d | Some label | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
| <a id="my_rule-e"></a>e | Some label_keyed_string_dict | <a href="https://bazel.build/rules/lib/dict">Dictionary: Label -> String</a> | required | |
| <a id="my_rule-f"></a>f | Some label_list | <a href="https://bazel.build/concepts/labels">List of labels</a> | required | |
-| <a id="my_rule-g"></a>g | Some output | <a href="https://bazel.build/concepts/labels">Label</a> | optional | |
-| <a id="my_rule-h"></a>h | Some output_list | List of labels | optional | |
+| <a id="my_rule-g"></a>g | Some output | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
+| <a id="my_rule-h"></a>h | Some output_list | List of labels | optional | `[]` |
| <a id="my_rule-i"></a>i | Some string | String | required | |
| <a id="my_rule-j"></a>j | Some string_dict | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | required | |
| <a id="my_rule-k"></a>k | Some string_list | List of strings | required | |
-| <a id="my_rule-l"></a>l | Some string_list_dict | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> List of strings</a> | optional | <code>{}</code> |
+| <a id="my_rule-l"></a>l | Some string_list_dict | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> List of strings</a> | optional | `{}` |
diff --git a/test/testdata/attribute_types_test/input.bzl b/test/testdata/attribute_types_test/input.bzl
index 92c037c..3c1e8d5 100644
--- a/test/testdata/attribute_types_test/input.bzl
+++ b/test/testdata/attribute_types_test/input.bzl
@@ -6,7 +6,11 @@ def my_rule_impl(ctx):
my_rule = rule(
implementation = my_rule_impl,
- doc = "This is my rule. It does stuff.",
+ doc = """
+ This is my rule.
+
+ It does stuff.
+ """,
attrs = {
"a": attr.bool(mandatory = True, doc = "Some bool"),
"b": attr.int(mandatory = True, doc = "Some int"),
diff --git a/test/testdata/attribute_types_test/legacy_golden.md b/test/testdata/attribute_types_test/legacy_golden.md
new file mode 100644
index 0000000..aa2ae91
--- /dev/null
+++ b/test/testdata/attribute_types_test/legacy_golden.md
@@ -0,0 +1,36 @@
+<!-- Generated with Stardoc: http://skydoc.bazel.build -->
+
+
+
+<a id="my_rule"></a>
+
+## my_rule
+
+<pre>
+my_rule(<a href="#my_rule-name">name</a>, <a href="#my_rule-a">a</a>, <a href="#my_rule-b">b</a>, <a href="#my_rule-c">c</a>, <a href="#my_rule-d">d</a>, <a href="#my_rule-e">e</a>, <a href="#my_rule-f">f</a>, <a href="#my_rule-g">g</a>, <a href="#my_rule-h">h</a>, <a href="#my_rule-i">i</a>, <a href="#my_rule-j">j</a>, <a href="#my_rule-k">k</a>, <a href="#my_rule-l">l</a>)
+</pre>
+
+This is my rule.
+
+It does stuff.
+
+**ATTRIBUTES**
+
+
+| Name | Description | Type | Mandatory | Default |
+| :------------- | :------------- | :------------- | :------------- | :------------- |
+| <a id="my_rule-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
+| <a id="my_rule-a"></a>a | Some bool | Boolean | required | |
+| <a id="my_rule-b"></a>b | Some int | Integer | required | |
+| <a id="my_rule-c"></a>c | Some int_list | List of integers | required | |
+| <a id="my_rule-d"></a>d | Some label | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
+| <a id="my_rule-e"></a>e | Some label_keyed_string_dict | <a href="https://bazel.build/rules/lib/dict">Dictionary: Label -> String</a> | required | |
+| <a id="my_rule-f"></a>f | Some label_list | <a href="https://bazel.build/concepts/labels">List of labels</a> | required | |
+| <a id="my_rule-g"></a>g | Some output | <a href="https://bazel.build/concepts/labels">Label</a> | optional | |
+| <a id="my_rule-h"></a>h | Some output_list | List of labels | optional | |
+| <a id="my_rule-i"></a>i | Some string | String | required | |
+| <a id="my_rule-j"></a>j | Some string_dict | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | required | |
+| <a id="my_rule-k"></a>k | Some string_list | List of strings | required | |
+| <a id="my_rule-l"></a>l | Some string_list_dict | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> List of strings</a> | optional | `{}` |
+
+
diff --git a/test/testdata/cc_api_test/golden.md b/test/testdata/cc_api_test/golden.md
index 10ca7f8..183402e 100755..100644
--- a/test/testdata/cc_api_test/golden.md
+++ b/test/testdata/cc_api_test/golden.md
@@ -19,7 +19,7 @@ This rule does C++-related things.
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="cpp_related_rule-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
| <a id="cpp_related_rule-first"></a>first | - | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
-| <a id="cpp_related_rule-fourth"></a>fourth | - | Boolean | optional | <code>False</code> |
+| <a id="cpp_related_rule-fourth"></a>fourth | - | Boolean | optional | `False` |
| <a id="cpp_related_rule-second"></a>second | - | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | required | |
| <a id="cpp_related_rule-third"></a>third | - | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
diff --git a/test/testdata/config_apis_test/golden.md b/test/testdata/config_apis_test/golden.md
index e1d5fdf..e1d5fdf 100755..100644
--- a/test/testdata/config_apis_test/golden.md
+++ b/test/testdata/config_apis_test/golden.md
diff --git a/test/testdata/config_apis_test/input.bzl b/test/testdata/config_apis_test/input.bzl
index fb2a8ce..d5b3c2f 100644
--- a/test/testdata/config_apis_test/input.bzl
+++ b/test/testdata/config_apis_test/input.bzl
@@ -1,7 +1,7 @@
# buildifier: disable=module-docstring
# buildifier: disable=function-docstring
def exercise_the_api():
- _var6 = configuration_field("foo", "bar") # @unused
+ _unused = configuration_field(fragment = "cpp", name = "custom_malloc") # @unused
exercise_the_api()
diff --git a/test/testdata/cpp_basic_test/golden.md b/test/testdata/cpp_basic_test/golden.md
index 7061e26..abce00a 100755..100644
--- a/test/testdata/cpp_basic_test/golden.md
+++ b/test/testdata/cpp_basic_test/golden.md
@@ -19,7 +19,7 @@ This rule does cpp-related things.
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="cpp_related_rule-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
| <a id="cpp_related_rule-first"></a>first | - | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
-| <a id="cpp_related_rule-fourth"></a>fourth | - | Boolean | optional | <code>False</code> |
+| <a id="cpp_related_rule-fourth"></a>fourth | - | Boolean | optional | `False` |
| <a id="cpp_related_rule-second"></a>second | - | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | required | |
| <a id="cpp_related_rule-third"></a>third | - | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
diff --git a/test/testdata/filter_rules_test/golden.md b/test/testdata/filter_rules_test/golden.md
index 7e85581..2801a16 100755..100644
--- a/test/testdata/filter_rules_test/golden.md
+++ b/test/testdata/filter_rules_test/golden.md
@@ -2,43 +2,43 @@
-<a id="my_rule"></a>
+<a id="allowlisted_dep_rule"></a>
-## my_rule
+## allowlisted_dep_rule
<pre>
-my_rule(<a href="#my_rule-name">name</a>, <a href="#my_rule-first">first</a>, <a href="#my_rule-second">second</a>)
+allowlisted_dep_rule(<a href="#allowlisted_dep_rule-name">name</a>, <a href="#allowlisted_dep_rule-first">first</a>, <a href="#allowlisted_dep_rule-second">second</a>)
</pre>
-This is my rule. It does stuff.
+This is the dep rule. It does stuff.
**ATTRIBUTES**
| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
-| <a id="my_rule-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
-| <a id="my_rule-first"></a>first | first my_rule doc string | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
-| <a id="my_rule-second"></a>second | - | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | required | |
+| <a id="allowlisted_dep_rule-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
+| <a id="allowlisted_dep_rule-first"></a>first | dep's my_rule doc string | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
+| <a id="allowlisted_dep_rule-second"></a>second | - | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | required | |
-<a id="whitelisted_dep_rule"></a>
+<a id="my_rule"></a>
-## whitelisted_dep_rule
+## my_rule
<pre>
-whitelisted_dep_rule(<a href="#whitelisted_dep_rule-name">name</a>, <a href="#whitelisted_dep_rule-first">first</a>, <a href="#whitelisted_dep_rule-second">second</a>)
+my_rule(<a href="#my_rule-name">name</a>, <a href="#my_rule-first">first</a>, <a href="#my_rule-second">second</a>)
</pre>
-This is the dep rule. It does stuff.
+This is my rule. It does stuff.
**ATTRIBUTES**
| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
-| <a id="whitelisted_dep_rule-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
-| <a id="whitelisted_dep_rule-first"></a>first | dep's my_rule doc string | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
-| <a id="whitelisted_dep_rule-second"></a>second | - | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | required | |
+| <a id="my_rule-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
+| <a id="my_rule-first"></a>first | first my_rule doc string | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
+| <a id="my_rule-second"></a>second | - | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | required | |
diff --git a/test/testdata/filter_rules_test/input.bzl b/test/testdata/filter_rules_test/input.bzl
index 5d05b9b..08cc012 100644
--- a/test/testdata/filter_rules_test/input.bzl
+++ b/test/testdata/filter_rules_test/input.bzl
@@ -1,13 +1,10 @@
# buildifier: disable=module-docstring
load(
":testdata/filter_rules_test/dep.bzl",
+ "my_rule_impl",
dep_rule = "my_rule",
)
-def my_rule_impl(ctx):
- _ignore = [ctx] # @unused
- return []
-
my_rule = rule(
implementation = my_rule_impl,
doc = "This is my rule. It does stuff.",
@@ -29,7 +26,7 @@ other_rule = rule(
},
)
-whitelisted_dep_rule = dep_rule
+allowlisted_dep_rule = dep_rule
yet_another_rule = rule(
implementation = my_rule_impl,
diff --git a/test/testdata/function_basic_test/golden.md b/test/testdata/function_basic_test/golden.md
index 138f3c2..bf758b1 100755..100644
--- a/test/testdata/function_basic_test/golden.md
+++ b/test/testdata/function_basic_test/golden.md
@@ -24,12 +24,12 @@ Use `bazel build` to run the check.
| :------------- | :------------- | :------------- |
| <a id="check_sources-name"></a>name | A unique name for this rule. | none |
| <a id="check_sources-required_param"></a>required_param | Use your imagination. | none |
-| <a id="check_sources-bool_param"></a>bool_param | <p align="center"> - </p> | <code>True</code> |
-| <a id="check_sources-srcs"></a>srcs | Source files to run the checks against. | <code>[]</code> |
-| <a id="check_sources-string_param"></a>string_param | <p align="center"> - </p> | <code>""</code> |
-| <a id="check_sources-int_param"></a>int_param | Your favorite number. | <code>2</code> |
-| <a id="check_sources-dict_param"></a>dict_param | <p align="center"> - </p> | <code>{}</code> |
-| <a id="check_sources-struct_param"></a>struct_param | <p align="center"> - </p> | <code>struct(foo = "bar")</code> |
+| <a id="check_sources-bool_param"></a>bool_param | <p align="center"> - </p> | `True` |
+| <a id="check_sources-srcs"></a>srcs | Source files to run the checks against. | `[]` |
+| <a id="check_sources-string_param"></a>string_param | <p align="center"> - </p> | `""` |
+| <a id="check_sources-int_param"></a>int_param | Your favorite number. | `2` |
+| <a id="check_sources-dict_param"></a>dict_param | <p align="center"> - </p> | `{}` |
+| <a id="check_sources-struct_param"></a>struct_param | <p align="center"> - </p> | `struct(foo = "bar")` |
<a id="deprecated_do_not_use"></a>
@@ -48,6 +48,24 @@ This function is deprecated.
Use literally anything but this function.
+<a id="param_doc_multiline"></a>
+
+## param_doc_multiline
+
+<pre>
+param_doc_multiline(<a href="#param_doc_multiline-complex">complex</a>)
+</pre>
+
+Has a complex parameter.
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="param_doc_multiline-complex"></a>complex | A parameter with some non-obvious behavior.<br><br> For example, it does things that require **multiple paragraphs** to explain.<br><br>Note: we should preserve the nested indent in the following code:<br><br><pre><code class="language-json">{&#10; "key": "value"&#10;}</code></pre> | none |
+
+
<a id="returns_a_thing"></a>
## returns_a_thing
diff --git a/test/testdata/function_basic_test/input.bzl b/test/testdata/function_basic_test/input.bzl
index 93bf711..2d75025 100644
--- a/test/testdata/function_basic_test/input.bzl
+++ b/test/testdata/function_basic_test/input.bzl
@@ -54,6 +54,25 @@ def deprecated_do_not_use():
"""
pass
+# buildifier: disable=unused-variable
def undocumented_function(a, b, c):
- _ignore = [a, b, c] # @unused
+ pass
+
+# buildifier: disable=unused-variable
+def param_doc_multiline(complex):
+ """Has a complex parameter.
+
+ Args:
+ complex: A parameter with some non-obvious behavior.
+
+ For example, it does things that require **multiple paragraphs** to explain.
+
+ Note: we should preserve the nested indent in the following code:
+
+ ```json
+ {
+ "key": "value"
+ }
+ ```
+ """
pass
diff --git a/test/testdata/function_wrap_multiple_lines_test/golden.md b/test/testdata/function_wrap_multiple_lines_test/golden.md
new file mode 100644
index 0000000..81f7f9e
--- /dev/null
+++ b/test/testdata/function_wrap_multiple_lines_test/golden.md
@@ -0,0 +1,56 @@
+<!-- Generated with Stardoc: http://skydoc.bazel.build -->
+
+Rules for ANTLR 3.
+
+<a id="antlr"></a>
+
+## antlr
+
+<pre>
+antlr(<a href="#antlr-name">name</a>, <a href="#antlr-deps">deps</a>, <a href="#antlr-srcs">srcs</a>, <a href="#antlr-Xconversiontimeout">Xconversiontimeout</a>, <a href="#antlr-Xdbgconversion">Xdbgconversion</a>, <a href="#antlr-Xdbgst">Xdbgst</a>, <a href="#antlr-Xdfa">Xdfa</a>, <a href="#antlr-Xdfaverbose">Xdfaverbose</a>, <a href="#antlr-Xgrtree">Xgrtree</a>, <a href="#antlr-Xm">Xm</a>,
+ <a href="#antlr-Xmaxdfaedges">Xmaxdfaedges</a>, <a href="#antlr-Xmaxinlinedfastates">Xmaxinlinedfastates</a>, <a href="#antlr-Xminswitchalts">Xminswitchalts</a>, <a href="#antlr-Xmultithreaded">Xmultithreaded</a>, <a href="#antlr-Xnfastates">Xnfastates</a>, <a href="#antlr-Xnocollapse">Xnocollapse</a>,
+ <a href="#antlr-Xnomergestopstates">Xnomergestopstates</a>, <a href="#antlr-Xnoprune">Xnoprune</a>, <a href="#antlr-XsaveLexer">XsaveLexer</a>, <a href="#antlr-Xwatchconversion">Xwatchconversion</a>, <a href="#antlr-debug">debug</a>, <a href="#antlr-depend">depend</a>, <a href="#antlr-dfa">dfa</a>, <a href="#antlr-dump">dump</a>, <a href="#antlr-imports">imports</a>,
+ <a href="#antlr-language">language</a>, <a href="#antlr-message_format">message_format</a>, <a href="#antlr-nfa">nfa</a>, <a href="#antlr-package">package</a>, <a href="#antlr-profile">profile</a>, <a href="#antlr-report">report</a>, <a href="#antlr-trace">trace</a>)
+</pre>
+
+Runs [ANTLR 3](https://www.antlr3.org//) on a set of grammars.
+
+**ATTRIBUTES**
+
+
+| Name | Description | Type | Mandatory | Default |
+| :------------- | :------------- | :------------- | :------------- | :------------- |
+| <a id="antlr-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
+| <a id="antlr-deps"></a>deps | The dependencies to use. Defaults to the most recent ANTLR 3 release, but if you need to use a different version, you can specify the dependencies here. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `["@antlr3_runtimes//:tool"]` |
+| <a id="antlr-srcs"></a>srcs | The grammar files to process. | <a href="https://bazel.build/concepts/labels">List of labels</a> | required | |
+| <a id="antlr-Xconversiontimeout"></a>Xconversiontimeout | Set NFA conversion timeout for each decision. | Integer | optional | `0` |
+| <a id="antlr-Xdbgconversion"></a>Xdbgconversion | Dump lots of info during NFA conversion. | Boolean | optional | `False` |
+| <a id="antlr-Xdbgst"></a>Xdbgst | Put tags at start/stop of all templates in output. | Boolean | optional | `False` |
+| <a id="antlr-Xdfa"></a>Xdfa | Print DFA as text. | Boolean | optional | `False` |
+| <a id="antlr-Xdfaverbose"></a>Xdfaverbose | Generate DFA states in DOT with NFA configs. | Boolean | optional | `False` |
+| <a id="antlr-Xgrtree"></a>Xgrtree | Print the grammar AST. | Boolean | optional | `False` |
+| <a id="antlr-Xm"></a>Xm | Max number of rule invocations during conversion. | Integer | optional | `0` |
+| <a id="antlr-Xmaxdfaedges"></a>Xmaxdfaedges | Max &quot;comfortable&quot; number of edges for single DFA state. | Integer | optional | `0` |
+| <a id="antlr-Xmaxinlinedfastates"></a>Xmaxinlinedfastates | Max DFA states before table used rather than inlining. | Integer | optional | `0` |
+| <a id="antlr-Xminswitchalts"></a>Xminswitchalts | Don't generate switch() statements for dfas smaller than given number. | Integer | optional | `0` |
+| <a id="antlr-Xmultithreaded"></a>Xmultithreaded | Run the analysis in 2 threads. | Boolean | optional | `False` |
+| <a id="antlr-Xnfastates"></a>Xnfastates | For nondeterminisms, list NFA states for each path. | Boolean | optional | `False` |
+| <a id="antlr-Xnocollapse"></a>Xnocollapse | Collapse incident edges into DFA states. | Boolean | optional | `False` |
+| <a id="antlr-Xnomergestopstates"></a>Xnomergestopstates | Max DFA states before table used rather than inlining. | Boolean | optional | `False` |
+| <a id="antlr-Xnoprune"></a>Xnoprune | Do not test EBNF block exit branches. | Boolean | optional | `False` |
+| <a id="antlr-XsaveLexer"></a>XsaveLexer | For nondeterminisms, list NFA states for each path. | Boolean | optional | `False` |
+| <a id="antlr-Xwatchconversion"></a>Xwatchconversion | Don't delete temporary lexers generated from combined grammars. | Boolean | optional | `False` |
+| <a id="antlr-debug"></a>debug | Generate a parser that emits debugging events. | Boolean | optional | `False` |
+| <a id="antlr-depend"></a>depend | Generate file dependencies; don't actually run antlr. | Boolean | optional | `False` |
+| <a id="antlr-dfa"></a>dfa | Generate a DFA for each decision point. | Boolean | optional | `False` |
+| <a id="antlr-dump"></a>dump | Print out the grammar without actions. | Boolean | optional | `False` |
+| <a id="antlr-imports"></a>imports | The grammar and .tokens files to import. Must be all in the same directory. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
+| <a id="antlr-language"></a>language | The code generation target language. Either C, Cpp, CSharp2, CSharp3, JavaScript, Java, ObjC, Python, Python3 or Ruby (case-sensitive). | String | optional | `""` |
+| <a id="antlr-message_format"></a>message_format | Specify output style for messages. | String | optional | `""` |
+| <a id="antlr-nfa"></a>nfa | Generate an NFA for each rule. | Boolean | optional | `False` |
+| <a id="antlr-package"></a>package | The package/namespace for the generated code. | String | optional | `""` |
+| <a id="antlr-profile"></a>profile | Generate a parser that computes profiling information. | Boolean | optional | `False` |
+| <a id="antlr-report"></a>report | Print out a report about the grammar(s) processed. | Boolean | optional | `False` |
+| <a id="antlr-trace"></a>trace | Generate a parser with trace output. If the default output is not enough, you can override the traceIn and traceOut methods. | Boolean | optional | `False` |
+
+
diff --git a/test/testdata/function_wrap_multiple_lines_test/input.bzl b/test/testdata/function_wrap_multiple_lines_test/input.bzl
new file mode 100644
index 0000000..c822551
--- /dev/null
+++ b/test/testdata/function_wrap_multiple_lines_test/input.bzl
@@ -0,0 +1,54 @@
+"""Rules for ANTLR 3."""
+
+# buildifier: disable=unused-variable
+def _generate(ctx):
+ return None
+
+antlr = rule(
+ implementation = _generate,
+ doc = "Runs [ANTLR 3](https://www.antlr3.org//) on a set of grammars.",
+ attrs = {
+ "debug": attr.bool(default = False, doc = "Generate a parser that emits debugging events."),
+ "depend": attr.bool(default = False, doc = "Generate file dependencies; don't actually run antlr."),
+ "deps": attr.label_list(
+ default = [Label("@antlr3_runtimes//:tool")],
+ doc = """
+The dependencies to use. Defaults to the most recent ANTLR 3 release,
+but if you need to use a different version, you can specify the
+dependencies here.
+""",
+ ),
+ "dfa": attr.bool(default = False, doc = "Generate a DFA for each decision point."),
+ "dump": attr.bool(default = False, doc = "Print out the grammar without actions."),
+ "imports": attr.label_list(allow_files = True, doc = "The grammar and .tokens files to import. Must be all in the same directory."),
+ "language": attr.string(doc = "The code generation target language. Either C, Cpp, CSharp2, CSharp3, JavaScript, Java, ObjC, Python, Python3 or Ruby (case-sensitive)."),
+ "message_format": attr.string(doc = "Specify output style for messages."),
+ "nfa": attr.bool(default = False, doc = "Generate an NFA for each rule."),
+ "package": attr.string(doc = "The package/namespace for the generated code."),
+ "profile": attr.bool(default = False, doc = "Generate a parser that computes profiling information."),
+ "report": attr.bool(default = False, doc = "Print out a report about the grammar(s) processed."),
+ "srcs": attr.label_list(allow_files = True, mandatory = True, doc = "The grammar files to process."),
+ "trace": attr.bool(default = False, doc = "Generate a parser with trace output. If the default output is not enough, you can override the traceIn and traceOut methods."),
+ "Xconversiontimeout": attr.int(doc = "Set NFA conversion timeout for each decision."),
+ "Xdbgconversion": attr.bool(default = False, doc = "Dump lots of info during NFA conversion."),
+ "Xdbgst": attr.bool(default = False, doc = "Put tags at start/stop of all templates in output."),
+ "Xdfa": attr.bool(default = False, doc = "Print DFA as text."),
+ "Xdfaverbose": attr.bool(default = False, doc = "Generate DFA states in DOT with NFA configs."),
+ "Xgrtree": attr.bool(default = False, doc = "Print the grammar AST."),
+ "Xm": attr.int(doc = "Max number of rule invocations during conversion."),
+ "Xmaxdfaedges": attr.int(doc = "Max &quot;comfortable&quot; number of edges for single DFA state."),
+ "Xmaxinlinedfastates": attr.int(doc = "Max DFA states before table used rather than inlining."),
+ "Xminswitchalts": attr.int(doc = "Don't generate switch() statements for dfas smaller than given number."),
+ "Xmultithreaded": attr.bool(default = False, doc = "Run the analysis in 2 threads."),
+ "Xnfastates": attr.bool(default = False, doc = "For nondeterminisms, list NFA states for each path."),
+ "Xnocollapse": attr.bool(default = False, doc = "Collapse incident edges into DFA states."),
+ "Xnoprune": attr.bool(default = False, doc = "Do not test EBNF block exit branches."),
+ "Xnomergestopstates": attr.bool(default = False, doc = "Max DFA states before table used rather than inlining."),
+ "XsaveLexer": attr.bool(default = False, doc = "For nondeterminisms, list NFA states for each path."),
+ "Xwatchconversion": attr.bool(default = False, doc = "Don't delete temporary lexers generated from combined grammars."),
+ "_tool": attr.label(
+ executable = True,
+ cfg = "exec",
+ ),
+ },
+)
diff --git a/test/testdata/function_wrap_multiple_lines_test/legacy_golden.md b/test/testdata/function_wrap_multiple_lines_test/legacy_golden.md
new file mode 100644
index 0000000..817f02b
--- /dev/null
+++ b/test/testdata/function_wrap_multiple_lines_test/legacy_golden.md
@@ -0,0 +1,56 @@
+<!-- Generated with Stardoc: http://skydoc.bazel.build -->
+
+Rules for ANTLR 3.
+
+<a id="antlr"></a>
+
+## antlr
+
+<pre>
+antlr(<a href="#antlr-name">name</a>, <a href="#antlr-deps">deps</a>, <a href="#antlr-srcs">srcs</a>, <a href="#antlr-Xconversiontimeout">Xconversiontimeout</a>, <a href="#antlr-Xdbgconversion">Xdbgconversion</a>, <a href="#antlr-Xdbgst">Xdbgst</a>, <a href="#antlr-Xdfa">Xdfa</a>, <a href="#antlr-Xdfaverbose">Xdfaverbose</a>, <a href="#antlr-Xgrtree">Xgrtree</a>, <a href="#antlr-Xm">Xm</a>,
+ <a href="#antlr-Xmaxdfaedges">Xmaxdfaedges</a>, <a href="#antlr-Xmaxinlinedfastates">Xmaxinlinedfastates</a>, <a href="#antlr-Xminswitchalts">Xminswitchalts</a>, <a href="#antlr-Xmultithreaded">Xmultithreaded</a>, <a href="#antlr-Xnfastates">Xnfastates</a>, <a href="#antlr-Xnocollapse">Xnocollapse</a>,
+ <a href="#antlr-Xnomergestopstates">Xnomergestopstates</a>, <a href="#antlr-Xnoprune">Xnoprune</a>, <a href="#antlr-XsaveLexer">XsaveLexer</a>, <a href="#antlr-Xwatchconversion">Xwatchconversion</a>, <a href="#antlr-debug">debug</a>, <a href="#antlr-depend">depend</a>, <a href="#antlr-dfa">dfa</a>, <a href="#antlr-dump">dump</a>, <a href="#antlr-imports">imports</a>,
+ <a href="#antlr-language">language</a>, <a href="#antlr-message_format">message_format</a>, <a href="#antlr-nfa">nfa</a>, <a href="#antlr-package">package</a>, <a href="#antlr-profile">profile</a>, <a href="#antlr-report">report</a>, <a href="#antlr-trace">trace</a>)
+</pre>
+
+Runs [ANTLR 3](https://www.antlr3.org//) on a set of grammars.
+
+**ATTRIBUTES**
+
+
+| Name | Description | Type | Mandatory | Default |
+| :------------- | :------------- | :------------- | :------------- | :------------- |
+| <a id="antlr-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
+| <a id="antlr-deps"></a>deps | The dependencies to use. Defaults to the most recent ANTLR 3 release, but if you need to use a different version, you can specify the dependencies here. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[Label("@antlr3_runtimes//:tool")]` |
+| <a id="antlr-srcs"></a>srcs | The grammar files to process. | <a href="https://bazel.build/concepts/labels">List of labels</a> | required | |
+| <a id="antlr-Xconversiontimeout"></a>Xconversiontimeout | Set NFA conversion timeout for each decision. | Integer | optional | `0` |
+| <a id="antlr-Xdbgconversion"></a>Xdbgconversion | Dump lots of info during NFA conversion. | Boolean | optional | `False` |
+| <a id="antlr-Xdbgst"></a>Xdbgst | Put tags at start/stop of all templates in output. | Boolean | optional | `False` |
+| <a id="antlr-Xdfa"></a>Xdfa | Print DFA as text. | Boolean | optional | `False` |
+| <a id="antlr-Xdfaverbose"></a>Xdfaverbose | Generate DFA states in DOT with NFA configs. | Boolean | optional | `False` |
+| <a id="antlr-Xgrtree"></a>Xgrtree | Print the grammar AST. | Boolean | optional | `False` |
+| <a id="antlr-Xm"></a>Xm | Max number of rule invocations during conversion. | Integer | optional | `0` |
+| <a id="antlr-Xmaxdfaedges"></a>Xmaxdfaedges | Max &quot;comfortable&quot; number of edges for single DFA state. | Integer | optional | `0` |
+| <a id="antlr-Xmaxinlinedfastates"></a>Xmaxinlinedfastates | Max DFA states before table used rather than inlining. | Integer | optional | `0` |
+| <a id="antlr-Xminswitchalts"></a>Xminswitchalts | Don't generate switch() statements for dfas smaller than given number. | Integer | optional | `0` |
+| <a id="antlr-Xmultithreaded"></a>Xmultithreaded | Run the analysis in 2 threads. | Boolean | optional | `False` |
+| <a id="antlr-Xnfastates"></a>Xnfastates | For nondeterminisms, list NFA states for each path. | Boolean | optional | `False` |
+| <a id="antlr-Xnocollapse"></a>Xnocollapse | Collapse incident edges into DFA states. | Boolean | optional | `False` |
+| <a id="antlr-Xnomergestopstates"></a>Xnomergestopstates | Max DFA states before table used rather than inlining. | Boolean | optional | `False` |
+| <a id="antlr-Xnoprune"></a>Xnoprune | Do not test EBNF block exit branches. | Boolean | optional | `False` |
+| <a id="antlr-XsaveLexer"></a>XsaveLexer | For nondeterminisms, list NFA states for each path. | Boolean | optional | `False` |
+| <a id="antlr-Xwatchconversion"></a>Xwatchconversion | Don't delete temporary lexers generated from combined grammars. | Boolean | optional | `False` |
+| <a id="antlr-debug"></a>debug | Generate a parser that emits debugging events. | Boolean | optional | `False` |
+| <a id="antlr-depend"></a>depend | Generate file dependencies; don't actually run antlr. | Boolean | optional | `False` |
+| <a id="antlr-dfa"></a>dfa | Generate a DFA for each decision point. | Boolean | optional | `False` |
+| <a id="antlr-dump"></a>dump | Print out the grammar without actions. | Boolean | optional | `False` |
+| <a id="antlr-imports"></a>imports | The grammar and .tokens files to import. Must be all in the same directory. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
+| <a id="antlr-language"></a>language | The code generation target language. Either C, Cpp, CSharp2, CSharp3, JavaScript, Java, ObjC, Python, Python3 or Ruby (case-sensitive). | String | optional | `""` |
+| <a id="antlr-message_format"></a>message_format | Specify output style for messages. | String | optional | `""` |
+| <a id="antlr-nfa"></a>nfa | Generate an NFA for each rule. | Boolean | optional | `False` |
+| <a id="antlr-package"></a>package | The package/namespace for the generated code. | String | optional | `""` |
+| <a id="antlr-profile"></a>profile | Generate a parser that computes profiling information. | Boolean | optional | `False` |
+| <a id="antlr-report"></a>report | Print out a report about the grammar(s) processed. | Boolean | optional | `False` |
+| <a id="antlr-trace"></a>trace | Generate a parser with trace output. If the default output is not enough, you can override the traceIn and traceOut methods. | Boolean | optional | `False` |
+
+
diff --git a/test/testdata/generated_bzl_test/dep.bzl.tpl b/test/testdata/generated_bzl_test/dep.bzl.tpl
deleted file mode 100644
index 4c8bd78..0000000
--- a/test/testdata/generated_bzl_test/dep.bzl.tpl
+++ /dev/null
@@ -1,4 +0,0 @@
-"""Used to generate dep.bzl"""
-
-def my_rule_impl(ctx):
- return []
diff --git a/test/testdata/generated_bzl_test/golden.md b/test/testdata/generated_bzl_test/golden.md
deleted file mode 100755
index bd98967..0000000
--- a/test/testdata/generated_bzl_test/golden.md
+++ /dev/null
@@ -1,24 +0,0 @@
-<!-- Generated with Stardoc: http://skydoc.bazel.build -->
-
-A direct dependency file of the input file.
-
-<a id="my_rule"></a>
-
-## my_rule
-
-<pre>
-my_rule(<a href="#my_rule-name">name</a>, <a href="#my_rule-first">first</a>, <a href="#my_rule-second">second</a>)
-</pre>
-
-This is my rule. It does stuff.
-
-**ATTRIBUTES**
-
-
-| Name | Description | Type | Mandatory | Default |
-| :------------- | :------------- | :------------- | :------------- | :------------- |
-| <a id="my_rule-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
-| <a id="my_rule-first"></a>first | first my_rule doc string | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
-| <a id="my_rule-second"></a>second | - | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | required | |
-
-
diff --git a/test/testdata/generated_bzl_test/input.bzl b/test/testdata/generated_bzl_test/input.bzl
deleted file mode 100644
index bad15f6..0000000
--- a/test/testdata/generated_bzl_test/input.bzl
+++ /dev/null
@@ -1,16 +0,0 @@
-"""A direct dependency file of the input file."""
-
-load(":testdata/generated_bzl_test/dep.bzl", "my_rule_impl")
-
-my_rule = rule(
- implementation = my_rule_impl,
- doc = "This is my rule. It does stuff.",
- attrs = {
- "first": attr.label(
- mandatory = True,
- doc = "first my_rule doc string",
- allow_single_file = True,
- ),
- "second": attr.string_dict(mandatory = True),
- },
-)
diff --git a/test/testdata/html_tables_template_test/golden.md b/test/testdata/html_tables_template_test/golden.md
index e933347..5ac16a8 100755..100644
--- a/test/testdata/html_tables_template_test/golden.md
+++ b/test/testdata/html_tables_template_test/golden.md
@@ -217,7 +217,7 @@ A unique name for this target.
<td><code>first</code></td>
<td>
-<a href="https://bazel.build/concepts/labels">Label</a>; required
+Integer; required
</td>
</tr>
diff --git a/test/testdata/html_tables_template_test/input.bzl b/test/testdata/html_tables_template_test/input.bzl
index 42ca4ac..08c6689 100644
--- a/test/testdata/html_tables_template_test/input.bzl
+++ b/test/testdata/html_tables_template_test/input.bzl
@@ -42,7 +42,7 @@ example_aspect = aspect(
doc = "Small example of aspect using a markdown template.",
attr_aspects = ["deps", "attr_aspect"],
attrs = {
- "first": attr.label(mandatory = True, allow_single_file = True),
+ "first": attr.int(mandatory = True),
"second": attr.string(doc = "This is the second attribute."),
},
)
diff --git a/test/testdata/input_template_test/golden.md b/test/testdata/input_template_test/golden.md
index 90e9a5d..a7a78bc 100755..100644
--- a/test/testdata/input_template_test/golden.md
+++ b/test/testdata/input_template_test/golden.md
@@ -132,7 +132,7 @@ This is my aspect. It does stuff.
</p>
<b>
<code>first</code>
- <a href="https://bazel.build/concepts/labels">Label</a>; required
+ String; required
</b>
diff --git a/test/testdata/input_template_test/input.bzl b/test/testdata/input_template_test/input.bzl
index d47d025..4de3dd4 100644
--- a/test/testdata/input_template_test/input.bzl
+++ b/test/testdata/input_template_test/input.bzl
@@ -46,6 +46,6 @@ my_aspect = aspect(
doc = "This is my aspect. It does stuff.",
attr_aspects = ["deps", "attr_aspect"],
attrs = {
- "first": attr.label(mandatory = True, allow_single_file = True),
+ "first": attr.string(mandatory = True),
},
)
diff --git a/test/testdata/java_basic_test/golden.md b/test/testdata/java_basic_test/golden.md
index a6d0818..e98bbd6 100755..100644
--- a/test/testdata/java_basic_test/golden.md
+++ b/test/testdata/java_basic_test/golden.md
@@ -19,7 +19,7 @@ This rule does java-related things.
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="java_related_rule-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
| <a id="java_related_rule-first"></a>first | - | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
-| <a id="java_related_rule-fourth"></a>fourth | - | Boolean | optional | <code>False</code> |
+| <a id="java_related_rule-fourth"></a>fourth | - | Boolean | optional | `False` |
| <a id="java_related_rule-second"></a>second | - | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | required | |
| <a id="java_related_rule-third"></a>third | - | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
diff --git a/test/testdata/java_basic_test/input.bzl b/test/testdata/java_basic_test/input.bzl
index d61141f..0f42592 100644
--- a/test/testdata/java_basic_test/input.bzl
+++ b/test/testdata/java_basic_test/input.bzl
@@ -3,7 +3,6 @@
def exercise_the_api():
var1 = java_common.JavaRuntimeInfo # @unused
var2 = JavaInfo # @unused
- var3 = java_proto_common # @unused
exercise_the_api()
diff --git a/test/testdata/local_repository_test/input.bzl b/test/testdata/local_repository_test/input.bzl
index fdd686b..7504183 100644
--- a/test/testdata/local_repository_test/input.bzl
+++ b/test/testdata/local_repository_test/input.bzl
@@ -1,6 +1,6 @@
"""A test that verifies documenting functions in an input file under a local_repository."""
-load("@io_bazel_stardoc//test/testdata/fakedeps:dep.bzl", "give_me_five")
+load("@io_bazel_stardoc//test:testdata/fakedeps/dep.bzl", "give_me_five")
def min(integers):
"""Returns the minimum of given elements.
diff --git a/test/testdata/macro_kwargs_test/golden.md b/test/testdata/macro_kwargs_test/golden.md
index d2af867..1a9df5b 100755..100644
--- a/test/testdata/macro_kwargs_test/golden.md
+++ b/test/testdata/macro_kwargs_test/golden.md
@@ -44,7 +44,7 @@ Not much else to say.
| Name | Description | Default Value |
| :------------- | :------------- | :------------- |
| <a id="macro_with_both-name"></a>name | The name of the test rule. | none |
-| <a id="macro_with_both-number"></a>number | Some number used for important things | <code>3</code> |
+| <a id="macro_with_both-number"></a>number | Some number used for important things | `3` |
| <a id="macro_with_both-args"></a>args | Other arguments to include | none |
| <a id="macro_with_both-kwargs"></a>kwargs | Other attributes to include | none |
@@ -77,7 +77,7 @@ vel mollis eros pellentesque.
| :------------- | :------------- | :------------- |
| <a id="macro_with_kwargs-name"></a>name | The name of the test rule. | none |
| <a id="macro_with_kwargs-config"></a>config | Config to use for my macro | none |
-| <a id="macro_with_kwargs-deps"></a>deps | List of my macro's dependencies | <code>[]</code> |
+| <a id="macro_with_kwargs-deps"></a>deps | List of my macro's dependencies | `[]` |
| <a id="macro_with_kwargs-kwargs"></a>kwargs | Other attributes to include | none |
**RETURNS**
diff --git a/test/testdata/misc_apis_test/golden.md b/test/testdata/misc_apis_test/golden.md
index 7b94d9f..3e3ef3c 100755..100644
--- a/test/testdata/misc_apis_test/golden.md
+++ b/test/testdata/misc_apis_test/golden.md
@@ -7,7 +7,7 @@
## my_rule
<pre>
-my_rule(<a href="#my_rule-name">name</a>, <a href="#my_rule-deps">deps</a>, <a href="#my_rule-extra_arguments">extra_arguments</a>, <a href="#my_rule-out">out</a>, <a href="#my_rule-src">src</a>, <a href="#my_rule-tool">tool</a>)
+my_rule(<a href="#my_rule-name">name</a>, <a href="#my_rule-deps">deps</a>, <a href="#my_rule-src">src</a>, <a href="#my_rule-out">out</a>, <a href="#my_rule-extra_arguments">extra_arguments</a>, <a href="#my_rule-tool">tool</a>)
</pre>
This rule exercises some of the build API.
@@ -18,11 +18,11 @@ This rule exercises some of the build API.
| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="my_rule-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
-| <a id="my_rule-deps"></a>deps | A list of dependencies. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | <code>[]</code> |
-| <a id="my_rule-extra_arguments"></a>extra_arguments | - | List of strings | optional | <code>[]</code> |
+| <a id="my_rule-deps"></a>deps | A list of dependencies. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
+| <a id="my_rule-src"></a>src | The source file. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
| <a id="my_rule-out"></a>out | The output file. | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
-| <a id="my_rule-src"></a>src | The source file. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>None</code> |
-| <a id="my_rule-tool"></a>tool | The location of the tool to use. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>//foo/bar/baz:target</code> |
+| <a id="my_rule-extra_arguments"></a>extra_arguments | - | List of strings | optional | `[]` |
+| <a id="my_rule-tool"></a>tool | The location of the tool to use. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `"@io_bazel_stardoc//foo/bar/baz:target"` |
<a id="MyInfo"></a>
diff --git a/test/testdata/misc_apis_test/legacy_golden.md b/test/testdata/misc_apis_test/legacy_golden.md
new file mode 100644
index 0000000..1a6b867
--- /dev/null
+++ b/test/testdata/misc_apis_test/legacy_golden.md
@@ -0,0 +1,76 @@
+<!-- Generated with Stardoc: http://skydoc.bazel.build -->
+
+
+
+<a id="my_rule"></a>
+
+## my_rule
+
+<pre>
+my_rule(<a href="#my_rule-name">name</a>, <a href="#my_rule-deps">deps</a>, <a href="#my_rule-src">src</a>, <a href="#my_rule-out">out</a>, <a href="#my_rule-extra_arguments">extra_arguments</a>, <a href="#my_rule-tool">tool</a>)
+</pre>
+
+This rule exercises some of the build API.
+
+**ATTRIBUTES**
+
+
+| Name | Description | Type | Mandatory | Default |
+| :------------- | :------------- | :------------- | :------------- | :------------- |
+| <a id="my_rule-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
+| <a id="my_rule-deps"></a>deps | A list of dependencies. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
+| <a id="my_rule-src"></a>src | The source file. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
+| <a id="my_rule-out"></a>out | The output file. | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
+| <a id="my_rule-extra_arguments"></a>extra_arguments | - | List of strings | optional | `[]` |
+| <a id="my_rule-tool"></a>tool | The location of the tool to use. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `//foo/bar/baz:target` |
+
+
+<a id="MyInfo"></a>
+
+## MyInfo
+
+<pre>
+MyInfo(<a href="#MyInfo-foo">foo</a>, <a href="#MyInfo-bar">bar</a>)
+</pre>
+
+
+
+**FIELDS**
+
+
+| Name | Description |
+| :------------- | :------------- |
+| <a id="MyInfo-foo"></a>foo | Something foo-related. |
+| <a id="MyInfo-bar"></a>bar | Something bar-related. |
+
+
+<a id="exercise_the_api"></a>
+
+## exercise_the_api
+
+<pre>
+exercise_the_api()
+</pre>
+
+
+
+
+
+<a id="my_rule_impl"></a>
+
+## my_rule_impl
+
+<pre>
+my_rule_impl(<a href="#my_rule_impl-ctx">ctx</a>)
+</pre>
+
+
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="my_rule_impl-ctx"></a>ctx | <p align="center"> - </p> | none |
+
+
diff --git a/test/testdata/module_extension_test/golden.md b/test/testdata/module_extension_test/golden.md
new file mode 100644
index 0000000..addfc77
--- /dev/null
+++ b/test/testdata/module_extension_test/golden.md
@@ -0,0 +1,45 @@
+<!-- Generated with Stardoc: http://skydoc.bazel.build -->
+
+Minimal example of a .bzl file defining a module extension.
+
+<a id="my_ext"></a>
+
+## my_ext
+
+<pre>
+my_ext = use_extension("@io_bazel_stardoc//test:testdata/module_extension_test/input.bzl", "my_ext")
+my_ext.install(<a href="#my_ext.install-artifacts">artifacts</a>)
+my_ext.artifact(<a href="#my_ext.artifact-artifact">artifact</a>, <a href="#my_ext.artifact-group">group</a>)
+</pre>
+
+Minimal example of a module extension.
+
+
+**TAG CLASSES**
+
+<a id="my_ext.install"></a>
+
+### install
+
+Install tag
+
+**Attributes**
+
+| Name | Description | Type | Mandatory | Default |
+| :------------- | :------------- | :------------- | :------------- | :------------- |
+| <a id="my_ext.install-artifacts"></a>artifacts | Install artifacts | List of strings | optional | `[]` |
+
+<a id="my_ext.artifact"></a>
+
+### artifact
+
+Artifact tag
+
+**Attributes**
+
+| Name | Description | Type | Mandatory | Default |
+| :------------- | :------------- | :------------- | :------------- | :------------- |
+| <a id="my_ext.artifact-artifact"></a>artifact | Artifact | String | required | |
+| <a id="my_ext.artifact-group"></a>group | Group name | String | optional | `"my_group"` |
+
+
diff --git a/test/testdata/module_extension_test/input.bzl b/test/testdata/module_extension_test/input.bzl
new file mode 100644
index 0000000..ceffee4
--- /dev/null
+++ b/test/testdata/module_extension_test/input.bzl
@@ -0,0 +1,38 @@
+"""Minimal example of a .bzl file defining a module extension."""
+
+# buildifier: disable=unused-variable
+def _impl(module_ctx):
+ """No-op"""
+ pass
+
+_artifact = tag_class(
+ doc = "Artifact tag",
+ attrs = {
+ "group": attr.string(
+ doc = "Group name",
+ default = "my_group",
+ ),
+ "artifact": attr.string(
+ doc = "Artifact",
+ mandatory = True,
+ ),
+ },
+)
+
+_install = tag_class(
+ doc = "Install tag",
+ attrs = {
+ "artifacts": attr.string_list(
+ doc = "Install artifacts",
+ ),
+ },
+)
+
+my_ext = module_extension(
+ implementation = _impl,
+ doc = "Minimal example of a module extension.",
+ tag_classes = {
+ "install": _install,
+ "artifact": _artifact,
+ },
+)
diff --git a/test/testdata/multi_level_namespace_test/golden.md b/test/testdata/multi_level_namespace_test/golden.md
index 85791c9..3e753c0 100755..100644
--- a/test/testdata/multi_level_namespace_test/golden.md
+++ b/test/testdata/multi_level_namespace_test/golden.md
@@ -2,12 +2,24 @@
A test that verifies documenting a multi-leveled namespace of functions.
-<a id="my_namespace.min"></a>
+<a id="my_namespace.foo.bar.baz"></a>
-## my_namespace.min
+## my_namespace.foo.bar.baz
<pre>
-my_namespace.min(<a href="#my_namespace.min-integers">integers</a>)
+my_namespace.foo.bar.baz()
+</pre>
+
+This function does nothing.
+
+
+
+<a id="my_namespace.math.min"></a>
+
+## my_namespace.math.min
+
+<pre>
+my_namespace.math.min(<a href="#my_namespace.math.min-integers">integers</a>)
</pre>
Returns the minimum of given elements.
@@ -17,19 +29,19 @@ Returns the minimum of given elements.
| Name | Description | Default Value |
| :------------- | :------------- | :------------- |
-| <a id="my_namespace.min-integers"></a>integers | A list of integers. Must not be empty. | none |
+| <a id="my_namespace.math.min-integers"></a>integers | A list of integers. Must not be empty. | none |
**RETURNS**
The minimum integer in the given list.
-<a id="my_namespace.math.min"></a>
+<a id="my_namespace.min"></a>
-## my_namespace.math.min
+## my_namespace.min
<pre>
-my_namespace.math.min(<a href="#my_namespace.math.min-integers">integers</a>)
+my_namespace.min(<a href="#my_namespace.min-integers">integers</a>)
</pre>
Returns the minimum of given elements.
@@ -39,19 +51,19 @@ Returns the minimum of given elements.
| Name | Description | Default Value |
| :------------- | :------------- | :------------- |
-| <a id="my_namespace.math.min-integers"></a>integers | A list of integers. Must not be empty. | none |
+| <a id="my_namespace.min-integers"></a>integers | A list of integers. Must not be empty. | none |
**RETURNS**
The minimum integer in the given list.
-<a id="my_namespace.foo.bar.baz"></a>
+<a id="my_namespace.one.three.does_nothing"></a>
-## my_namespace.foo.bar.baz
+## my_namespace.one.three.does_nothing
<pre>
-my_namespace.foo.bar.baz()
+my_namespace.one.three.does_nothing()
</pre>
This function does nothing.
@@ -80,15 +92,3 @@ Returns the minimum of given elements.
The minimum integer in the given list.
-<a id="my_namespace.one.three.does_nothing"></a>
-
-## my_namespace.one.three.does_nothing
-
-<pre>
-my_namespace.one.three.does_nothing()
-</pre>
-
-This function does nothing.
-
-
-
diff --git a/test/testdata/multi_level_namespace_test_with_whitelist/golden.md b/test/testdata/multi_level_namespace_test_with_allowlist/golden.md
index 1ca1608..f35b10d 100644
--- a/test/testdata/multi_level_namespace_test_with_whitelist/golden.md
+++ b/test/testdata/multi_level_namespace_test_with_allowlist/golden.md
@@ -1,15 +1,15 @@
<!-- Generated with Stardoc: http://skydoc.bazel.build -->
-A test that verifies documenting a multi-leveled namespace of functions with whitelist symbols.
-The whitelist symbols should cause everything in my_namespace to to be documented, but only a
+A test that verifies documenting a multi-leveled namespace of functions with allowlist symbols.
+The allowlist symbols should cause everything in my_namespace to to be documented, but only a
specific symbol in other_namespace to be documented.
-<a id="my_namespace.min"></a>
+<a id="my_namespace.math.min"></a>
-## my_namespace.min
+## my_namespace.math.min
<pre>
-my_namespace.min(<a href="#my_namespace.min-integers">integers</a>)
+my_namespace.math.min(<a href="#my_namespace.math.min-integers">integers</a>)
</pre>
Returns the minimum of given elements.
@@ -19,15 +19,15 @@ Returns the minimum of given elements.
| Name | Description | Default Value |
| :------------- | :------------- | :------------- |
-| <a id="my_namespace.min-integers"></a>integers | <p align="center"> - </p> | none |
+| <a id="my_namespace.math.min-integers"></a>integers | <p align="center"> - </p> | none |
-<a id="my_namespace.math.min"></a>
+<a id="my_namespace.min"></a>
-## my_namespace.math.min
+## my_namespace.min
<pre>
-my_namespace.math.min(<a href="#my_namespace.math.min-integers">integers</a>)
+my_namespace.min(<a href="#my_namespace.min-integers">integers</a>)
</pre>
Returns the minimum of given elements.
@@ -37,7 +37,7 @@ Returns the minimum of given elements.
| Name | Description | Default Value |
| :------------- | :------------- | :------------- |
-| <a id="my_namespace.math.min-integers"></a>integers | <p align="center"> - </p> | none |
+| <a id="my_namespace.min-integers"></a>integers | <p align="center"> - </p> | none |
<a id="other_namespace.foo.nothing"></a>
diff --git a/test/testdata/multi_level_namespace_test_with_whitelist/input.bzl b/test/testdata/multi_level_namespace_test_with_allowlist/input.bzl
index f070309..5146d11 100644
--- a/test/testdata/multi_level_namespace_test_with_whitelist/input.bzl
+++ b/test/testdata/multi_level_namespace_test_with_allowlist/input.bzl
@@ -1,5 +1,5 @@
-"""A test that verifies documenting a multi-leveled namespace of functions with whitelist symbols.
-The whitelist symbols should cause everything in my_namespace to to be documented, but only a
+"""A test that verifies documenting a multi-leveled namespace of functions with allowlist symbols.
+The allowlist symbols should cause everything in my_namespace to to be documented, but only a
specific symbol in other_namespace to be documented."""
def _min(integers):
diff --git a/test/testdata/multiple_files_test/golden.md b/test/testdata/multiple_files_test/golden.md
index 0fab337..0fab337 100755..100644
--- a/test/testdata/multiple_files_test/golden.md
+++ b/test/testdata/multiple_files_test/golden.md
diff --git a/test/testdata/multiple_rules_test/golden.md b/test/testdata/multiple_rules_test/golden.md
index 085fec8..085fec8 100755..100644
--- a/test/testdata/multiple_rules_test/golden.md
+++ b/test/testdata/multiple_rules_test/golden.md
diff --git a/test/testdata/namespace_test/golden.md b/test/testdata/namespace_test/golden.md
index f840fcf..6e4c453 100755..100644
--- a/test/testdata/namespace_test/golden.md
+++ b/test/testdata/namespace_test/golden.md
@@ -21,48 +21,48 @@ Asserts the two given lists are not empty.
| <a id="my_namespace.assert_non_empty-other_list"></a>other_list | The second list | none |
-<a id="my_namespace.min"></a>
+<a id="my_namespace.join_strings"></a>
-## my_namespace.min
+## my_namespace.join_strings
<pre>
-my_namespace.min(<a href="#my_namespace.min-integers">integers</a>)
+my_namespace.join_strings(<a href="#my_namespace.join_strings-strings">strings</a>, <a href="#my_namespace.join_strings-delimiter">delimiter</a>)
</pre>
-Returns the minimum of given elements.
+Joins the given strings with a delimiter.
**PARAMETERS**
| Name | Description | Default Value |
| :------------- | :------------- | :------------- |
-| <a id="my_namespace.min-integers"></a>integers | A list of integers. Must not be empty. | none |
+| <a id="my_namespace.join_strings-strings"></a>strings | A list of strings to join. | none |
+| <a id="my_namespace.join_strings-delimiter"></a>delimiter | The delimiter to use | `", "` |
**RETURNS**
-The minimum integer in the given list.
+The joined string.
-<a id="my_namespace.join_strings"></a>
+<a id="my_namespace.min"></a>
-## my_namespace.join_strings
+## my_namespace.min
<pre>
-my_namespace.join_strings(<a href="#my_namespace.join_strings-strings">strings</a>, <a href="#my_namespace.join_strings-delimiter">delimiter</a>)
+my_namespace.min(<a href="#my_namespace.min-integers">integers</a>)
</pre>
-Joins the given strings with a delimiter.
+Returns the minimum of given elements.
**PARAMETERS**
| Name | Description | Default Value |
| :------------- | :------------- | :------------- |
-| <a id="my_namespace.join_strings-strings"></a>strings | A list of strings to join. | none |
-| <a id="my_namespace.join_strings-delimiter"></a>delimiter | The delimiter to use | <code>", "</code> |
+| <a id="my_namespace.min-integers"></a>integers | A list of integers. Must not be empty. | none |
**RETURNS**
-The joined string.
+The minimum integer in the given list.
diff --git a/test/testdata/proto_format_test/golden.binaryproto b/test/testdata/proto_format_test/golden.binaryproto
new file mode 100644
index 0000000..ff1d54b
--- /dev/null
+++ b/test/testdata/proto_format_test/golden.binaryproto
@@ -0,0 +1,21 @@
+
+Õ
+
+my_exampleSmall example of rule.*
+nameA unique name for this target. 7
+uselessThis argument will be ignored.2
+"ignoreme""J
+
+my_example<@io_bazel_stardoc//test:testdata/proto_format_test/input.bzlÞ
+example$Stores information about an example.
+fooA string representing foo
+barA string representing bar
+bazA string representing baz"G
+example<@io_bazel_stardoc//test:testdata/proto_format_test/input.bzl–
+check_function%
+fooA unique name for this rule. ŒRuns some checks on the given function parameter.
+
+This rule runs checks on a given function parameter.
+Use `bazel build` to run the check.
+2N
+check_function<@io_bazel_stardoc//test:testdata/proto_format_test/input.bzl* Input file for proto format test2<@io_bazel_stardoc//test:testdata/proto_format_test/input.bzl \ No newline at end of file
diff --git a/test/testdata/proto_format_test/golden.raw b/test/testdata/proto_format_test/legacy_golden.binaryproto
index a93d367..d158834 100644
--- a/test/testdata/proto_format_test/golden.raw
+++ b/test/testdata/proto_format_test/legacy_golden.binaryproto
Binary files differ
diff --git a/test/testdata/provider_basic_test/golden.md b/test/testdata/provider_basic_test/golden.md
index a9d76bf..7029581 100755..100644
--- a/test/testdata/provider_basic_test/golden.md
+++ b/test/testdata/provider_basic_test/golden.md
@@ -17,8 +17,8 @@ Stores information about a foo.
| Name | Description |
| :------------- | :------------- |
-| <a id="MyFooInfo-bar"></a>bar | (Undocumented) |
-| <a id="MyFooInfo-baz"></a>baz | (Undocumented) |
+| <a id="MyFooInfo-bar"></a>bar | - |
+| <a id="MyFooInfo-baz"></a>baz | - |
<a id="MyPoorlyDocumentedInfo"></a>
@@ -43,17 +43,16 @@ MyPoorlyDocumentedInfo()
MyVeryDocumentedInfo(<a href="#MyVeryDocumentedInfo-favorite_food">favorite_food</a>, <a href="#MyVeryDocumentedInfo-favorite_color">favorite_color</a>)
</pre>
-
A provider with some really neat documentation.
-Look on my works, ye mighty, and despair!
+Look on my works, ye mighty, and despair!
**FIELDS**
| Name | Description |
| :------------- | :------------- |
-| <a id="MyVeryDocumentedInfo-favorite_food"></a>favorite_food | A string representing my favorite food |
+| <a id="MyVeryDocumentedInfo-favorite_food"></a>favorite_food | A string representing my favorite food<br><br>Expected to be delicious. |
| <a id="MyVeryDocumentedInfo-favorite_color"></a>favorite_color | A string representing my favorite color |
diff --git a/test/testdata/provider_basic_test/input.bzl b/test/testdata/provider_basic_test/input.bzl
index bb76c0d..cc3068d 100644
--- a/test/testdata/provider_basic_test/input.bzl
+++ b/test/testdata/provider_basic_test/input.bzl
@@ -10,11 +10,21 @@ MyFooInfo = provider(
# buildifier: disable=unsorted-dict-items
MyVeryDocumentedInfo = provider(
doc = """
-A provider with some really neat documentation.
-Look on my works, ye mighty, and despair!
-""",
+ A provider with some really neat documentation.
+
+ Look on my works, ye mighty, and despair!
+ """,
fields = {
- "favorite_food": "A string representing my favorite food",
+ "favorite_food": """
+ A string representing my favorite food
+
+ Expected to be delicious.
+ """,
"favorite_color": "A string representing my favorite color",
},
)
+
+named_providers_are_hashable = {
+ MyFooInfo: "MyFooInfo is hashable",
+ MyVeryDocumentedInfo: "So is MyVeryDocumentedInfo",
+}
diff --git a/test/testdata/provider_basic_test/legacy_golden.md b/test/testdata/provider_basic_test/legacy_golden.md
new file mode 100644
index 0000000..38dd0f6
--- /dev/null
+++ b/test/testdata/provider_basic_test/legacy_golden.md
@@ -0,0 +1,58 @@
+<!-- Generated with Stardoc: http://skydoc.bazel.build -->
+
+
+
+<a id="MyFooInfo"></a>
+
+## MyFooInfo
+
+<pre>
+MyFooInfo(<a href="#MyFooInfo-bar">bar</a>, <a href="#MyFooInfo-baz">baz</a>)
+</pre>
+
+Stores information about a foo.
+
+**FIELDS**
+
+
+| Name | Description |
+| :------------- | :------------- |
+| <a id="MyFooInfo-bar"></a>bar | (Undocumented) |
+| <a id="MyFooInfo-baz"></a>baz | (Undocumented) |
+
+
+<a id="MyPoorlyDocumentedInfo"></a>
+
+## MyPoorlyDocumentedInfo
+
+<pre>
+MyPoorlyDocumentedInfo()
+</pre>
+
+
+
+**FIELDS**
+
+
+
+<a id="MyVeryDocumentedInfo"></a>
+
+## MyVeryDocumentedInfo
+
+<pre>
+MyVeryDocumentedInfo(<a href="#MyVeryDocumentedInfo-favorite_food">favorite_food</a>, <a href="#MyVeryDocumentedInfo-favorite_color">favorite_color</a>)
+</pre>
+
+A provider with some really neat documentation.
+
+Look on my works, ye mighty, and despair!
+
+**FIELDS**
+
+
+| Name | Description |
+| :------------- | :------------- |
+| <a id="MyVeryDocumentedInfo-favorite_food"></a>favorite_food | A string representing my favorite food<br><br> Expected to be delicious. |
+| <a id="MyVeryDocumentedInfo-favorite_color"></a>favorite_color | A string representing my favorite color |
+
+
diff --git a/test/testdata/providers_for_attributes_test/golden.md b/test/testdata/providers_for_attributes_test/golden.md
index 24ebf27..a427cf2 100755..100644
--- a/test/testdata/providers_for_attributes_test/golden.md
+++ b/test/testdata/providers_for_attributes_test/golden.md
@@ -18,12 +18,12 @@ This rule does things.
| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="my_rule-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
-| <a id="my_rule-fifth"></a>fifth | - | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>None</code> |
-| <a id="my_rule-first"></a>first | this is the first attribute. | <a href="https://bazel.build/rules/lib/dict">Dictionary: Label -> String</a> | optional | <code>{}</code> |
-| <a id="my_rule-fourth"></a>fourth | - | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>None</code> |
-| <a id="my_rule-second"></a>second | - | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | <code>[]</code> |
-| <a id="my_rule-sixth"></a>sixth | - | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>None</code> |
-| <a id="my_rule-third"></a>third | - | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>None</code> |
+| <a id="my_rule-fifth"></a>fifth | - | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
+| <a id="my_rule-first"></a>first | this is the first attribute. | <a href="https://bazel.build/rules/lib/dict">Dictionary: Label -> String</a> | optional | `{}` |
+| <a id="my_rule-fourth"></a>fourth | - | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
+| <a id="my_rule-second"></a>second | - | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
+| <a id="my_rule-sixth"></a>sixth | - | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
+| <a id="my_rule-third"></a>third | - | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
<a id="MyProviderInfo"></a>
diff --git a/test/testdata/pure_markdown_template_test/golden.md b/test/testdata/pure_markdown_template_test/golden.md
new file mode 100644
index 0000000..62a9327
--- /dev/null
+++ b/test/testdata/pure_markdown_template_test/golden.md
@@ -0,0 +1,92 @@
+<!-- Generated with Stardoc: http://skydoc.bazel.build -->
+
+Input file for markdown template test
+
+<a id="example_rule"></a>
+
+## example_rule
+
+<pre>
+example_rule(<a href="#example_rule-name">name</a>, <a href="#example_rule-first">first</a>, <a href="#example_rule-second">second</a>)
+</pre>
+
+Small example of rule using a markdown template.
+
+**ATTRIBUTES**
+
+
+| Name | Description | Type | Mandatory | Default |
+| :------------- | :------------- | :------------- | :------------- | :------------- |
+| <a id="example_rule-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
+| <a id="example_rule-first"></a>first | This is the first attribute | String | optional | `""` |
+| <a id="example_rule-second"></a>second | - | Integer | optional | `2` |
+
+
+<a id="ExampleProviderInfo"></a>
+
+## ExampleProviderInfo
+
+<pre>
+ExampleProviderInfo(<a href="#ExampleProviderInfo-foo">foo</a>, <a href="#ExampleProviderInfo-bar">bar</a>, <a href="#ExampleProviderInfo-baz">baz</a>)
+</pre>
+
+Small example of provider using a markdown template.
+
+**FIELDS**
+
+
+| Name | Description |
+| :------------- | :------------- |
+| <a id="ExampleProviderInfo-foo"></a>foo | A string representing foo |
+| <a id="ExampleProviderInfo-bar"></a>bar | A string representing bar |
+| <a id="ExampleProviderInfo-baz"></a>baz | A string representing baz |
+
+
+<a id="example_function"></a>
+
+## example_function
+
+<pre>
+example_function(<a href="#example_function-foo">foo</a>, <a href="#example_function-bar">bar</a>)
+</pre>
+
+Small example of function using a markdown template.
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="example_function-foo"></a>foo | This parameter does foo related things. | none |
+| <a id="example_function-bar"></a>bar | This parameter does bar related things.<br><br>For example, it does things that require **multiple paragraphs** to explain.<br><br>Note: we should preserve the nested indent in the following code:<br><br><pre><code class="language-json">{&#10; "key": "value"&#10;}</code></pre> | `"bar"` |
+
+
+<a id="example_aspect"></a>
+
+## example_aspect
+
+<pre>
+example_aspect(<a href="#example_aspect-name">name</a>, <a href="#example_aspect-first">first</a>, <a href="#example_aspect-second">second</a>)
+</pre>
+
+Small example of aspect using a markdown template.
+
+**ASPECT ATTRIBUTES**
+
+
+| Name | Type |
+| :------------- | :------------- |
+| deps| String |
+| attr_aspect| String |
+
+
+**ATTRIBUTES**
+
+
+| Name | Description | Type | Mandatory | Default |
+| :------------- | :------------- | :------------- | :------------- | :------------- |
+| <a id="example_aspect-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
+| <a id="example_aspect-first"></a>first | - | String | required | |
+| <a id="example_aspect-second"></a>second | This is the second attribute. | String | optional | `""` |
+
+
diff --git a/test/testdata/pure_markdown_template_test/input.bzl b/test/testdata/pure_markdown_template_test/input.bzl
new file mode 100644
index 0000000..61d185d
--- /dev/null
+++ b/test/testdata/pure_markdown_template_test/input.bzl
@@ -0,0 +1,57 @@
+"""Input file for markdown template test"""
+
+# buildifier: disable=unused-variable
+def example_function(foo, bar = "bar"):
+ """Small example of function using a markdown template.
+
+ Args:
+ foo: This parameter does foo related things.
+ bar: This parameter does bar related things.
+
+ For example, it does things that require **multiple paragraphs** to explain.
+
+ Note: we should preserve the nested indent in the following code:
+
+ ```json
+ {
+ "key": "value"
+ }
+ ```
+ """
+ pass
+
+ExampleProviderInfo = provider(
+ doc = "Small example of provider using a markdown template.",
+ fields = {
+ "foo": "A string representing foo",
+ "bar": "A string representing bar",
+ "baz": "A string representing baz",
+ },
+)
+
+# buildifier: disable=unused-variable
+def _rule_impl(ctx):
+ return []
+
+example_rule = rule(
+ implementation = _rule_impl,
+ doc = "Small example of rule using a markdown template.",
+ attrs = {
+ "first": attr.string(doc = "This is the first attribute"),
+ "second": attr.int(default = 2),
+ },
+)
+
+# buildifier: disable=unused-variable
+def _aspect_impl(ctx):
+ return []
+
+example_aspect = aspect(
+ implementation = _aspect_impl,
+ doc = "Small example of aspect using a markdown template.",
+ attr_aspects = ["deps", "attr_aspect"],
+ attrs = {
+ "first": attr.string(mandatory = True),
+ "second": attr.string(doc = "This is the second attribute."),
+ },
+)
diff --git a/test/testdata/py_rule_test/golden.md b/test/testdata/py_rule_test/golden.md
index 0550bf9..d2a8394 100755..100644
--- a/test/testdata/py_rule_test/golden.md
+++ b/test/testdata/py_rule_test/golden.md
@@ -18,11 +18,11 @@ This rule does python-related things.
| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="py_related_rule-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
-| <a id="py_related_rule-fifth"></a>fifth | Hey look, its the fifth thing! | Boolean | optional | <code>True</code> |
+| <a id="py_related_rule-fifth"></a>fifth | Hey look, its the fifth thing! | Boolean | optional | `True` |
| <a id="py_related_rule-first"></a>first | this is the first doc string! | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
-| <a id="py_related_rule-fourth"></a>fourth | the fourth doc string. | Boolean | optional | <code>False</code> |
+| <a id="py_related_rule-fourth"></a>fourth | the fourth doc string. | Boolean | optional | `False` |
| <a id="py_related_rule-second"></a>second | - | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | required | |
-| <a id="py_related_rule-sixth"></a>sixth | it's the sixth thing. | List of integers | optional | <code>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]</code> |
+| <a id="py_related_rule-sixth"></a>sixth | it's the sixth thing. | List of integers | optional | `[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]` |
| <a id="py_related_rule-third"></a>third | - | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
diff --git a/test/testdata/repo_rules_test/golden.md b/test/testdata/repo_rules_test/golden.md
index 87391e3..de907c7 100755..100644
--- a/test/testdata/repo_rules_test/golden.md
+++ b/test/testdata/repo_rules_test/golden.md
@@ -18,7 +18,13 @@ Minimal example of a repository rule.
| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="my_repo-name"></a>name | A unique name for this repository. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
-| <a id="my_repo-repo_mapping"></a>repo_mapping | A dictionary from local repository name to global repository name. This allows controls over workspace dependency resolution for dependencies of this repository.&lt;p&gt;For example, an entry <code>"@foo": "@bar"</code> declares that, for any time this repository depends on <code>@foo</code> (such as a dependency on <code>@foo//some:target</code>, it should actually resolve that dependency within globally-declared <code>@bar</code> (<code>@bar//some:target</code>). | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | required | |
-| <a id="my_repo-useless"></a>useless | This argument will be ingored. You don't have to specify it, but you may. | String | optional | <code>"ignoreme"</code> |
+| <a id="my_repo-repo_mapping"></a>repo_mapping | In `WORKSPACE` context only: a dictionary from local repository name to global repository name. This allows controls over workspace dependency resolution for dependencies of this repository.<br><br>For example, an entry `"@foo": "@bar"` declares that, for any time this repository depends on `@foo` (such as a dependency on `@foo//some:target`, it should actually resolve that dependency within globally-declared `@bar` (`@bar//some:target`).<br><br>This attribute is _not_ supported in `MODULE.bazel` context (when invoking a repository rule inside a module extension's implementation function). | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | optional | |
+| <a id="my_repo-useless"></a>useless | This argument will be ignored.<br><br>You don't have to specify it, but you may. | String | optional | `"ignoreme"` |
+
+**ENVIRONMENT VARIABLES**
+
+This repository rule depends on the following environment variables:
+* `FOO_CC`
+* `BAR_PATH`
diff --git a/test/testdata/repo_rules_test/input.bzl b/test/testdata/repo_rules_test/input.bzl
index 023d92d..114c3bc 100644
--- a/test/testdata/repo_rules_test/input.bzl
+++ b/test/testdata/repo_rules_test/input.bzl
@@ -7,8 +7,12 @@ my_repo = repository_rule(
doc = "Minimal example of a repository rule.",
attrs = {
"useless": attr.string(
- doc = "This argument will be ingored. You don't have to specify it, but you may.",
+ doc = """This argument will be ignored.
+
+ You don't have to specify it, but you may.
+ """,
default = "ignoreme",
),
},
+ environ = ["FOO_CC", "BAR_PATH"],
)
diff --git a/test/testdata/repo_rules_test/legacy_golden.md b/test/testdata/repo_rules_test/legacy_golden.md
new file mode 100644
index 0000000..d705a32
--- /dev/null
+++ b/test/testdata/repo_rules_test/legacy_golden.md
@@ -0,0 +1,24 @@
+<!-- Generated with Stardoc: http://skydoc.bazel.build -->
+
+
+
+<a id="my_repo"></a>
+
+## my_repo
+
+<pre>
+my_repo(<a href="#my_repo-name">name</a>, <a href="#my_repo-repo_mapping">repo_mapping</a>, <a href="#my_repo-useless">useless</a>)
+</pre>
+
+Minimal example of a repository rule.
+
+**ATTRIBUTES**
+
+
+| Name | Description | Type | Mandatory | Default |
+| :------------- | :------------- | :------------- | :------------- | :------------- |
+| <a id="my_repo-name"></a>name | A unique name for this repository. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
+| <a id="my_repo-repo_mapping"></a>repo_mapping | A dictionary from local repository name to global repository name. This allows controls over workspace dependency resolution for dependencies of this repository.<p>For example, an entry `"@foo": "@bar"` declares that, for any time this repository depends on `@foo` (such as a dependency on `@foo//some:target`, it should actually resolve that dependency within globally-declared `@bar` (`@bar//some:target`). | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | required | |
+| <a id="my_repo-useless"></a>useless | This argument will be ignored.<br><br>You don't have to specify it, but you may. | String | optional | `"ignoreme"` |
+
+
diff --git a/test/testdata/same_level_file_test/golden.md b/test/testdata/same_level_file_test/golden.md
index 66b9a97..66b9a97 100755..100644
--- a/test/testdata/same_level_file_test/golden.md
+++ b/test/testdata/same_level_file_test/golden.md
diff --git a/test/testdata/simple_test/golden.md b/test/testdata/simple_test/golden.md
index b203bd2..a5a2e39 100755..100644
--- a/test/testdata/simple_test/golden.md
+++ b/test/testdata/simple_test/golden.md
@@ -19,7 +19,7 @@ This is my rule. It does stuff.
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="my_rule-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
| <a id="my_rule-first"></a>first | first doc string | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
-| <a id="my_rule-fourth"></a>fourth | fourth doc string | Boolean | optional | <code>False</code> |
+| <a id="my_rule-fourth"></a>fourth | fourth doc string | Boolean | optional | `False` |
| <a id="my_rule-second"></a>second | - | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | required | |
| <a id="my_rule-third"></a>third | - | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
diff --git a/test/testdata/struct_default_value_test/golden.md b/test/testdata/struct_default_value_test/golden.md
index 6d07214..38f9908 100755..100644
--- a/test/testdata/struct_default_value_test/golden.md
+++ b/test/testdata/struct_default_value_test/golden.md
@@ -18,10 +18,10 @@ Checks the default values of structs.
| Name | Description | Default Value |
| :------------- | :------------- | :------------- |
-| <a id="check_struct_default_values-struct_no_args"></a>struct_no_args | struct with no arguments | <code>struct()</code> |
-| <a id="check_struct_default_values-struct_arg"></a>struct_arg | struct with one argument | <code>struct(foo = "bar")</code> |
-| <a id="check_struct_default_values-struct_args"></a>struct_args | struct with multiple arguments | <code>struct(bar = "foo", foo = "bar")</code> |
-| <a id="check_struct_default_values-struct_int_args"></a>struct_int_args | struct with int arguments | <code>struct(one = 1, three = 3, two = 2)</code> |
-| <a id="check_struct_default_values-struct_struct_args"></a>struct_struct_args | struct with struct arguments | <code>struct(multiple = struct(one = 1, three = 3, two = 2), none = struct(), one = struct(foo = "bar"))</code> |
+| <a id="check_struct_default_values-struct_no_args"></a>struct_no_args | struct with no arguments | `struct()` |
+| <a id="check_struct_default_values-struct_arg"></a>struct_arg | struct with one argument | `struct(foo = "bar")` |
+| <a id="check_struct_default_values-struct_args"></a>struct_args | struct with multiple arguments | `struct(bar = "foo", foo = "bar")` |
+| <a id="check_struct_default_values-struct_int_args"></a>struct_int_args | struct with int arguments | `struct(one = 1, three = 3, two = 2)` |
+| <a id="check_struct_default_values-struct_struct_args"></a>struct_struct_args | struct with struct arguments | `struct(multiple = struct(one = 1, three = 3, two = 2), none = struct(), one = struct(foo = "bar"))` |
diff --git a/test/testdata/unknown_name_test/golden.md b/test/testdata/unknown_name_test/golden.md
index 8bbe43c..8bbe43c 100755..100644
--- a/test/testdata/unknown_name_test/golden.md
+++ b/test/testdata/unknown_name_test/golden.md
diff --git a/update-release-binary.sh b/update-release-binary.sh
index 1423fbf..bf1307a 100755
--- a/update-release-binary.sh
+++ b/update-release-binary.sh
@@ -28,15 +28,6 @@ cp bazel-bin/external/io_bazel/src/main/java/com/google/devtools/build/skydoc/sk
echo "** Stardoc copied."
-echo "** Building Renderer from source..."
-bazel build --java_language_version=11 @io_bazel//src/main/java/com/google/devtools/build/skydoc/renderer:renderer_deploy.jar
-
-echo "** Copying Renderer binary..."
-cp bazel-bin/external/io_bazel/src/main/java/com/google/devtools/build/skydoc/renderer/renderer_deploy.jar \
- stardoc/renderer_binary.jar
-
-echo "** Renderer copied."
-
echo "** Copying stardoc_output.proto from source..."
cp $(bazel info output_base)/external/io_bazel/src/main/java/com/google/devtools/build/skydoc/rendering/proto/stardoc_output.proto stardoc/proto/stardoc_output.proto
echo "** stardoc_output.proto copied."
diff --git a/update-stardoc-docs.sh b/update-stardoc-docs.sh
index 986f5c2..d4d7ce3 100755
--- a/update-stardoc-docs.sh
+++ b/update-stardoc-docs.sh
@@ -19,8 +19,11 @@
set -eu
+# Allow users to override the bazel command with e.g. bazelisk.
+: "${BAZEL:=bazel}"
+
echo "** Generating Stardoc documentation..."
-bazel build //stardoc:stardoc_doc.md
+${BAZEL} build //stardoc:stardoc_doc.md
echo "** Copying result to docs/stardoc_rule.md ..."
cp bazel-bin/stardoc/stardoc_doc.md docs/stardoc_rule.md
diff --git a/update-stardoc-tests.sh b/update-stardoc-tests.sh
index b01e39c..d0264d0 100755
--- a/update-stardoc-tests.sh
+++ b/update-stardoc-tests.sh
@@ -21,27 +21,80 @@
set -eu
+function run_buildozer () {
+ # buildozer uses return code 3 to signal a no-op, so we can't use "set -e"
+ set +e
+ buildozer "$@"
+ ret=$?
+ set -e
+ if [[ $ret != 0 && $ret != 3 ]]; then
+ return $ret
+ fi
+}
+
+# Allow users to override the bazel command with e.g. bazelisk.
+: "${BAZEL:=bazel}"
+
+echo "** Verifying Bazel version..."
+if ! ${BAZEL} build --experimental_enable_starlark_doc_extract &> /dev/null; then
+ echo >&2 "Please use a development version of Bazel, or Bazel 7 once it is released."
+ echo >&2 "For example: USE_BAZEL_VERSION=last_green BAZEL=bazelisk ./update-stardoc-tests.sh"
+ exit 1
+fi
+
# Some tests cannot be automatically regenerated using this script, as they don't fall under the normal
# golden test pattern
-EXCLUDED_TESTS="namespace_test_with_whitelist|proto_format_test|multi_level_namespace_test_with_whitelist|local_repository_test"
+EXCLUDED_TESTS="namespace_test_with_allowlist|multi_level_namespace_test_with_allowlist|local_repository_test"
echo "** Querying for tests..."
-regen_targets=$(bazel query //test:all | grep regenerate_with_jar | grep -vE "$EXCLUDED_TESTS")
+regen_legacy_targets=$(${BAZEL} query //test:all | grep regenerate_with_jar | grep -vE "_golden_stardoc|$EXCLUDED_TESTS")
+regen_starlark_doc_extract_targets=$(${BAZEL} query //test:all | grep regenerate_ | grep -vE "_legacy|_golden\.extract|$EXCLUDED_TESTS")
echo "** Building goldens..."
-bazel build $regen_targets
+${BAZEL} build $regen_legacy_targets $regen_starlark_doc_extract_targets
+
+echo "** Copying starlark_doc_extract goldens..."
+for regen_target in $regen_starlark_doc_extract_targets; do
+ base_target_name=$(echo $regen_target | sed 's/\/\/test://g')
+ testdata_pkg_name=$(echo $base_target_name | sed 's/regenerate_//g' | sed 's/_golden//g')
+ out_file="bazel-bin/test/${base_target_name}.out"
+ if [[ $regen_target == *"proto_format"* ]]; then
+ ext="binaryproto"
+ else
+ ext="md"
+ fi
+ golden="test/testdata/${testdata_pkg_name}/golden.${ext}"
+ cp "${out_file}" "${golden}"
+ chmod 644 "${golden}"
+done
-echo "** Copying goldens..."
-for regen_target in $regen_targets; do
+echo "** Copying legacy goldens..."
+for regen_target in $regen_legacy_targets; do
base_target_name=$(echo $regen_target | sed 's/\/\/test://g')
- testdata_pkg_name=$(echo $base_target_name | sed 's/regenerate_with_jar_//g' | sed 's/_golden//g')
+ testdata_pkg_name=$(echo $base_target_name | sed 's/regenerate_with_jar_//g' | sed 's/_legacy_golden//g')
out_file="bazel-bin/test/${base_target_name}.out"
- cp $out_file "test/testdata/${testdata_pkg_name}/golden.md"
+ if [[ $regen_target == *"proto_format"* ]]; then
+ ext="binaryproto"
+ else
+ ext="md"
+ fi
+ golden="test/testdata/${testdata_pkg_name}/golden.${ext}"
+ legacy_golden="test/testdata/${testdata_pkg_name}/legacy_golden.${ext}"
+ legacy_golden_target="${legacy_golden#test/}"
+ if diff "${out_file}" "${golden}" > /dev/null; then
+ # legacy_golden is no longer needed; we only need golden
+ [[ -e "${legacy_golden}" ]] && rm "${legacy_golden}"
+ run_buildozer "remove legacy_golden_file" "//test:${testdata_pkg_name}"
+ else
+ cp "${out_file}" "${legacy_golden}"
+ chmod 644 "${legacy_golden}"
+ run_buildozer "set legacy_golden_file \"${legacy_golden_target}\"" "//test:${testdata_pkg_name}"
+ fi
done
echo "** Files copied."
echo "Please note that not all golden files are correctly copied by this script."
echo "You may want to manually run:"
echo ""
-echo "bazel test //test:all"
+echo "${BAZEL} test //test:all"
echo ""
echo "...and manually update tests which are still broken."
diff --git a/version.bzl b/version.bzl
index 29e5337..9e7b7c6 100644
--- a/version.bzl
+++ b/version.bzl
@@ -13,4 +13,4 @@
# limitations under the License.
"""The version of Stardoc."""
-version = "0.5.3"
+version = "0.6.2"