generated from bazel-contrib/rules-template
-
-
Notifications
You must be signed in to change notification settings - Fork 60
/
Copy pathspotbugs.bzl
142 lines (121 loc) · 4.96 KB
/
spotbugs.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
"""API for declaring a spotbugs lint aspect that visits java_library and java_binary rules.
Typical usage:
First, call the `fetch_spotbugs` helper in `WORKSPACE` to download the jar file.
Alternatively you could use whatever you prefer for managing Java dependencies, such as a Maven integration rule.
Next, declare a binary target for it, typically in `tools/lint/BUILD.bazel`:
```starlark
java_binary(
name = "spotbugs",
main_class = "edu.umd.cs.findbugs.LaunchAppropriateUI",
runtime_deps = [
"@spotbugs//:jar",
],
)
```
Finally, declare an aspect for it, typically in `tools/lint/linters.bzl`:
```starlark
load("@aspect_rules_lint//lint:spotbugs.bzl", "lint_spotbugs_aspect")
spotbugs = lint_spotbugs_aspect(
binary = "@@//tools/lint:spotbugs",
exclude_filter = "@@//:spotbugs-exclude.xml",
)
```
"""
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_jar")
load("//lint/private:lint_aspect.bzl", "LintOptionsInfo", "filter_srcs", "noop_lint_action", "output_files", "should_visit")
_MNEMONIC = "AspectRulesLintCSpotbugs"
def spotbugs_action(ctx, executable, srcs, exclude_filter, stdout, exit_code = None, options = []):
"""Run Spotbugs as an action under Bazel.
Based on https://spotbugs.readthedocs.io/en/latest/index.html
Args:
ctx: Bazel Rule or Aspect evaluation context
executable: label of the the Spotbugs program
srcs: jar to be linted
exclude_filter: label of the spotbugs-exclude.xml file
stdout: output file to generate
exit_code: output file to write the exit code.
If None, then fail the build when Spotbugs exits non-zero.
options: additional command-line options, see https://spotbugs.readthedocs.io/en/latest/running.html#command-line-options
"""
inputs = srcs + [exclude_filter]
outputs = [stdout]
args = ctx.actions.args()
args.add_all(options)
if exclude_filter:
args.add_all(["-exclude", exclude_filter.path])
src_args = ctx.actions.args()
src_args.add_all(srcs)
args.add_all(["-exclude", exclude_filter.path])
if exit_code:
command = "{SPOTBUGS} $@ >{stdout}; echo $? > " + exit_code.path
outputs.append(exit_code)
else:
# Create empty stdout file on success, as Bazel expects one
command = "{SPOTBUGS} $@ && touch {stdout}"
ctx.actions.run_shell(
inputs = inputs,
outputs = outputs,
command = command.format(SPOTBUGS = executable.path, stdout = stdout.path),
arguments = [args, src_args],
mnemonic = _MNEMONIC,
tools = [executable],
progress_message = "Linting %{label} with Spotbugs",
)
# buildifier: disable=function-docstrings
def _spotbugs_aspect_impl(target, ctx):
if not should_visit(ctx.rule, ctx.attr._rule_kinds):
return []
print("Print target %s", target.label)
print("JavaInfo %s", target[JavaInfo])
print("OutputGroupInfo %s", target[OutputGroupInfo])
files_to_lint = [jar.class_jar for jar in target[JavaInfo].outputs.jars]
print("Files to lint %s", files_to_lint)
outputs, info = output_files(_MNEMONIC, target, ctx)
if len(files_to_lint) == 0:
noop_lint_action(ctx, outputs)
return [info]
format_options = [] # to define
spotbugs_action(ctx, ctx.executable._spotbugs, files_to_lint, ctx.file._exclude_filter, outputs.human.out, outputs.human.exit_code, format_options)
spotbugs_action(ctx, ctx.executable._spotbugs, files_to_lint, ctx.file._exclude_filter, outputs.machine.out, outputs.machine.exit_code, format_options)
return [info]
def lint_spotbugs_aspect(binary, exclude_filter, rule_kinds = ["java_library", "java_binary"]):
return aspect(
implementation = _spotbugs_aspect_impl,
# Edges we need to walk up the graph from the selected targets.
# Needed for linters that need semantic information like transitive type declarations.
attr_aspects = ["deps"],
attrs = {
"_options": attr.label(
default = "//lint:options",
providers = [LintOptionsInfo],
),
"_spotbugs": attr.label(
default = binary,
executable = True,
cfg = "exec",
),
"_exclude_filter": attr.label(
doc = "Report all bug instances except those matching the filter specified by this filter file",
allow_single_file = True,
default = exclude_filter,
),
"_rule_kinds": attr.string_list(
default = rule_kinds,
),
},
)
def fetch_spotbugs():
http_archive(
name = "spotbugs",
urls = ["https://github.com/spotbugs/spotbugs/releases/download/4.8.6/spotbugs-4.8.6.zip"],
strip_prefix = "spotbugs-4.8.6",
build_file_content = """
java_import(
name = "jar",
jars = [
"lib/spotbugs.jar",
],
visibility = ["//visibility:public"],
)
""",
)