Render *args / * / **kwargs properly in function summary line (#231)
Note that this requires Bazel 8 for an updated proto output from `starlark_doc_extract`.
Fixes #225
diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml
index 19a8766..c3ef4e5 100644
--- a/.bazelci/presubmit.yml
+++ b/.bazelci/presubmit.yml
@@ -98,5 +98,15 @@
test_flags: *common_flags
test_targets:
- "//test:proto_format_test_e2e_test"
+ - "//test:macro_kwargs_legacy_test_e2e_test"
+
+ bazel_8_tests:
+ name: Stardoc golden tests requiring Bazel HEAD
+ platform: ubuntu2004
+ bazel: last_green
+ build_flags: *common_flags
+ test_flags: *common_flags
+ test_targets:
+ - "//test:macro_kwargs_test_e2e_test"
buildifier: latest
diff --git a/docs/stardoc_rule.md b/docs/stardoc_rule.md
index 52658ea..9851880 100644
--- a/docs/stardoc_rule.md
+++ b/docs/stardoc_rule.md
@@ -7,10 +7,10 @@
## stardoc
<pre>
-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-renderer">renderer</a>, <a href="#stardoc-aspect_template">aspect_template</a>, <a href="#stardoc-func_template">func_template</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-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-table_of_contents_template">table_of_contents_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-footer_template">footer_template</a>, <a href="#stardoc-render_main_repo_name">render_main_repo_name</a>,
- <a href="#stardoc-stamp">stamp</a>, <a href="#stardoc-kwargs">kwargs</a>)
+ <a href="#stardoc-stamp">stamp</a>, <a href="#stardoc-kwargs">**kwargs</a>)
</pre>
Generates documentation for exported starlark rule definitions in a target starlark file.
diff --git a/src/main/java/com/google/devtools/build/stardoc/rendering/MarkdownUtil.java b/src/main/java/com/google/devtools/build/stardoc/rendering/MarkdownUtil.java
index 4ac54ce..9324bb6 100644
--- a/src/main/java/com/google/devtools/build/stardoc/rendering/MarkdownUtil.java
+++ b/src/main/java/com/google/devtools/build/stardoc/rendering/MarkdownUtil.java
@@ -16,6 +16,9 @@
import static com.google.common.base.Strings.isNullOrEmpty;
import static com.google.common.collect.ImmutableList.toImmutableList;
+import static com.google.devtools.build.lib.starlarkdocextract.StardocOutputProtos.FunctionParamRole.PARAM_ROLE_KEYWORD_ONLY;
+import static com.google.devtools.build.lib.starlarkdocextract.StardocOutputProtos.FunctionParamRole.PARAM_ROLE_KWARGS;
+import static com.google.devtools.build.lib.starlarkdocextract.StardocOutputProtos.FunctionParamRole.PARAM_ROLE_VARARGS;
import static java.util.Comparator.naturalOrder;
import static java.util.stream.Collectors.joining;
@@ -38,6 +41,7 @@
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
+import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -247,9 +251,7 @@
String providerName, ProviderInfo providerInfo, String paramAnchorPrefix) {
ImmutableList<Param> params =
providerInfo.hasInit()
- ? providerInfo.getInit().getParameterList().stream()
- .map(paramInfo -> new Param(paramInfo, paramAnchorPrefix))
- .collect(toImmutableList())
+ ? getFunctionParamsInDeclarationOrder(providerInfo.getInit(), paramAnchorPrefix)
: providerInfo.getFieldInfoList().stream()
.map(fieldInfo -> new Param(fieldInfo, paramAnchorPrefix))
.collect(toImmutableList());
@@ -324,11 +326,9 @@
*/
@SuppressWarnings("unused") // Used by markdown template.
public String funcSummary(StarlarkFunctionInfo funcInfo) {
- ImmutableList<Param> params =
- funcInfo.getParameterList().stream()
- .map(paramInfo -> new Param(paramInfo, funcInfo.getFunctionName()))
- .collect(toImmutableList());
- return summary(funcInfo.getFunctionName(), params);
+ return summary(
+ funcInfo.getFunctionName(),
+ getFunctionParamsInDeclarationOrder(funcInfo, funcInfo.getFunctionName()));
}
/**
@@ -350,15 +350,30 @@
/** Representation of a callable's parameter in a summary line. */
private static final class Param {
- // Parameter name for use in summary line
+ // User-visible name, including the leading "*" or "**" for residuals
final String name;
// HTML anchor for the parameter's detailed documentation elsewhere on the page
- final String anchorName;
+ final Optional<String> anchorName;
+
+ public static final Param STAR_SEPARATOR = new Param("*", Optional.empty());
+
+ private Param(String name, Optional<String> anchorName) {
+ this.name = name;
+ this.anchorName = anchorName;
+ }
Param(FunctionParamInfo paramInfo, String anchorPrefix) {
- // TODO(https://github.com/bazelbuild/stardoc/issues/225): prepend "*" or "**" to this.name
- // for residual params.
- this.name = paramInfo.getName();
+ switch (paramInfo.getRole()) {
+ case PARAM_ROLE_VARARGS:
+ this.name = "*" + paramInfo.getName();
+ break;
+ case PARAM_ROLE_KWARGS:
+ this.name = "**" + paramInfo.getName();
+ break;
+ default:
+ this.name = paramInfo.getName();
+ break;
+ }
this.anchorName = formatAnchorName(paramInfo.getName(), anchorPrefix);
}
@@ -372,8 +387,8 @@
this.anchorName = formatAnchorName(fieldInfo.getName(), anchorPrefix);
}
- private static String formatAnchorName(String name, String anchorPrefix) {
- return String.format("%s-%s", anchorPrefix, name);
+ private static Optional<String> formatAnchorName(String name, String anchorPrefix) {
+ return Optional.of(String.format("%s-%s", anchorPrefix, name));
}
String getName() {
@@ -381,10 +396,58 @@
}
String renderHtml() {
- return String.format("<a href=\"#%s\">%s</a>", anchorName, name);
+ if (anchorName.isPresent()) {
+ return String.format("<a href=\"#%s\">%s</a>", anchorName.get(), name);
+ } else {
+ return name;
+ }
}
}
+ private static ImmutableList<Param> getFunctionParamsInDeclarationOrder(
+ StarlarkFunctionInfo funcInfo, String anchorPrefix) {
+ List<FunctionParamInfo> paramInfos = funcInfo.getParameterList();
+ int nparams = paramInfos.size();
+ Optional<Param> kwargs;
+ if (nparams > 0 && paramInfos.get(nparams - 1).getRole() == PARAM_ROLE_KWARGS) {
+ kwargs = Optional.of(new Param(paramInfos.get(nparams - 1), anchorPrefix));
+ nparams--;
+ } else {
+ kwargs = Optional.empty();
+ }
+ Optional<Param> varargs;
+ if (nparams > 0 && paramInfos.get(nparams - 1).getRole() == PARAM_ROLE_VARARGS) {
+ varargs = Optional.of(new Param(paramInfos.get(nparams - 1), anchorPrefix));
+ nparams--;
+ } else {
+ varargs = Optional.empty();
+ }
+ // Invariant: nparams is now the number of non-residual parameters.
+
+ ImmutableList.Builder<Param> paramsBuilder = new ImmutableList.Builder();
+ int numKwonly = 0;
+ // Add ordinary or positional-only params
+ for (int i = 0; i < nparams; i++) {
+ FunctionParamInfo paramInfo = paramInfos.get(i);
+ if (paramInfo.getRole() == PARAM_ROLE_KEYWORD_ONLY) {
+ numKwonly = nparams - i;
+ break;
+ }
+ paramsBuilder.add(new Param(paramInfo, anchorPrefix));
+ }
+ // Add *args or (if needed) the "*" separator
+ if (varargs.isPresent() || numKwonly > 0) {
+ paramsBuilder.add(varargs.orElse(Param.STAR_SEPARATOR));
+ }
+ // Add kwonly params (if any)
+ for (int i = nparams - numKwonly; i < nparams; i++) {
+ paramsBuilder.add(new Param(paramInfos.get(i), anchorPrefix));
+ }
+ // Add **kwargs
+ kwargs.ifPresent(paramsBuilder::add);
+ return paramsBuilder.build();
+ }
+
/**
* Wraps the given function parameter names to be able to construct a function summary that stays
* within the provided line length limit.
diff --git a/stardoc/proto/stardoc_output.proto b/stardoc/proto/stardoc_output.proto
index 82c97e8..ee6082f 100644
--- a/stardoc/proto/stardoc_output.proto
+++ b/stardoc/proto/stardoc_output.proto
@@ -13,7 +13,8 @@
// limitations under the License.
//
// Vendored from src/main/protobuf/stardoc_output.proto
-// in the Bazel source tree at commit f4cfc846dbdf5f6c19d0a716fccd2ddcdae0d609n
+// in the Bazel source tree at commit bd1c3af2ea14e81268e940d2b8ba5ad00c3f08d7n
+
//
// Protos for Stardoc data.
//
@@ -193,7 +194,16 @@
// "foo.frobnicate".
string function_name = 1;
- // The parameters for the function.
+ // The parameters for the function, in the following order:
+ // - positional parameters
+ // - keyword-only parameters
+ // - residual varargs parameter (`*args`)
+ // - residual keyword arguments parameter (`**kwargs`)
+ // This order differs from the order in which parameters are listed in the
+ // function's declaration (where positional parameters and keyword-only
+ // parameters are separated either by `*` or `*args`). The declaration order
+ // can be recovered by looking for the transition from ordinary/positional to
+ // keyword-only.
repeated FunctionParamInfo parameter = 2;
// The documented description of the function (if specified in the function's
@@ -213,9 +223,28 @@
OriginKey origin_key = 6;
}
+// Representation of the syntactic role of a given function parameter.
+enum FunctionParamRole {
+ PARAM_ROLE_UNSPECIFIED = 0;
+ // An ordinary parameter which may be used as a positional or by keyword.
+ PARAM_ROLE_ORDINARY = 1;
+ // A positional-only parameter; such parameters cannot be defined in pure
+ // Starlark code, but exist in some natively-defined functions.
+ PARAM_ROLE_POSITIONAL_ONLY = 2;
+ // A keyword-only parameter, i.e. a non-vararg/kwarg parameter that follows
+ // `*` or `*args` in the function's declaration.
+ PARAM_ROLE_KEYWORD_ONLY = 3;
+ // Residual varargs, typically `*args` in the function's declaration.
+ PARAM_ROLE_VARARGS = 4;
+ // Residual keyword arguments, typically `**kwargs` in the function's
+ // declaration.
+ PARAM_ROLE_KWARGS = 5;
+}
+
// Representation of a Starlark function parameter definition.
message FunctionParamInfo {
- // The name of the parameter.
+ // The name of the parameter. This does *not* include the `*` or `**` prefix
+ // for varargs or residual keyword argument parameters.
string name = 1;
// The documented description of the parameter (if specified in the function's
@@ -230,6 +259,9 @@
// parameter. This might be false even if defaultValue is empty in the case of
// special parameter such as *args and **kwargs"
bool mandatory = 4;
+
+ // The parameter's syntactic role.
+ FunctionParamRole role = 5;
}
message FunctionReturnInfo {
diff --git a/test/BUILD b/test/BUILD
index 4e8e8f2..3c5bc9e 100644
--- a/test/BUILD
+++ b/test/BUILD
@@ -13,6 +13,11 @@
name = "stardoc_self_gen_test",
golden_file = "//stardoc:stardoc_doc.md",
stardoc_doc = "//:stardoc_rule_doc",
+ # stardoc_doc.md output was generated with Bazel HEAD on 2024-06-12 and may differ in other versions
+ tags = [
+ "bazel_8",
+ "manual",
+ ],
)
exports_files(["testdata/fakedeps/dep.bzl"])
@@ -200,9 +205,25 @@
)
stardoc_test(
+ name = "macro_kwargs_legacy_test",
+ golden_file = "testdata/macro_kwargs_test/legacy_golden.md",
+ input_file = "testdata/macro_kwargs_test/input.bzl",
+ # Golden output was generated with Bazel 7.1 and may differ in other versions
+ tags = [
+ "bazel_7_1",
+ "manual",
+ ],
+)
+
+stardoc_test(
name = "macro_kwargs_test",
golden_file = "testdata/macro_kwargs_test/golden.md",
input_file = "testdata/macro_kwargs_test/input.bzl",
+ # Golden output was generated with Bazel HEAD on 2024-06-12 and may differ in other versions
+ tags = [
+ "bazel_8",
+ "manual",
+ ],
)
stardoc_test(
diff --git a/test/testdata/macro_kwargs_test/golden.md b/test/testdata/macro_kwargs_test/golden.md
index 1a9df5b..c4e95cd 100644
--- a/test/testdata/macro_kwargs_test/golden.md
+++ b/test/testdata/macro_kwargs_test/golden.md
@@ -7,7 +7,7 @@
## macro_with_args
<pre>
-macro_with_args(<a href="#macro_with_args-name">name</a>, <a href="#macro_with_args-args">args</a>)
+macro_with_args(<a href="#macro_with_args-name">name</a>, <a href="#macro_with_args-args">*args</a>)
</pre>
My args macro is OK.
@@ -25,12 +25,92 @@
An empty list.
+<a id="macro_with_args_and_kwonly"></a>
+
+## macro_with_args_and_kwonly
+
+<pre>
+macro_with_args_and_kwonly(<a href="#macro_with_args_and_kwonly-args">*args</a>, <a href="#macro_with_args_and_kwonly-name">name</a>)
+</pre>
+
+*args and a keyword-only param
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_args_and_kwonly-name"></a>name | The name | none |
+| <a id="macro_with_args_and_kwonly-args"></a>args | Positional arguments | none |
+
+
+<a id="macro_with_args_and_kwonlys"></a>
+
+## macro_with_args_and_kwonlys
+
+<pre>
+macro_with_args_and_kwonlys(<a href="#macro_with_args_and_kwonlys-args">*args</a>, <a href="#macro_with_args_and_kwonlys-name">name</a>, <a href="#macro_with_args_and_kwonlys-number">number</a>)
+</pre>
+
+*args and several keyword-only params
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_args_and_kwonlys-name"></a>name | The name | none |
+| <a id="macro_with_args_and_kwonlys-number"></a>number | The number | `3` |
+| <a id="macro_with_args_and_kwonlys-args"></a>args | Positional arguments | none |
+
+
+<a id="macro_with_args_kwonly_and_kwargs"></a>
+
+## macro_with_args_kwonly_and_kwargs
+
+<pre>
+macro_with_args_kwonly_and_kwargs(<a href="#macro_with_args_kwonly_and_kwargs-args">*args</a>, <a href="#macro_with_args_kwonly_and_kwargs-name">name</a>, <a href="#macro_with_args_kwonly_and_kwargs-kwargs">**kwargs</a>)
+</pre>
+
+*args, a keyword-only param, and **kwargs
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_args_kwonly_and_kwargs-name"></a>name | The name | none |
+| <a id="macro_with_args_kwonly_and_kwargs-args"></a>args | Positional arguments | none |
+| <a id="macro_with_args_kwonly_and_kwargs-kwargs"></a>kwargs | Other named arguments | none |
+
+
+<a id="macro_with_args_kwonlys_and_kwargs"></a>
+
+## macro_with_args_kwonlys_and_kwargs
+
+<pre>
+macro_with_args_kwonlys_and_kwargs(<a href="#macro_with_args_kwonlys_and_kwargs-args">*args</a>, <a href="#macro_with_args_kwonlys_and_kwargs-name">name</a>, <a href="#macro_with_args_kwonlys_and_kwargs-number">number</a>, <a href="#macro_with_args_kwonlys_and_kwargs-kwargs">**kwargs</a>)
+</pre>
+
+*args, several keyword-only params, and **kwargs
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_args_kwonlys_and_kwargs-name"></a>name | The name | none |
+| <a id="macro_with_args_kwonlys_and_kwargs-number"></a>number | The number | `3` |
+| <a id="macro_with_args_kwonlys_and_kwargs-args"></a>args | Positional arguments | none |
+| <a id="macro_with_args_kwonlys_and_kwargs-kwargs"></a>kwargs | Other named arguments | none |
+
+
<a id="macro_with_both"></a>
## macro_with_both
<pre>
-macro_with_both(<a href="#macro_with_both-name">name</a>, <a href="#macro_with_both-number">number</a>, <a href="#macro_with_both-args">args</a>, <a href="#macro_with_both-kwargs">kwargs</a>)
+macro_with_both(<a href="#macro_with_both-name">name</a>, <a href="#macro_with_both-number">number</a>, <a href="#macro_with_both-args">*args</a>, <a href="#macro_with_both-kwargs">**kwargs</a>)
</pre>
Oh wow this macro has both.
@@ -58,7 +138,7 @@
## macro_with_kwargs
<pre>
-macro_with_kwargs(<a href="#macro_with_kwargs-name">name</a>, <a href="#macro_with_kwargs-config">config</a>, <a href="#macro_with_kwargs-deps">deps</a>, <a href="#macro_with_kwargs-kwargs">kwargs</a>)
+macro_with_kwargs(<a href="#macro_with_kwargs-name">name</a>, <a href="#macro_with_kwargs-config">config</a>, <a href="#macro_with_kwargs-deps">deps</a>, <a href="#macro_with_kwargs-kwargs">**kwargs</a>)
</pre>
My kwargs macro is the best.
@@ -85,3 +165,302 @@
An empty list.
+<a id="macro_with_kwonly"></a>
+
+## macro_with_kwonly
+
+<pre>
+macro_with_kwonly(*, <a href="#macro_with_kwonly-name">name</a>)
+</pre>
+
+One keyword-only param
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_kwonly-name"></a>name | The name | none |
+
+
+<a id="macro_with_kwonly_and_kwargs"></a>
+
+## macro_with_kwonly_and_kwargs
+
+<pre>
+macro_with_kwonly_and_kwargs(*, <a href="#macro_with_kwonly_and_kwargs-name">name</a>, <a href="#macro_with_kwonly_and_kwargs-kwargs">**kwargs</a>)
+</pre>
+
+One keyword-only param and **kwargs
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_kwonly_and_kwargs-name"></a>name | The name | none |
+| <a id="macro_with_kwonly_and_kwargs-kwargs"></a>kwargs | Other named arguments | none |
+
+
+<a id="macro_with_kwonlys"></a>
+
+## macro_with_kwonlys
+
+<pre>
+macro_with_kwonlys(*, <a href="#macro_with_kwonlys-name">name</a>, <a href="#macro_with_kwonlys-number">number</a>)
+</pre>
+
+Several keyword-only params
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_kwonlys-name"></a>name | The name | none |
+| <a id="macro_with_kwonlys-number"></a>number | The number | `3` |
+
+
+<a id="macro_with_kwonlys_and_kwargs"></a>
+
+## macro_with_kwonlys_and_kwargs
+
+<pre>
+macro_with_kwonlys_and_kwargs(*, <a href="#macro_with_kwonlys_and_kwargs-name">name</a>, <a href="#macro_with_kwonlys_and_kwargs-number">number</a>, <a href="#macro_with_kwonlys_and_kwargs-kwargs">**kwargs</a>)
+</pre>
+
+Several keyword-only params and **kwargs
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_kwonlys_and_kwargs-name"></a>name | The name | none |
+| <a id="macro_with_kwonlys_and_kwargs-number"></a>number | The number | `3` |
+| <a id="macro_with_kwonlys_and_kwargs-kwargs"></a>kwargs | Other named arguments | none |
+
+
+<a id="macro_with_only_args"></a>
+
+## macro_with_only_args
+
+<pre>
+macro_with_only_args(<a href="#macro_with_only_args-args">*args</a>)
+</pre>
+
+Macro only taking *args
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_only_args-args"></a>args | Positional arguments | none |
+
+
+<a id="macro_with_only_args_and_kwargs"></a>
+
+## macro_with_only_args_and_kwargs
+
+<pre>
+macro_with_only_args_and_kwargs(<a href="#macro_with_only_args_and_kwargs-args">*args</a>, <a href="#macro_with_only_args_and_kwargs-kwargs">**kwargs</a>)
+</pre>
+
+Macro only taking *args and **kwargs
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_only_args_and_kwargs-args"></a>args | Positional arguments | none |
+| <a id="macro_with_only_args_and_kwargs-kwargs"></a>kwargs | Named arguments | none |
+
+
+<a id="macro_with_only_kwargs"></a>
+
+## macro_with_only_kwargs
+
+<pre>
+macro_with_only_kwargs(<a href="#macro_with_only_kwargs-kwargs">**kwargs</a>)
+</pre>
+
+Macro only taking **kwargs
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_only_kwargs-kwargs"></a>kwargs | Named arguments | none |
+
+
+<a id="macro_with_ordinary_param_and_kwonlys"></a>
+
+## macro_with_ordinary_param_and_kwonlys
+
+<pre>
+macro_with_ordinary_param_and_kwonlys(<a href="#macro_with_ordinary_param_and_kwonlys-name">name</a>, *, <a href="#macro_with_ordinary_param_and_kwonlys-number">number</a>, <a href="#macro_with_ordinary_param_and_kwonlys-config">config</a>)
+</pre>
+
+One ordinary param and several keyword-only params
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_ordinary_param_and_kwonlys-name"></a>name | The name | none |
+| <a id="macro_with_ordinary_param_and_kwonlys-number"></a>number | The number | none |
+| <a id="macro_with_ordinary_param_and_kwonlys-config"></a>config | Configuration | none |
+
+
+<a id="macro_with_ordinary_param_args_and_kwonlys"></a>
+
+## macro_with_ordinary_param_args_and_kwonlys
+
+<pre>
+macro_with_ordinary_param_args_and_kwonlys(<a href="#macro_with_ordinary_param_args_and_kwonlys-name">name</a>, <a href="#macro_with_ordinary_param_args_and_kwonlys-args">*args</a>, <a href="#macro_with_ordinary_param_args_and_kwonlys-number">number</a>, <a href="#macro_with_ordinary_param_args_and_kwonlys-config">config</a>)
+</pre>
+
+One ordinary param, *args, and several keyword-only params
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_ordinary_param_args_and_kwonlys-name"></a>name | The name | none |
+| <a id="macro_with_ordinary_param_args_and_kwonlys-number"></a>number | The number | none |
+| <a id="macro_with_ordinary_param_args_and_kwonlys-config"></a>config | Configuration | none |
+| <a id="macro_with_ordinary_param_args_and_kwonlys-args"></a>args | Positional arguments | none |
+
+
+<a id="macro_with_ordinary_param_args_kwonlys_and_kwargs"></a>
+
+## macro_with_ordinary_param_args_kwonlys_and_kwargs
+
+<pre>
+macro_with_ordinary_param_args_kwonlys_and_kwargs(<a href="#macro_with_ordinary_param_args_kwonlys_and_kwargs-name">name</a>, <a href="#macro_with_ordinary_param_args_kwonlys_and_kwargs-args">*args</a>, <a href="#macro_with_ordinary_param_args_kwonlys_and_kwargs-number">number</a>, <a href="#macro_with_ordinary_param_args_kwonlys_and_kwargs-config">config</a>, <a href="#macro_with_ordinary_param_args_kwonlys_and_kwargs-kwargs">**kwargs</a>)
+</pre>
+
+One ordinary param, *args, several keyword-only params, and **kwargs
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_ordinary_param_args_kwonlys_and_kwargs-name"></a>name | The name | none |
+| <a id="macro_with_ordinary_param_args_kwonlys_and_kwargs-number"></a>number | The number | none |
+| <a id="macro_with_ordinary_param_args_kwonlys_and_kwargs-config"></a>config | Configuration | none |
+| <a id="macro_with_ordinary_param_args_kwonlys_and_kwargs-args"></a>args | Other positional arguments | none |
+| <a id="macro_with_ordinary_param_args_kwonlys_and_kwargs-kwargs"></a>kwargs | Other named arguments | none |
+
+
+<a id="macro_with_ordinary_param_kwonlys_and_kwargs"></a>
+
+## macro_with_ordinary_param_kwonlys_and_kwargs
+
+<pre>
+macro_with_ordinary_param_kwonlys_and_kwargs(<a href="#macro_with_ordinary_param_kwonlys_and_kwargs-name">name</a>, *, <a href="#macro_with_ordinary_param_kwonlys_and_kwargs-number">number</a>, <a href="#macro_with_ordinary_param_kwonlys_and_kwargs-config">config</a>, <a href="#macro_with_ordinary_param_kwonlys_and_kwargs-kwargs">**kwargs</a>)
+</pre>
+
+One ordinary param, several keyword-only params, and **kwargs
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_ordinary_param_kwonlys_and_kwargs-name"></a>name | The name | none |
+| <a id="macro_with_ordinary_param_kwonlys_and_kwargs-number"></a>number | The number | none |
+| <a id="macro_with_ordinary_param_kwonlys_and_kwargs-config"></a>config | Configuration | none |
+| <a id="macro_with_ordinary_param_kwonlys_and_kwargs-kwargs"></a>kwargs | Other named arguments | none |
+
+
+<a id="macro_with_ordinary_params_and_kwonly"></a>
+
+## macro_with_ordinary_params_and_kwonly
+
+<pre>
+macro_with_ordinary_params_and_kwonly(<a href="#macro_with_ordinary_params_and_kwonly-name">name</a>, <a href="#macro_with_ordinary_params_and_kwonly-number">number</a>, *, <a href="#macro_with_ordinary_params_and_kwonly-config">config</a>)
+</pre>
+
+Several ordinary params and a keyword-only param
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_ordinary_params_and_kwonly-name"></a>name | The name | none |
+| <a id="macro_with_ordinary_params_and_kwonly-number"></a>number | The number | `3` |
+| <a id="macro_with_ordinary_params_and_kwonly-config"></a>config | Configuration | none |
+
+
+<a id="macro_with_ordinary_params_args_and_kwonly"></a>
+
+## macro_with_ordinary_params_args_and_kwonly
+
+<pre>
+macro_with_ordinary_params_args_and_kwonly(<a href="#macro_with_ordinary_params_args_and_kwonly-name">name</a>, <a href="#macro_with_ordinary_params_args_and_kwonly-number">number</a>, <a href="#macro_with_ordinary_params_args_and_kwonly-args">*args</a>, <a href="#macro_with_ordinary_params_args_and_kwonly-config">config</a>)
+</pre>
+
+Several ordinary params, *args, and a keyword-only param
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_ordinary_params_args_and_kwonly-name"></a>name | The name | none |
+| <a id="macro_with_ordinary_params_args_and_kwonly-number"></a>number | The number | `3` |
+| <a id="macro_with_ordinary_params_args_and_kwonly-config"></a>config | Configuration | none |
+| <a id="macro_with_ordinary_params_args_and_kwonly-args"></a>args | Positional arguments | none |
+
+
+<a id="macro_with_ordinary_params_args_kwonly_and_kwargs"></a>
+
+## macro_with_ordinary_params_args_kwonly_and_kwargs
+
+<pre>
+macro_with_ordinary_params_args_kwonly_and_kwargs(<a href="#macro_with_ordinary_params_args_kwonly_and_kwargs-name">name</a>, <a href="#macro_with_ordinary_params_args_kwonly_and_kwargs-number">number</a>, <a href="#macro_with_ordinary_params_args_kwonly_and_kwargs-args">*args</a>, <a href="#macro_with_ordinary_params_args_kwonly_and_kwargs-config">config</a>, <a href="#macro_with_ordinary_params_args_kwonly_and_kwargs-kwargs">**kwargs</a>)
+</pre>
+
+Several ordinary params, *args, one keyword-only param, and **kwargs
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_ordinary_params_args_kwonly_and_kwargs-name"></a>name | The name | none |
+| <a id="macro_with_ordinary_params_args_kwonly_and_kwargs-number"></a>number | The number | `3` |
+| <a id="macro_with_ordinary_params_args_kwonly_and_kwargs-config"></a>config | Configuration | none |
+| <a id="macro_with_ordinary_params_args_kwonly_and_kwargs-args"></a>args | Other positional arguments | none |
+| <a id="macro_with_ordinary_params_args_kwonly_and_kwargs-kwargs"></a>kwargs | Other named arguments | none |
+
+
+<a id="macro_with_ordinary_params_kwonly_and_kwargs"></a>
+
+## macro_with_ordinary_params_kwonly_and_kwargs
+
+<pre>
+macro_with_ordinary_params_kwonly_and_kwargs(<a href="#macro_with_ordinary_params_kwonly_and_kwargs-name">name</a>, <a href="#macro_with_ordinary_params_kwonly_and_kwargs-number">number</a>, *, <a href="#macro_with_ordinary_params_kwonly_and_kwargs-config">config</a>, <a href="#macro_with_ordinary_params_kwonly_and_kwargs-kwargs">**kwargs</a>)
+</pre>
+
+Several ordinary params, a keyword-only param, and **kwargs
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_ordinary_params_kwonly_and_kwargs-name"></a>name | The name | none |
+| <a id="macro_with_ordinary_params_kwonly_and_kwargs-number"></a>number | The number | `3` |
+| <a id="macro_with_ordinary_params_kwonly_and_kwargs-config"></a>config | Configuration | none |
+| <a id="macro_with_ordinary_params_kwonly_and_kwargs-kwargs"></a>kwargs | Other named arguments | none |
+
+
diff --git a/test/testdata/macro_kwargs_test/input.bzl b/test/testdata/macro_kwargs_test/input.bzl
index 8de782e..844899d 100644
--- a/test/testdata/macro_kwargs_test/input.bzl
+++ b/test/testdata/macro_kwargs_test/input.bzl
@@ -50,3 +50,211 @@
"""
_ignore = [name, number, args, kwargs] # @unused
return []
+
+# buildifier: disable=unused-variable
+def macro_with_only_args(*args):
+ """Macro only taking *args
+
+ Args:
+ *args: Positional arguments
+ """
+ pass
+
+# buildifier: disable=unused-variable
+def macro_with_only_kwargs(**kwargs):
+ """Macro only taking **kwargs
+
+ Args:
+ **kwargs: Named arguments
+ """
+ pass
+
+# buildifier: disable=unused-variable
+def macro_with_only_args_and_kwargs(*args, **kwargs):
+ """Macro only taking *args and **kwargs
+
+ Args:
+ *args: Positional arguments
+ **kwargs: Named arguments
+ """
+ pass
+
+# buildifier: disable=unused-variable
+def macro_with_kwonly(*, name):
+ """One keyword-only param
+
+ Args:
+ name: The name
+ """
+ pass
+
+# buildifier: disable=unused-variable
+def macro_with_kwonlys(*, name, number = 3):
+ """Several keyword-only params
+
+ Args:
+ name: The name
+ number: The number
+ """
+ pass
+
+# buildifier: disable=unused-variable
+def macro_with_kwonly_and_kwargs(*, name, **kwargs):
+ """One keyword-only param and **kwargs
+
+ Args:
+ name: The name
+ **kwargs: Other named arguments
+ """
+ pass
+
+# buildifier: disable=unused-variable
+def macro_with_kwonlys_and_kwargs(*, name, number = 3, **kwargs):
+ """Several keyword-only params and **kwargs
+
+ Args:
+ name: The name
+ number: The number
+ **kwargs: Other named arguments
+ """
+ pass
+
+# buildifier: disable=unused-variable
+def macro_with_ordinary_params_and_kwonly(name, number = 3, *, config):
+ """Several ordinary params and a keyword-only param
+
+ Args:
+ name: The name
+ number: The number
+ config: Configuration
+ """
+ pass
+
+# buildifier: disable=unused-variable
+def macro_with_ordinary_param_and_kwonlys(name, *, number, config):
+ """One ordinary param and several keyword-only params
+
+ Args:
+ name: The name
+ number: The number
+ config: Configuration
+ """
+ pass
+
+# buildifier: disable=unused-variable
+def macro_with_ordinary_param_kwonlys_and_kwargs(name, *, number, config, **kwargs):
+ """One ordinary param, several keyword-only params, and **kwargs
+
+ Args:
+ name: The name
+ number: The number
+ config: Configuration
+ **kwargs: Other named arguments
+ """
+ pass
+
+# buildifier: disable=unused-variable
+def macro_with_ordinary_params_kwonly_and_kwargs(name, number = 3, *, config, **kwargs):
+ """Several ordinary params, a keyword-only param, and **kwargs
+
+ Args:
+ name: The name
+ number: The number
+ config: Configuration
+ **kwargs: Other named arguments
+ """
+ pass
+
+# buildifier: disable=unused-variable
+def macro_with_args_and_kwonly(*args, name):
+ """*args and a keyword-only param
+
+ Args:
+ *args: Positional arguments
+ name: The name
+ """
+ pass
+
+# buildifier: disable=unused-variable
+def macro_with_args_and_kwonlys(*args, name, number = 3):
+ """*args and several keyword-only params
+
+ Args:
+ *args: Positional arguments
+ name: The name
+ number: The number
+ """
+ pass
+
+# buildifier: disable=unused-variable
+def macro_with_args_kwonly_and_kwargs(*args, name, **kwargs):
+ """*args, a keyword-only param, and **kwargs
+
+ Args:
+ *args: Positional arguments
+ name: The name
+ **kwargs: Other named arguments
+ """
+ pass
+
+# buildifier: disable=unused-variable
+def macro_with_args_kwonlys_and_kwargs(*args, name, number = 3, **kwargs):
+ """*args, several keyword-only params, and **kwargs
+
+ Args:
+ *args: Positional arguments
+ name: The name
+ number: The number
+ **kwargs: Other named arguments
+ """
+ pass
+
+# buildifier: disable=unused-variable
+def macro_with_ordinary_params_args_and_kwonly(name, number = 3, *args, config):
+ """Several ordinary params, *args, and a keyword-only param
+
+ Args:
+ name: The name
+ number: The number
+ *args: Positional arguments
+ config: Configuration
+ """
+ pass
+
+# buildifier: disable=unused-variable
+def macro_with_ordinary_param_args_and_kwonlys(name, *args, number, config):
+ """One ordinary param, *args, and several keyword-only params
+
+ Args:
+ name: The name
+ *args: Positional arguments
+ number: The number
+ config: Configuration
+ """
+ pass
+
+# buildifier: disable=unused-variable
+def macro_with_ordinary_param_args_kwonlys_and_kwargs(name, *args, number, config, **kwargs):
+ """One ordinary param, *args, several keyword-only params, and **kwargs
+
+ Args:
+ name: The name
+ *args: Other positional arguments
+ number: The number
+ config: Configuration
+ **kwargs: Other named arguments
+ """
+ pass
+
+# buildifier: disable=unused-variable
+def macro_with_ordinary_params_args_kwonly_and_kwargs(name, number = 3, *args, config, **kwargs):
+ """Several ordinary params, *args, one keyword-only param, and **kwargs
+
+ Args:
+ name: The name
+ number: The number
+ *args: Other positional arguments
+ config: Configuration
+ **kwargs: Other named arguments
+ """
+ pass
diff --git a/test/testdata/macro_kwargs_test/legacy_golden.md b/test/testdata/macro_kwargs_test/legacy_golden.md
new file mode 100644
index 0000000..0b1f040
--- /dev/null
+++ b/test/testdata/macro_kwargs_test/legacy_golden.md
@@ -0,0 +1,466 @@
+<!-- Generated with Stardoc: http://skydoc.bazel.build -->
+
+Tests for functions which use *args or **kwargs
+
+<a id="macro_with_args"></a>
+
+## macro_with_args
+
+<pre>
+macro_with_args(<a href="#macro_with_args-name">name</a>, <a href="#macro_with_args-args">args</a>)
+</pre>
+
+My args macro is OK.
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_args-name"></a>name | The name of the test rule. | none |
+| <a id="macro_with_args-args"></a>args | Other arguments to include | none |
+
+**RETURNS**
+
+An empty list.
+
+
+<a id="macro_with_args_and_kwonly"></a>
+
+## macro_with_args_and_kwonly
+
+<pre>
+macro_with_args_and_kwonly(<a href="#macro_with_args_and_kwonly-name">name</a>, <a href="#macro_with_args_and_kwonly-args">args</a>)
+</pre>
+
+*args and a keyword-only param
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_args_and_kwonly-name"></a>name | The name | none |
+| <a id="macro_with_args_and_kwonly-args"></a>args | Positional arguments | none |
+
+
+<a id="macro_with_args_and_kwonlys"></a>
+
+## macro_with_args_and_kwonlys
+
+<pre>
+macro_with_args_and_kwonlys(<a href="#macro_with_args_and_kwonlys-name">name</a>, <a href="#macro_with_args_and_kwonlys-number">number</a>, <a href="#macro_with_args_and_kwonlys-args">args</a>)
+</pre>
+
+*args and several keyword-only params
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_args_and_kwonlys-name"></a>name | The name | none |
+| <a id="macro_with_args_and_kwonlys-number"></a>number | The number | `3` |
+| <a id="macro_with_args_and_kwonlys-args"></a>args | Positional arguments | none |
+
+
+<a id="macro_with_args_kwonly_and_kwargs"></a>
+
+## macro_with_args_kwonly_and_kwargs
+
+<pre>
+macro_with_args_kwonly_and_kwargs(<a href="#macro_with_args_kwonly_and_kwargs-name">name</a>, <a href="#macro_with_args_kwonly_and_kwargs-args">args</a>, <a href="#macro_with_args_kwonly_and_kwargs-kwargs">kwargs</a>)
+</pre>
+
+*args, a keyword-only param, and **kwargs
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_args_kwonly_and_kwargs-name"></a>name | The name | none |
+| <a id="macro_with_args_kwonly_and_kwargs-args"></a>args | Positional arguments | none |
+| <a id="macro_with_args_kwonly_and_kwargs-kwargs"></a>kwargs | Other named arguments | none |
+
+
+<a id="macro_with_args_kwonlys_and_kwargs"></a>
+
+## macro_with_args_kwonlys_and_kwargs
+
+<pre>
+macro_with_args_kwonlys_and_kwargs(<a href="#macro_with_args_kwonlys_and_kwargs-name">name</a>, <a href="#macro_with_args_kwonlys_and_kwargs-number">number</a>, <a href="#macro_with_args_kwonlys_and_kwargs-args">args</a>, <a href="#macro_with_args_kwonlys_and_kwargs-kwargs">kwargs</a>)
+</pre>
+
+*args, several keyword-only params, and **kwargs
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_args_kwonlys_and_kwargs-name"></a>name | The name | none |
+| <a id="macro_with_args_kwonlys_and_kwargs-number"></a>number | The number | `3` |
+| <a id="macro_with_args_kwonlys_and_kwargs-args"></a>args | Positional arguments | none |
+| <a id="macro_with_args_kwonlys_and_kwargs-kwargs"></a>kwargs | Other named arguments | none |
+
+
+<a id="macro_with_both"></a>
+
+## macro_with_both
+
+<pre>
+macro_with_both(<a href="#macro_with_both-name">name</a>, <a href="#macro_with_both-number">number</a>, <a href="#macro_with_both-args">args</a>, <a href="#macro_with_both-kwargs">kwargs</a>)
+</pre>
+
+Oh wow this macro has both.
+
+Not much else to say.
+
+
+**PARAMETERS**
+
+
+| 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 | `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 |
+
+**RETURNS**
+
+An empty list.
+
+
+<a id="macro_with_kwargs"></a>
+
+## macro_with_kwargs
+
+<pre>
+macro_with_kwargs(<a href="#macro_with_kwargs-name">name</a>, <a href="#macro_with_kwargs-config">config</a>, <a href="#macro_with_kwargs-deps">deps</a>, <a href="#macro_with_kwargs-kwargs">kwargs</a>)
+</pre>
+
+My kwargs macro is the best.
+
+This is a long multi-line doc string.
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer
+elementum, diam vitae tincidunt pulvinar, nunc tortor volutpat dui,
+vitae facilisis odio ligula a tortor. Donec ullamcorper odio eget ipsum tincidunt,
+vel mollis eros pellentesque.
+
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <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 | `[]` |
+| <a id="macro_with_kwargs-kwargs"></a>kwargs | Other attributes to include | none |
+
+**RETURNS**
+
+An empty list.
+
+
+<a id="macro_with_kwonly"></a>
+
+## macro_with_kwonly
+
+<pre>
+macro_with_kwonly(<a href="#macro_with_kwonly-name">name</a>)
+</pre>
+
+One keyword-only param
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_kwonly-name"></a>name | The name | none |
+
+
+<a id="macro_with_kwonly_and_kwargs"></a>
+
+## macro_with_kwonly_and_kwargs
+
+<pre>
+macro_with_kwonly_and_kwargs(<a href="#macro_with_kwonly_and_kwargs-name">name</a>, <a href="#macro_with_kwonly_and_kwargs-kwargs">kwargs</a>)
+</pre>
+
+One keyword-only param and **kwargs
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_kwonly_and_kwargs-name"></a>name | The name | none |
+| <a id="macro_with_kwonly_and_kwargs-kwargs"></a>kwargs | Other named arguments | none |
+
+
+<a id="macro_with_kwonlys"></a>
+
+## macro_with_kwonlys
+
+<pre>
+macro_with_kwonlys(<a href="#macro_with_kwonlys-name">name</a>, <a href="#macro_with_kwonlys-number">number</a>)
+</pre>
+
+Several keyword-only params
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_kwonlys-name"></a>name | The name | none |
+| <a id="macro_with_kwonlys-number"></a>number | The number | `3` |
+
+
+<a id="macro_with_kwonlys_and_kwargs"></a>
+
+## macro_with_kwonlys_and_kwargs
+
+<pre>
+macro_with_kwonlys_and_kwargs(<a href="#macro_with_kwonlys_and_kwargs-name">name</a>, <a href="#macro_with_kwonlys_and_kwargs-number">number</a>, <a href="#macro_with_kwonlys_and_kwargs-kwargs">kwargs</a>)
+</pre>
+
+Several keyword-only params and **kwargs
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_kwonlys_and_kwargs-name"></a>name | The name | none |
+| <a id="macro_with_kwonlys_and_kwargs-number"></a>number | The number | `3` |
+| <a id="macro_with_kwonlys_and_kwargs-kwargs"></a>kwargs | Other named arguments | none |
+
+
+<a id="macro_with_only_args"></a>
+
+## macro_with_only_args
+
+<pre>
+macro_with_only_args(<a href="#macro_with_only_args-args">args</a>)
+</pre>
+
+Macro only taking *args
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_only_args-args"></a>args | Positional arguments | none |
+
+
+<a id="macro_with_only_args_and_kwargs"></a>
+
+## macro_with_only_args_and_kwargs
+
+<pre>
+macro_with_only_args_and_kwargs(<a href="#macro_with_only_args_and_kwargs-args">args</a>, <a href="#macro_with_only_args_and_kwargs-kwargs">kwargs</a>)
+</pre>
+
+Macro only taking *args and **kwargs
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_only_args_and_kwargs-args"></a>args | Positional arguments | none |
+| <a id="macro_with_only_args_and_kwargs-kwargs"></a>kwargs | Named arguments | none |
+
+
+<a id="macro_with_only_kwargs"></a>
+
+## macro_with_only_kwargs
+
+<pre>
+macro_with_only_kwargs(<a href="#macro_with_only_kwargs-kwargs">kwargs</a>)
+</pre>
+
+Macro only taking **kwargs
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_only_kwargs-kwargs"></a>kwargs | Named arguments | none |
+
+
+<a id="macro_with_ordinary_param_and_kwonlys"></a>
+
+## macro_with_ordinary_param_and_kwonlys
+
+<pre>
+macro_with_ordinary_param_and_kwonlys(<a href="#macro_with_ordinary_param_and_kwonlys-name">name</a>, <a href="#macro_with_ordinary_param_and_kwonlys-number">number</a>, <a href="#macro_with_ordinary_param_and_kwonlys-config">config</a>)
+</pre>
+
+One ordinary param and several keyword-only params
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_ordinary_param_and_kwonlys-name"></a>name | The name | none |
+| <a id="macro_with_ordinary_param_and_kwonlys-number"></a>number | The number | none |
+| <a id="macro_with_ordinary_param_and_kwonlys-config"></a>config | Configuration | none |
+
+
+<a id="macro_with_ordinary_param_args_and_kwonlys"></a>
+
+## macro_with_ordinary_param_args_and_kwonlys
+
+<pre>
+macro_with_ordinary_param_args_and_kwonlys(<a href="#macro_with_ordinary_param_args_and_kwonlys-name">name</a>, <a href="#macro_with_ordinary_param_args_and_kwonlys-number">number</a>, <a href="#macro_with_ordinary_param_args_and_kwonlys-config">config</a>, <a href="#macro_with_ordinary_param_args_and_kwonlys-args">args</a>)
+</pre>
+
+One ordinary param, *args, and several keyword-only params
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_ordinary_param_args_and_kwonlys-name"></a>name | The name | none |
+| <a id="macro_with_ordinary_param_args_and_kwonlys-number"></a>number | The number | none |
+| <a id="macro_with_ordinary_param_args_and_kwonlys-config"></a>config | Configuration | none |
+| <a id="macro_with_ordinary_param_args_and_kwonlys-args"></a>args | Positional arguments | none |
+
+
+<a id="macro_with_ordinary_param_args_kwonlys_and_kwargs"></a>
+
+## macro_with_ordinary_param_args_kwonlys_and_kwargs
+
+<pre>
+macro_with_ordinary_param_args_kwonlys_and_kwargs(<a href="#macro_with_ordinary_param_args_kwonlys_and_kwargs-name">name</a>, <a href="#macro_with_ordinary_param_args_kwonlys_and_kwargs-number">number</a>, <a href="#macro_with_ordinary_param_args_kwonlys_and_kwargs-config">config</a>, <a href="#macro_with_ordinary_param_args_kwonlys_and_kwargs-args">args</a>, <a href="#macro_with_ordinary_param_args_kwonlys_and_kwargs-kwargs">kwargs</a>)
+</pre>
+
+One ordinary param, *args, several keyword-only params, and **kwargs
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_ordinary_param_args_kwonlys_and_kwargs-name"></a>name | The name | none |
+| <a id="macro_with_ordinary_param_args_kwonlys_and_kwargs-number"></a>number | The number | none |
+| <a id="macro_with_ordinary_param_args_kwonlys_and_kwargs-config"></a>config | Configuration | none |
+| <a id="macro_with_ordinary_param_args_kwonlys_and_kwargs-args"></a>args | Other positional arguments | none |
+| <a id="macro_with_ordinary_param_args_kwonlys_and_kwargs-kwargs"></a>kwargs | Other named arguments | none |
+
+
+<a id="macro_with_ordinary_param_kwonlys_and_kwargs"></a>
+
+## macro_with_ordinary_param_kwonlys_and_kwargs
+
+<pre>
+macro_with_ordinary_param_kwonlys_and_kwargs(<a href="#macro_with_ordinary_param_kwonlys_and_kwargs-name">name</a>, <a href="#macro_with_ordinary_param_kwonlys_and_kwargs-number">number</a>, <a href="#macro_with_ordinary_param_kwonlys_and_kwargs-config">config</a>, <a href="#macro_with_ordinary_param_kwonlys_and_kwargs-kwargs">kwargs</a>)
+</pre>
+
+One ordinary param, several keyword-only params, and **kwargs
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_ordinary_param_kwonlys_and_kwargs-name"></a>name | The name | none |
+| <a id="macro_with_ordinary_param_kwonlys_and_kwargs-number"></a>number | The number | none |
+| <a id="macro_with_ordinary_param_kwonlys_and_kwargs-config"></a>config | Configuration | none |
+| <a id="macro_with_ordinary_param_kwonlys_and_kwargs-kwargs"></a>kwargs | Other named arguments | none |
+
+
+<a id="macro_with_ordinary_params_and_kwonly"></a>
+
+## macro_with_ordinary_params_and_kwonly
+
+<pre>
+macro_with_ordinary_params_and_kwonly(<a href="#macro_with_ordinary_params_and_kwonly-name">name</a>, <a href="#macro_with_ordinary_params_and_kwonly-number">number</a>, <a href="#macro_with_ordinary_params_and_kwonly-config">config</a>)
+</pre>
+
+Several ordinary params and a keyword-only param
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_ordinary_params_and_kwonly-name"></a>name | The name | none |
+| <a id="macro_with_ordinary_params_and_kwonly-number"></a>number | The number | `3` |
+| <a id="macro_with_ordinary_params_and_kwonly-config"></a>config | Configuration | none |
+
+
+<a id="macro_with_ordinary_params_args_and_kwonly"></a>
+
+## macro_with_ordinary_params_args_and_kwonly
+
+<pre>
+macro_with_ordinary_params_args_and_kwonly(<a href="#macro_with_ordinary_params_args_and_kwonly-name">name</a>, <a href="#macro_with_ordinary_params_args_and_kwonly-number">number</a>, <a href="#macro_with_ordinary_params_args_and_kwonly-config">config</a>, <a href="#macro_with_ordinary_params_args_and_kwonly-args">args</a>)
+</pre>
+
+Several ordinary params, *args, and a keyword-only param
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_ordinary_params_args_and_kwonly-name"></a>name | The name | none |
+| <a id="macro_with_ordinary_params_args_and_kwonly-number"></a>number | The number | `3` |
+| <a id="macro_with_ordinary_params_args_and_kwonly-config"></a>config | Configuration | none |
+| <a id="macro_with_ordinary_params_args_and_kwonly-args"></a>args | Positional arguments | none |
+
+
+<a id="macro_with_ordinary_params_args_kwonly_and_kwargs"></a>
+
+## macro_with_ordinary_params_args_kwonly_and_kwargs
+
+<pre>
+macro_with_ordinary_params_args_kwonly_and_kwargs(<a href="#macro_with_ordinary_params_args_kwonly_and_kwargs-name">name</a>, <a href="#macro_with_ordinary_params_args_kwonly_and_kwargs-number">number</a>, <a href="#macro_with_ordinary_params_args_kwonly_and_kwargs-config">config</a>, <a href="#macro_with_ordinary_params_args_kwonly_and_kwargs-args">args</a>, <a href="#macro_with_ordinary_params_args_kwonly_and_kwargs-kwargs">kwargs</a>)
+</pre>
+
+Several ordinary params, *args, one keyword-only param, and **kwargs
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_ordinary_params_args_kwonly_and_kwargs-name"></a>name | The name | none |
+| <a id="macro_with_ordinary_params_args_kwonly_and_kwargs-number"></a>number | The number | `3` |
+| <a id="macro_with_ordinary_params_args_kwonly_and_kwargs-config"></a>config | Configuration | none |
+| <a id="macro_with_ordinary_params_args_kwonly_and_kwargs-args"></a>args | Other positional arguments | none |
+| <a id="macro_with_ordinary_params_args_kwonly_and_kwargs-kwargs"></a>kwargs | Other named arguments | none |
+
+
+<a id="macro_with_ordinary_params_kwonly_and_kwargs"></a>
+
+## macro_with_ordinary_params_kwonly_and_kwargs
+
+<pre>
+macro_with_ordinary_params_kwonly_and_kwargs(<a href="#macro_with_ordinary_params_kwonly_and_kwargs-name">name</a>, <a href="#macro_with_ordinary_params_kwonly_and_kwargs-number">number</a>, <a href="#macro_with_ordinary_params_kwonly_and_kwargs-config">config</a>, <a href="#macro_with_ordinary_params_kwonly_and_kwargs-kwargs">kwargs</a>)
+</pre>
+
+Several ordinary params, a keyword-only param, and **kwargs
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="macro_with_ordinary_params_kwonly_and_kwargs-name"></a>name | The name | none |
+| <a id="macro_with_ordinary_params_kwonly_and_kwargs-number"></a>number | The number | `3` |
+| <a id="macro_with_ordinary_params_kwonly_and_kwargs-config"></a>config | Configuration | none |
+| <a id="macro_with_ordinary_params_kwonly_and_kwargs-kwargs"></a>kwargs | Other named arguments | none |
+
+
diff --git a/update-stardoc-tests.sh b/update-stardoc-tests.sh
index dca9b18..c79f50b 100755
--- a/update-stardoc-tests.sh
+++ b/update-stardoc-tests.sh
@@ -37,7 +37,7 @@
# Some tests cannot be automatically regenerated using this script, as they don't fall under the normal
# golden test pattern or require a specific Bazel version
-EXCLUDED_TESTS="namespace_test_with_allowlist|multi_level_namespace_test_with_allowlist|local_repository_test|stamping_with_stamping_off"
+EXCLUDED_TESTS="namespace_test_with_allowlist|multi_level_namespace_test_with_allowlist|local_repository_test|stamping_with_stamping_off|macro_kwargs"
echo "** Querying for tests..."
regen_targets=$(${BAZEL} query //test:all | grep regenerate_ | grep -vE "_golden\.extract|$EXCLUDED_TESTS")