diff --git a/java/lint.go b/java/lint.go index aa308e669..a77daa85d 100644 --- a/java/lint.go +++ b/java/lint.go @@ -200,7 +200,7 @@ func (l *linter) writeLintProjectXML(ctx android.ModuleContext, rule *android.Ru srcJarList := zipSyncCmd(ctx, rule, srcJarDir, l.srcJars) cmd := rule.Command(). - BuiltTool("lint-project-xml"). + BuiltTool("lint_project_xml"). FlagWithOutput("--project_out ", projectXMLPath). FlagWithOutput("--config_out ", configXMLPath). FlagWithArg("--name ", ctx.ModuleName()) @@ -279,6 +279,19 @@ func (l *linter) generateManifest(ctx android.ModuleContext, rule *android.RuleB return manifestPath } +func (l *linter) getBaselineFilepath(ctx android.ModuleContext) android.OptionalPath { + var lintBaseline android.OptionalPath + if lintFilename := proptools.StringDefault(l.properties.Lint.Baseline_filename, "lint-baseline.xml"); lintFilename != "" { + if String(l.properties.Lint.Baseline_filename) != "" { + // if manually specified, we require the file to exist + lintBaseline = android.OptionalPathForPath(android.PathForModuleSrc(ctx, lintFilename)) + } else { + lintBaseline = android.ExistentPathForSource(ctx, ctx.ModuleDir(), lintFilename) + } + } + return lintBaseline +} + func (l *linter) lint(ctx android.ModuleContext) { if !l.enabled() { return @@ -381,17 +394,9 @@ func (l *linter) lint(ctx android.ModuleContext) { cmd.FlagWithArg("--check ", checkOnly) } - if lintFilename := proptools.StringDefault(l.properties.Lint.Baseline_filename, "lint-baseline.xml"); lintFilename != "" { - var lintBaseline android.OptionalPath - if String(l.properties.Lint.Baseline_filename) != "" { - // if manually specified, we require the file to exist - lintBaseline = android.OptionalPathForPath(android.PathForModuleSrc(ctx, lintFilename)) - } else { - lintBaseline = android.ExistentPathForSource(ctx, ctx.ModuleDir(), lintFilename) - } - if lintBaseline.Valid() { - cmd.FlagWithInput("--baseline ", lintBaseline.Path()) - } + lintBaseline := l.getBaselineFilepath(ctx) + if lintBaseline.Valid() { + cmd.FlagWithInput("--baseline ", lintBaseline.Path()) } cmd.Text("|| (").Text("if [ -e").Input(text).Text("]; then cat").Input(text).Text("; fi; exit 7)") diff --git a/scripts/Android.bp b/scripts/Android.bp index c54b2bcbd..b0a8669c2 100644 --- a/scripts/Android.bp +++ b/scripts/Android.bp @@ -219,14 +219,25 @@ python_library_host { } python_binary_host { - name: "lint-project-xml", - main: "lint-project-xml.py", + name: "lint_project_xml", + main: "lint_project_xml.py", srcs: [ - "lint-project-xml.py", + "lint_project_xml.py", ], libs: ["ninja_rsp"], } +python_test_host { + name: "lint_project_xml_test", + main: "lint_project_xml_test.py", + srcs: [ + "lint_project_xml_test.py", + "lint_project_xml.py", + ], + libs: ["ninja_rsp"], + test_suites: ["general-tests"], +} + python_binary_host { name: "gen-kotlin-build-file.py", main: "gen-kotlin-build-file.py", diff --git a/scripts/lint-project-xml.py b/scripts/lint_project_xml.py similarity index 85% rename from scripts/lint-project-xml.py rename to scripts/lint_project_xml.py index f1ef85dcc..74aebc10a 100755 --- a/scripts/lint-project-xml.py +++ b/scripts/lint_project_xml.py @@ -18,6 +18,7 @@ """This file generates project.xml and lint.xml files used to drive the Android Lint CLI tool.""" import argparse +from xml.dom import minidom from ninja_rsp import NinjaRspFileReader @@ -73,6 +74,8 @@ def parse_args(): help='file containing the module\'s manifest.') parser.add_argument('--merged_manifest', dest='merged_manifest', help='file containing merged manifest for the module and its dependencies.') + parser.add_argument('--baseline', dest='baseline_path', + help='file containing baseline lint issues.') parser.add_argument('--library', dest='library', action='store_true', help='mark the module as a library.') parser.add_argument('--test', dest='test', action='store_true', @@ -90,6 +93,8 @@ def parse_args(): help='treat a lint issue as a warning.') group.add_argument('--disable_check', dest='checks', action=check_action('ignore'), default=[], help='disable a lint issue.') + group.add_argument('--disallowed_issues', dest='disallowed_issues', default=[], + help='lint issues disallowed in the baseline file') return parser.parse_args() @@ -134,10 +139,30 @@ def write_config_xml(f, args): f.write("\n") +def check_baseline_for_disallowed_issues(baseline, forced_checks): + issues_element = baseline.documentElement + if issues_element.tagName != 'issues': + raise RuntimeError('expected issues tag at root') + issues = issues_element.getElementsByTagName('issue') + disallwed = set() + for issue in issues: + id = issue.getAttribute('id') + if id in forced_checks: + disallwed.add(id) + return disallwed + + def main(): """Program entry point.""" args = parse_args() + if args.baseline_path: + baseline = minidom.parse(args.baseline_path) + diallowed_issues = check_baseline_for_disallowed_issues(baseline, args.disallowed_issues) + if bool(diallowed_issues): + raise RuntimeError('disallowed issues %s found in lint baseline file %s for module %s' + % (diallowed_issues, args.baseline_path, args.name)) + if args.project_out: with open(args.project_out, 'w') as f: write_project_xml(f, args) diff --git a/scripts/lint_project_xml_test.py b/scripts/lint_project_xml_test.py new file mode 100644 index 000000000..344691d00 --- /dev/null +++ b/scripts/lint_project_xml_test.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2021 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +"""Unit tests for lint_project_xml.py.""" + +import unittest +from xml.dom import minidom + +import lint_project_xml + + +class CheckBaselineForDisallowedIssuesTest(unittest.TestCase): + """Unit tests for check_baseline_for_disallowed_issues function.""" + + baseline_xml = minidom.parseString( + '\n' + '\n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + '\n') + + def test_check_baseline_for_disallowed_issues(self): + disallowed_issues = lint_project_xml.check_baseline_for_disallowed_issues(self.baseline_xml, ["foo", "bar", "qux"]) + self.assertEqual({"foo", "bar"}, disallowed_issues) + + +if __name__ == '__main__': + unittest.main(verbosity=2)