From 89fb6c91c6317140b184333763e851aa8698d76a Mon Sep 17 00:00:00 2001 From: Edbert Chan Date: Thu, 4 Apr 2024 15:58:55 -0700 Subject: [PATCH 1/4] adding html_support --- rules/impl.bzl | 12 +++++++++++- src/cli/AndroidLintActionArgs.kt | 6 ++++++ src/cli/AndroidLintRunner.kt | 6 ++++-- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/rules/impl.bzl b/rules/impl.bzl index 23d2a94..36f14c9 100644 --- a/rules/impl.bzl +++ b/rules/impl.bzl @@ -20,6 +20,7 @@ def _run_android_lint( android_lint, module_name, output, + html_output, srcs, deps, resource_files, @@ -63,7 +64,7 @@ def _run_android_lint( android_lint_skip_bytecode_verifier: Disables bytecode verification """ inputs = [] - outputs = [output] + outputs = [output, html_output] args = ctx.actions.args() args.set_param_file_format("multiline") @@ -118,6 +119,13 @@ def _run_android_lint( args.add("--output", output) outputs.append(output) + args.add("--html-output", html_output) + outputs.append(html_output) + + label = ctx.attr.android_home.label + if ctx.attr.android_home: + args.add("--android_home", label.workspace_root) + ctx.actions.run( mnemonic = "AndroidLint", inputs = inputs, @@ -198,11 +206,13 @@ def process_android_lint_issues(ctx, regenerate): ) output = ctx.actions.declare_file("{}.xml".format(ctx.label.name)) + html_output = ctx.actions.declare_file("{}.html".format(ctx.label.name)) _run_android_lint( ctx, android_lint = _utils.only(_utils.list_or_depset_to_list(_utils.get_android_lint_toolchain(ctx).android_lint.files)), module_name = _get_module_name(ctx), output = output, + html_output = html_output, srcs = ctx.files.srcs, deps = depset(transitive = deps), resource_files = ctx.files.resource_files, diff --git a/src/cli/AndroidLintActionArgs.kt b/src/cli/AndroidLintActionArgs.kt index 12aa735..6d78f2f 100644 --- a/src/cli/AndroidLintActionArgs.kt +++ b/src/cli/AndroidLintActionArgs.kt @@ -38,6 +38,12 @@ internal class AndroidLintActionArgs( transform = argsParserPathTransformer, ) + val htmlOutput: Path by parser.storing( + names = arrayOf("--html-output"), + help = "", + transform = argsParserPathTransformer, + ) + val resources: List by parser.adding( names = arrayOf("--resource"), help = "", diff --git a/src/cli/AndroidLintRunner.kt b/src/cli/AndroidLintRunner.kt index 3b339d3..217193b 100644 --- a/src/cli/AndroidLintRunner.kt +++ b/src/cli/AndroidLintRunner.kt @@ -92,10 +92,12 @@ internal class AndroidLintRunner { val args = mutableListOf( "--project", projectFilePath.pathString, - "--xml", - actionArgs.output.pathString, "--path-variables", "PWD=$rootDirPath", + "--xml", + actionArgs.output.pathString, + "--html", + actionArgs.htmlOutput.pathString, "--exitcode", "--compile-sdk-version", actionArgs.compileSdkVersion, From 97ab9b838f015884e90308e68305b3fab5fb494c Mon Sep 17 00:00:00 2001 From: Edbert Chan Date: Wed, 24 Apr 2024 13:32:50 -0700 Subject: [PATCH 2/4] all html code changes --- docs/rules.md | 12 ++++-- rules/android_lint_test.bzl | 12 ++++-- rules/attrs.bzl | 6 +++ rules/impl.bzl | 49 +++++++++++++--------- rules/providers.bzl | 4 +- src/cli/AndroidLintActionArgs.kt | 10 ++--- src/cli/AndroidLintRunner.kt | 14 +++++-- tests/src/cli/AndroidLintActionArgsTest.kt | 9 ++-- 8 files changed, 75 insertions(+), 41 deletions(-) diff --git a/docs/rules.md b/docs/rules.md index f3f1ad3..746aaff 100644 --- a/docs/rules.md +++ b/docs/rules.md @@ -9,7 +9,7 @@ Android Lint rules
 android_lint(name, android_lint_config, autofix, custom_rules, deps, disable_checks, enable_checks,
-             is_test_sources, lib, manifest, resource_files, srcs, warnings_as_errors)
+             is_test_sources, lib, manifest, output_formats, resource_files, srcs, warnings_as_errors)
 
@@ -29,6 +29,7 @@ android_lint(name, is_test_sources | True when linting test sources, otherwise false. | Boolean | optional | False | | lib | The target being linted. This is needed to get the compiled R files. | Label | required | | | manifest | Android manifest to run Android Lint against. | Label | optional | None | +| output_formats | List of output formats to produce. Supported [xml, html] | List of strings | optional | ["xml"] | | resource_files | Android resource files to run Android Lint against. | List of labels | optional | [] | | srcs | Sources to run Android Lint against. | List of labels | required | | | warnings_as_errors | When true, lint will treat warnings as errors. | Boolean | optional | False | @@ -40,7 +41,7 @@ android_lint(name, name, android_lint_config, autofix, baseline, custom_rules, deps, disable_checks, - enable_checks, is_test_sources, lib, manifest, resource_files, srcs, + enable_checks, is_test_sources, lib, manifest, output_formats, resource_files, srcs, warnings_as_errors) @@ -62,6 +63,7 @@ android_lint_test(name, is_test_sources | True when linting test sources, otherwise false. | Boolean | optional | False | | lib | The target being linted. This is needed to get the compiled R files. | Label | required | | | manifest | Android manifest to run Android Lint against. | Label | optional | None | +| output_formats | List of output formats to produce. Supported [xml, html] | List of strings | optional | ["xml"] | | resource_files | Android resource files to run Android Lint against. | List of labels | optional | [] | | srcs | Sources to run Android Lint against. | List of labels | required | | | warnings_as_errors | When true, lint will treat warnings as errors. | Boolean | optional | False | @@ -72,7 +74,7 @@ android_lint_test(name, output) +AndroidLintResultsInfo(baseline, xml_output, html_output) Info needed to evaluate lint results @@ -82,6 +84,8 @@ Info needed to evaluate lint results | Name | Description | | :------------- | :------------- | -| output | The Android Lint baseline output | +| baseline | The Android Lint baseline output | +| xml_output | The Android Lint xml output | +| html_output | The Android Lint html output | diff --git a/rules/android_lint_test.bzl b/rules/android_lint_test.bzl index cc2739f..8afe537 100644 --- a/rules/android_lint_test.bzl +++ b/rules/android_lint_test.bzl @@ -21,7 +21,7 @@ def _test_impl(ctx): android_lint_results = _process_android_lint_issues(ctx, regenerate = False) inputs = [] - inputs.append(android_lint_results.output) + inputs.append(android_lint_results.xml_output) inputs.extend(ctx.attr._android_lint_output_validator.default_runfiles.files.to_list()) ctx.actions.write( @@ -33,15 +33,19 @@ def _test_impl(ctx): {executable} --lint_baseline "{lint_baseline}" """.format( executable = ctx.executable._android_lint_output_validator.short_path, - lint_baseline = android_lint_results.output.short_path, + lint_baseline = android_lint_results.xml_output.short_path, ), ) - + files_info = [ctx.outputs.executable] + if android_lint_results.xml_output != None: + files_info.append(android_lint_results.xml_output) + if android_lint_results.html_output != None: + files_info.append(android_lint_results.html_output) return [ DefaultInfo( runfiles = ctx.runfiles(files = inputs), executable = ctx.outputs.executable, - files = depset([ctx.outputs.executable, android_lint_results.output]), + files = depset(files_info), ), ] + android_lint_results.providers diff --git a/rules/attrs.bzl b/rules/attrs.bzl index 1945a4e..44c292c 100644 --- a/rules/attrs.bzl +++ b/rules/attrs.bzl @@ -77,5 +77,11 @@ ATTRS = dict( default = [], doc = "Custom lint rules to run.", ), + output_formats = attr.string_list( + mandatory = False, + allow_empty = False, + default = ["xml"], + doc = "List of output formats to produce. Supported [xml, html]", + ), _use_auto_exec_groups = attr.bool(default = True), ) diff --git a/rules/impl.bzl b/rules/impl.bzl index 36f14c9..70c6c49 100644 --- a/rules/impl.bzl +++ b/rules/impl.bzl @@ -19,7 +19,7 @@ def _run_android_lint( ctx, android_lint, module_name, - output, + xml_output, html_output, srcs, deps, @@ -44,7 +44,7 @@ def _run_android_lint( ctx: The target context android_lint: The Android Lint binary to use module_name: The name of the module - output: The output file + xml_output: The xml_output file srcs: The source files deps: Depset of aars and jars to include on the classpath resource_files: The Android resource files @@ -64,7 +64,7 @@ def _run_android_lint( android_lint_skip_bytecode_verifier: Disables bytecode verification """ inputs = [] - outputs = [output, html_output] + outputs = [] args = ctx.actions.args() args.set_param_file_format("multiline") @@ -115,16 +115,14 @@ def _run_android_lint( if android_lint_enable_check_dependencies: args.add("--enable-check-dependencies") - # Declare the output file - args.add("--output", output) - outputs.append(output) - - args.add("--html-output", html_output) - outputs.append(html_output) - - label = ctx.attr.android_home.label - if ctx.attr.android_home: - args.add("--android_home", label.workspace_root) + if xml_output != None: + args.add("--xml-output", xml_output) + outputs.append(xml_output) + if html_output != None: + args.add("--html-output", html_output) + outputs.append(html_output) + if len(outputs) == 0: + fail("Lint cannot have no outputs!") ctx.actions.run( mnemonic = "AndroidLint", @@ -171,7 +169,7 @@ def process_android_lint_issues(ctx, regenerate): regenerate: Whether to regenerate the baseline files Returns: - A struct containing the output file and the providers + A struct containing the output files and the providers """ # Append the Android manifest file. Lint requires that the input manifest files be named @@ -205,13 +203,20 @@ def process_android_lint_issues(ctx, regenerate): _utils.list_or_depset_to_list(_utils.get_android_lint_toolchain(ctx).android_lint_config.files), ) - output = ctx.actions.declare_file("{}.xml".format(ctx.label.name)) - html_output = ctx.actions.declare_file("{}.html".format(ctx.label.name)) + baseline = getattr(ctx.file, "baseline", None) + xml_output = None + html_output = None + for output_format in ctx.attr.output_formats: + if output_format == "xml": + xml_output = ctx.actions.declare_file("{}.xml".format(ctx.label.name)) + if output_format == "html": + html_output = ctx.actions.declare_file("{}.html".format(ctx.label.name)) + _run_android_lint( ctx, android_lint = _utils.only(_utils.list_or_depset_to_list(_utils.get_android_lint_toolchain(ctx).android_lint.files)), module_name = _get_module_name(ctx), - output = output, + xml_output = xml_output, html_output = html_output, srcs = ctx.files.srcs, deps = depset(transitive = deps), @@ -220,7 +225,7 @@ def process_android_lint_issues(ctx, regenerate): compile_sdk_version = _utils.get_android_lint_toolchain(ctx).compile_sdk_version, java_language_level = _utils.get_android_lint_toolchain(ctx).java_language_level, kotlin_language_level = _utils.get_android_lint_toolchain(ctx).kotlin_language_level, - baseline = getattr(ctx.file, "baseline", None), + baseline = baseline, config = config, warnings_as_errors = ctx.attr.warnings_as_errors, custom_rules = ctx.files.custom_rules, @@ -233,10 +238,14 @@ def process_android_lint_issues(ctx, regenerate): ) return struct( - output = output, + baseline = baseline, + xml_output = xml_output, + html_output = html_output, providers = [ _AndroidLintResultsInfo( - output = output, + baseline = baseline, + xml_output = xml_output, + html_output = html_output, ), ], ) diff --git a/rules/providers.bzl b/rules/providers.bzl index 2992a84..8cd359b 100644 --- a/rules/providers.bzl +++ b/rules/providers.bzl @@ -4,6 +4,8 @@ AndroidLintResultsInfo = provider( "Info needed to evaluate lint results", fields = { - "output": "The Android Lint baseline output", + "baseline": "The Android Lint baseline output", + "xml_output": "The Android Lint xml output", + "html_output": "The Android Lint html output", }, ) diff --git a/src/cli/AndroidLintActionArgs.kt b/src/cli/AndroidLintActionArgs.kt index 6d78f2f..b1a9643 100644 --- a/src/cli/AndroidLintActionArgs.kt +++ b/src/cli/AndroidLintActionArgs.kt @@ -32,17 +32,17 @@ internal class AndroidLintActionArgs( transform = argsParserPathTransformer, ) - val output: Path by parser.storing( - names = arrayOf("--output"), + val xmlOutput: Path? by parser.storing( + names = arrayOf("--xml-output"), help = "", transform = argsParserPathTransformer, - ) + ).default { null } - val htmlOutput: Path by parser.storing( + val htmlOutput: Path? by parser.storing( names = arrayOf("--html-output"), help = "", transform = argsParserPathTransformer, - ) + ).default { null } val resources: List by parser.adding( names = arrayOf("--resource"), diff --git a/src/cli/AndroidLintRunner.kt b/src/cli/AndroidLintRunner.kt index 217193b..93f6782 100644 --- a/src/cli/AndroidLintRunner.kt +++ b/src/cli/AndroidLintRunner.kt @@ -94,10 +94,6 @@ internal class AndroidLintRunner { projectFilePath.pathString, "--path-variables", "PWD=$rootDirPath", - "--xml", - actionArgs.output.pathString, - "--html", - actionArgs.htmlOutput.pathString, "--exitcode", "--compile-sdk-version", actionArgs.compileSdkVersion, @@ -115,6 +111,16 @@ internal class AndroidLintRunner { cacheDirectoryPath.pathString, "--client-id", "cli", ) + if (actionArgs.xmlOutput != null) { + args.add("--xml") + args.add(actionArgs.xmlOutput!!.pathString) + } + + if (actionArgs.htmlOutput != null) { + args.add("--html") + args.add(actionArgs.htmlOutput!!.pathString) + } + if (actionArgs.warningsAsErrors) { args.add("-Werror") } else { diff --git a/tests/src/cli/AndroidLintActionArgsTest.kt b/tests/src/cli/AndroidLintActionArgsTest.kt index 01e77e9..316726a 100644 --- a/tests/src/cli/AndroidLintActionArgsTest.kt +++ b/tests/src/cli/AndroidLintActionArgsTest.kt @@ -19,8 +19,10 @@ class AndroidLintActionArgsTest { "path/to/cli.jar", "--src", "path/to/Foo.kt", - "--output", - "output.jar", + "--xml-output", + "xml_output.xml", + "--html-output", + "html_output.html", "--resource", "path/to/resource/strings.xml", "--android-manifest", @@ -54,7 +56,8 @@ class AndroidLintActionArgsTest { assertThat(parseArgs.label).isEqualTo("test") assertThat(parseArgs.srcs).containsExactly(Paths.get("path/to/Foo.kt")) - assertThat(parseArgs.output).isEqualTo(Paths.get("output.jar")) + assertThat(parseArgs.xmlOutput).isEqualTo(Paths.get("xml_output.xml")) + assertThat(parseArgs.htmlOutput).isEqualTo(Paths.get("html_output.html")) assertThat(parseArgs.resources).containsExactly(Paths.get("path/to/resource/strings.xml")) assertThat(parseArgs.baselineFile).isEqualTo(Paths.get("lib_lint_baseline.xml")) assertThat(parseArgs.config).isEqualTo(Paths.get("lint_config.xml")) From 9c4626f4dee401ce88a27cf00411e1f5e5789a44 Mon Sep 17 00:00:00 2001 From: Edbert Chan Date: Wed, 24 Apr 2024 14:02:15 -0700 Subject: [PATCH 3/4] fixing some output files --- rules/android_lint.bzl | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/rules/android_lint.bzl b/rules/android_lint.bzl index 4668539..fa6209a 100644 --- a/rules/android_lint.bzl +++ b/rules/android_lint.bzl @@ -21,12 +21,17 @@ def _impl(ctx): android_lint_results = _process_android_lint_issues(ctx, regenerate = False) inputs = [] - inputs.append(android_lint_results.output) + inputs.append(android_lint_results.xml_output) + files_output = [] + if android_lint_results.xml_output != None: + files_output.append(android_lint_results.xml_output) + if android_lint_results.html_output != None: + files_output.append(android_lint_results.html_output) return [ DefaultInfo( runfiles = ctx.runfiles(files = inputs), - files = depset([android_lint_results.output]), + files = depset(files_output), ), ] + android_lint_results.providers From ff6352056d54fe9c9c64e9c3a4149d937cb84491 Mon Sep 17 00:00:00 2001 From: Edbert Chan Date: Wed, 24 Apr 2024 14:06:30 -0700 Subject: [PATCH 4/4] fixing docs --- rules/impl.bzl | 1 + 1 file changed, 1 insertion(+) diff --git a/rules/impl.bzl b/rules/impl.bzl index 70c6c49..0c91e53 100644 --- a/rules/impl.bzl +++ b/rules/impl.bzl @@ -45,6 +45,7 @@ def _run_android_lint( android_lint: The Android Lint binary to use module_name: The name of the module xml_output: The xml_output file + html_output: The html_output file srcs: The source files deps: Depset of aars and jars to include on the classpath resource_files: The Android resource files