File: lint-project-xml.py

package info (click to toggle)
golang-android-soong 0.0~git20201014.17e97d9-4
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 7,680 kB
  • sloc: python: 3,000; sh: 1,780; cpp: 66; makefile: 5
file content (151 lines) | stat: -rwxr-xr-x 6,630 bytes parent folder | download | duplicates (2)
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
#!/usr/bin/env python3
#
# Copyright (C) 2018 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.
#

"""This file generates project.xml and lint.xml files used to drive the Android Lint CLI tool."""

import argparse

from ninja_rsp import NinjaRspFileReader


def check_action(check_type):
  """
  Returns an action that appends a tuple of check_type and the argument to the dest.
  """
  class CheckAction(argparse.Action):
    def __init__(self, option_strings, dest, nargs=None, **kwargs):
      if nargs is not None:
        raise ValueError("nargs must be None, was %s" % nargs)
      super(CheckAction, self).__init__(option_strings, dest, **kwargs)
    def __call__(self, parser, namespace, values, option_string=None):
      checks = getattr(namespace, self.dest, [])
      checks.append((check_type, values))
      setattr(namespace, self.dest, checks)
  return CheckAction


def parse_args():
  """Parse commandline arguments."""

  def convert_arg_line_to_args(arg_line):
    for arg in arg_line.split():
      if arg.startswith('#'):
        return
      if not arg.strip():
        continue
      yield arg

  parser = argparse.ArgumentParser(fromfile_prefix_chars='@')
  parser.convert_arg_line_to_args = convert_arg_line_to_args
  parser.add_argument('--project_out', dest='project_out',
                      help='file to which the project.xml contents will be written.')
  parser.add_argument('--config_out', dest='config_out',
                      help='file to which the lint.xml contents will be written.')
  parser.add_argument('--name', dest='name',
                      help='name of the module.')
  parser.add_argument('--srcs', dest='srcs', action='append', default=[],
                      help='file containing whitespace separated list of source files.')
  parser.add_argument('--generated_srcs', dest='generated_srcs', action='append', default=[],
                      help='file containing whitespace separated list of generated source files.')
  parser.add_argument('--resources', dest='resources', action='append', default=[],
                      help='file containing whitespace separated list of resource files.')
  parser.add_argument('--classes', dest='classes', action='append', default=[],
                      help='file containing the module\'s classes.')
  parser.add_argument('--classpath', dest='classpath', action='append', default=[],
                      help='file containing classes from dependencies.')
  parser.add_argument('--extra_checks_jar', dest='extra_checks_jars', action='append', default=[],
                      help='file containing extra lint checks.')
  parser.add_argument('--manifest', dest='manifest',
                      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('--library', dest='library', action='store_true',
                      help='mark the module as a library.')
  parser.add_argument('--test', dest='test', action='store_true',
                      help='mark the module as a test.')
  parser.add_argument('--cache_dir', dest='cache_dir',
                      help='directory to use for cached file.')
  parser.add_argument('--root_dir', dest='root_dir',
                      help='directory to use for root dir.')
  group = parser.add_argument_group('check arguments', 'later arguments override earlier ones.')
  group.add_argument('--fatal_check', dest='checks', action=check_action('fatal'), default=[],
                     help='treat a lint issue as a fatal error.')
  group.add_argument('--error_check', dest='checks', action=check_action('error'), default=[],
                     help='treat a lint issue as an error.')
  group.add_argument('--warning_check', dest='checks', action=check_action('warning'), default=[],
                     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.')
  return parser.parse_args()


def write_project_xml(f, args):
  test_attr = "test='true' " if args.test else ""

  f.write("<?xml version='1.0' encoding='utf-8'?>\n")
  f.write("<project>\n")
  if args.root_dir:
    f.write("  <root dir='%s' />\n" % args.root_dir)
  f.write("  <module name='%s' android='true' %sdesugar='full' >\n" % (args.name, "library='true' " if args.library else ""))
  if args.manifest:
    f.write("    <manifest file='%s' %s/>\n" % (args.manifest, test_attr))
  if args.merged_manifest:
    f.write("    <merged-manifest file='%s' %s/>\n" % (args.merged_manifest, test_attr))
  for src_file in args.srcs:
    for src in NinjaRspFileReader(src_file):
      f.write("    <src file='%s' %s/>\n" % (src, test_attr))
  for src_file in args.generated_srcs:
    for src in NinjaRspFileReader(src_file):
      f.write("    <src file='%s' generated='true' %s/>\n" % (src, test_attr))
  for res_file in args.resources:
    for res in NinjaRspFileReader(res_file):
      f.write("    <resource file='%s' %s/>\n" % (res, test_attr))
  for classes in args.classes:
    f.write("    <classes jar='%s' />\n" % classes)
  for classpath in args.classpath:
    f.write("    <classpath jar='%s' />\n" % classpath)
  for extra in args.extra_checks_jars:
    f.write("    <lint-checks jar='%s' />\n" % extra)
  f.write("  </module>\n")
  if args.cache_dir:
    f.write("  <cache dir='%s'/>\n" % args.cache_dir)
  f.write("</project>\n")


def write_config_xml(f, args):
  f.write("<?xml version='1.0' encoding='utf-8'?>\n")
  f.write("<lint>\n")
  for check in args.checks:
    f.write("  <issue id='%s' severity='%s' />\n" % (check[1], check[0]))
  f.write("</lint>\n")


def main():
  """Program entry point."""
  args = parse_args()

  if args.project_out:
    with open(args.project_out, 'w') as f:
      write_project_xml(f, args)

  if args.config_out:
    with open(args.config_out, 'w') as f:
      write_config_xml(f, args)


if __name__ == '__main__':
  main()