generated from bazel-contrib/rules-template
-
-
Notifications
You must be signed in to change notification settings - Fork 60
/
Copy pathkeep_sorted.bzl
161 lines (134 loc) · 6.31 KB
/
keep_sorted.bzl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
"""API for declaring a keep-sorted lint aspect that visits all source files.
Typical usage:
First, fetch the keep-sorted dependency via gazelle. We provide a convenient go.mod file.
To keep it isolated from your other go dependencies, we recommend adding to .bazelrc:
common --experimental_isolated_extension_usages
Next add to MODULE.bazel:
keep_sorted_deps = use_extension("@gazelle//:extensions.bzl", "go_deps", isolate = True)
keep_sorted_deps.from_file(go_mod = "@aspect_rules_lint//lint/keep-sorted:go.mod")
use_repo(keep_sorted_deps, "com_github_google_keep_sorted")
Finally, create the linter aspect, typically in `tools/lint/linters.bzl`:
```starlark
load("@aspect_rules_lint//lint:keep_sorted.bzl", "lint_keep_sorted_aspect")
keep_sorted = lint_keep_sorted_aspect(
binary = "@com_github_google_keep_sorted//:keep-sorted",
)
```
Now you can add `// keep-sorted start` / `// keep-sorted end` lines to your library sources,
following the documentation at https://github.com/google/keep-sorted#usage.
"""
load("//lint/private:lint_aspect.bzl", "LintOptionsInfo", "filter_srcs", "noop_lint_action", "output_files", "patch_and_output_files")
_MNEMONIC = "AspectRulesLintKeepSorted"
def keep_sorted_action(ctx, executable, srcs, stdout, exit_code = None, options = []):
"""Run keep-sorted as an action under Bazel.
Args:
ctx: Bazel Rule or Aspect evaluation context
executable: label of the the keep-sorted program
srcs: files to be linted
stdout: output file containing stdout
exit_code: output file containing exit code
If None, then fail the build when program exits non-zero.
options: additional command-line options
"""
inputs = srcs
outputs = [stdout]
# Wire command-line options, see
# Flags:
# --color string Whether to color debug output. One of "always", "never", or "auto" (default "auto")
# --default-options options The options keep-sorted will use to sort. Per-block overrides apply on top of these options. Note: list options like prefix_order are not merged with per-block overrides. They are completely overridden. (default allow_yaml_lists=yes case=yes group=yes remove_duplicates=yes sticky_comments=yes)
# --lines line_ranges Line ranges of the form "start:end". Only processes keep-sorted blocks that overlap with the given line ranges. Can only be used when fixing a single file. This flag can either be a comma-separated list of line ranges, or it can be specified multiple times on the command line to specify multiple line ranges. (default [])
# --mode mode Determines what mode to run this tool in. One of ["fix" "lint"] (default fix)
# -v, --verbose count Log more verbosely
# --version Report the keep-sorted version.
args = ctx.actions.args()
args.add_all(options)
args.add("--mode=lint")
args.add_all(srcs)
if exit_code:
command = "{keep_sorted} $@ >{stdout}; echo $? > " + exit_code.path
outputs.append(exit_code)
else:
# Create empty stdout file on success, as Bazel expects one
command = "{keep_sorted} $@ && touch {stdout}"
ctx.actions.run_shell(
inputs = inputs,
outputs = outputs,
tools = [executable],
command = command.format(keep_sorted = executable.path, stdout = stdout.path),
arguments = [args],
mnemonic = _MNEMONIC,
progress_message = "Linting %{label} with KeepSorted",
)
def keep_sorted_fix(ctx, executable, srcs, patch, stdout, exit_code = None, options = []):
patch_cfg = ctx.actions.declare_file("_{}.keep-sorted.patch_cfg".format(ctx.label.name))
ctx.actions.write(
output = patch_cfg,
content = json.encode({
"linter": executable._keep_sorted.path,
"args": ["--mode=fix"] + options + [s.path for s in srcs],
"files_to_diff": [s.path for s in srcs],
"output": patch.path,
}),
)
ctx.actions.run(
inputs = srcs + [patch_cfg],
outputs = [patch, exit_code, stdout],
executable = executable._patcher,
arguments = [patch_cfg.path],
env = {
"BAZEL_BINDIR": ".",
"JS_BINARY__EXIT_CODE_OUTPUT_FILE": exit_code.path,
"JS_BINARY__STDOUT_OUTPUT_FILE": stdout.path,
"JS_BINARY__SILENT_ON_SUCCESS": "1",
},
tools = [executable._keep_sorted],
mnemonic = _MNEMONIC,
progress_message = "Fixing %{label} with KeepSorted",
)
def _keep_sorted_aspect_impl(target, ctx):
if ctx.attr._options[LintOptionsInfo].fix:
outputs, info = patch_and_output_files(_MNEMONIC, target, ctx)
else:
outputs, info = output_files(_MNEMONIC, target, ctx)
if not hasattr(ctx.rule.attr, "srcs"):
noop_lint_action(ctx, outputs)
return [info]
files_to_lint = filter_srcs(ctx.rule)
if len(files_to_lint) == 0:
noop_lint_action(ctx, outputs)
return [info]
color_options = ["--color=always"] if ctx.attr._options[LintOptionsInfo].color else []
if hasattr(outputs, "patch"):
keep_sorted_fix(ctx, ctx.executable, files_to_lint, outputs.patch, outputs.human.out, outputs.human.exit_code, color_options)
else:
keep_sorted_action(ctx, ctx.executable._keep_sorted, files_to_lint, outputs.human.out, outputs.human.exit_code, color_options)
keep_sorted_action(ctx, ctx.executable._keep_sorted, files_to_lint, outputs.machine.out, outputs.machine.exit_code)
return [info]
def lint_keep_sorted_aspect(binary):
"""A factory function to create a linter aspect.
Args:
binary: a keep-sorted executable
Returns:
An aspect definition for keep-sorted
"""
return aspect(
implementation = _keep_sorted_aspect_impl,
attrs = {
"_options": attr.label(
default = "//lint:options",
providers = [LintOptionsInfo],
),
"_keep_sorted": attr.label(
default = binary,
executable = True,
cfg = "exec",
),
"_patcher": attr.label(
default = "@aspect_rules_lint//lint/private:patcher",
executable = True,
cfg = "exec",
),
},
toolchains = [
],
)