diff --git a/java/private/spotbugs.bzl b/java/private/spotbugs.bzl index 120dde2b..41887b07 100644 --- a/java/private/spotbugs.bzl +++ b/java/private/spotbugs.bzl @@ -7,11 +7,17 @@ Spotbugs integration logic def _spotbugs_impl(ctx): info = ctx.attr.config[SpotBugsInfo] + max_rank = info.max_rank effort = info.effort fail_on_warning = info.fail_on_warning exclude_filter = info.exclude_filter + omit_visitors = info.omit_visitors plugin_list = info.plugin_list + baseline_files = ctx.attr.baseline_file + if len(baseline_files) > 1: + fail("More than one baseline file was specified.") + if ctx.attr.only_output_jars: deps = [] for target in ctx.attr.deps: @@ -30,15 +36,28 @@ def _spotbugs_impl(ctx): flags.extend(["-exclude", exclude_filter.short_path]) runfiles.append(exclude_filter) + if len(baseline_files) > 0: + baseline_file = baseline_files[0].files.to_list()[0] + flags.extend(["-excludeBugs", baseline_file.short_path]) + runfiles.append(baseline_file) + + # NOTE: pluginList needs to be specified before specifying any visitor + # otherwise the execution will will fail with detector not found. if plugin_list: plugin_list_cli_flag = ":".join([plugin.short_path for plugin in plugin_list]) flags.extend(["-pluginList", plugin_list_cli_flag]) runfiles.extend(plugin_list) + if omit_visitors: + flags.extend(["-omitVisitors", ",".join(omit_visitors)]) + + if max_rank: + flags.extend(["-maxRank", max_rank]) + test = [ "#!/usr/bin/env bash", "ERRORLOG=$(mktemp)", - "RES=`{lib} {flags} {jars} 2>$ERRORLOG`".format( + "RES=`{lib} {flags} \"${{@}}\" {jars} 2>$ERRORLOG`".format( lib = info.binary.short_path, flags = " ".join(flags), jars = " ".join([jar.short_path for jar in jars]), @@ -94,6 +113,14 @@ spotbugs_test = rule( SpotBugsInfo, ], ), + # NOTE: this will always be just one file, but we use a label_list instead of a label + # so that we can pass a glob. In cases where no baseline file exist, the glob will simply + # be empty. Using a label instead of a label_list would force us to create a baseline file + # for all targets, even if theres no need for one. + "baseline_file": attr.label_list( + allow_files = True, + default = [], + ), "only_output_jars": attr.bool( doc = "If set to true, only the output jar of the target will be analyzed. Otherwise all transitive runtime dependencies will be analyzed", default = True, diff --git a/java/private/spotbugs_config.bzl b/java/private/spotbugs_config.bzl index 9666ce49..72b53021 100644 --- a/java/private/spotbugs_config.bzl +++ b/java/private/spotbugs_config.bzl @@ -47,7 +47,9 @@ def spotbugs_binary( SpotBugsInfo = provider( fields = { "effort": "Effort can be min, less, default, more or max.", + "max_rank": "Only report issues with a bug rank at least as scary as that provided.", "exclude_filter": "Optional filter file to use.", + "omit_visitors": "Omit named visitors", "fail_on_warning": "Whether to fail on warning, or just create a report.", "plugin_list": "Optional list of JARs to load as plugins.", "binary": "The spotbugs binary to use.", @@ -61,7 +63,9 @@ def _spotbugs_config_impl(ctx): ), SpotBugsInfo( effort = ctx.attr.effort, + max_rank = ctx.attr.max_rank, exclude_filter = ctx.file.exclude_filter, + omit_visitors = ctx.attr.omit_visitors, plugin_list = ctx.files.plugin_list, fail_on_warning = ctx.attr.fail_on_warning, binary = ctx.executable.spotbugs_binary, @@ -77,10 +81,17 @@ spotbugs_config = rule( values = ["min", "less", "default", "more", "max"], default = "default", ), + "max_rank": attr.string( + doc = "Only report issues with a bug rank at least as scary as that provided.", + ), "exclude_filter": attr.label( doc = "Report all bug instances except those matching the filter specified by this filter file", allow_single_file = True, ), + "omit_visitors": attr.string_list( + doc = "Omit named visitors.", + default = [], + ), "plugin_list": attr.label_list( doc = "Specify a list of plugin Jar files to load", allow_files = True,