OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # | 2 # |
3 # Copyright (c) 2013 The Chromium Authors. All rights reserved. | 3 # Copyright (c) 2013 The Chromium Authors. All rights reserved. |
4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
6 | 6 |
7 """Runs Android's lint tool.""" | 7 """Runs Android's lint tool.""" |
8 | 8 |
9 | 9 |
10 import argparse | 10 import argparse |
11 import os | 11 import os |
12 import re | |
12 import sys | 13 import sys |
13 import traceback | 14 import traceback |
14 from xml.dom import minidom | 15 from xml.dom import minidom |
15 | 16 |
16 from util import build_utils | 17 from util import build_utils |
17 | 18 |
18 | 19 |
19 _SRC_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), | 20 _SRC_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), |
20 '..', '..', '..')) | 21 '..', '..', '..')) |
21 | 22 |
22 | 23 |
23 def _OnStaleMd5(changes, lint_path, config_path, processed_config_path, | 24 def _OnStaleMd5(changes, lint_path, config_path, processed_config_path, |
24 manifest_path, result_path, product_dir, sources, jar_path, | 25 manifest_path, result_path, product_dir, sources, jar_path, |
25 cache_dir, resource_dir=None, can_fail_build=False, | 26 cache_dir, resource_dir=None, classpath=None, |
26 silent=False): | 27 can_fail_build=False, silent=False): |
27 | 28 |
28 def _RelativizePath(path): | 29 def _RelativizePath(path): |
29 """Returns relative path to top-level src dir. | 30 """Returns relative path to top-level src dir. |
30 | 31 |
31 Args: | 32 Args: |
32 path: A path relative to cwd. | 33 path: A path relative to cwd. |
33 """ | 34 """ |
34 return os.path.relpath(os.path.abspath(path), _SRC_ROOT) | 35 return os.path.relpath(os.path.abspath(path), _SRC_ROOT) |
35 | 36 |
36 def _ProcessConfigFile(): | 37 def _ProcessConfigFile(): |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
72 error = '%s %s: %s [warning]' % (path, message, issue_id) | 73 error = '%s %s: %s [warning]' % (path, message, issue_id) |
73 print >> sys.stderr, error.encode('utf-8') | 74 print >> sys.stderr, error.encode('utf-8') |
74 for attr in ['errorLine1', 'errorLine2']: | 75 for attr in ['errorLine1', 'errorLine2']: |
75 error_line = issue.getAttribute(attr) | 76 error_line = issue.getAttribute(attr) |
76 if error_line: | 77 if error_line: |
77 print >> sys.stderr, error_line.encode('utf-8') | 78 print >> sys.stderr, error_line.encode('utf-8') |
78 return len(issues) | 79 return len(issues) |
79 | 80 |
80 # Need to include all sources when a resource_dir is set so that resources are | 81 # Need to include all sources when a resource_dir is set so that resources are |
81 # not marked as unused. | 82 # not marked as unused. |
83 # TODO(agrieve): Figure out how IDEs make do incremental lint. | |
jbudorick
2016/03/31 20:05:26
s/make// ?
agrieve
2016/04/01 00:45:06
Done.
| |
82 if not resource_dir and changes.AddedOrModifiedOnly(): | 84 if not resource_dir and changes.AddedOrModifiedOnly(): |
83 changed_paths = set(changes.IterChangedPaths()) | 85 changed_paths = set(changes.IterChangedPaths()) |
84 sources = [s for s in sources if s in changed_paths] | 86 sources = [s for s in sources if s in changed_paths] |
85 | 87 |
86 with build_utils.TempDir() as temp_dir: | 88 with build_utils.TempDir() as temp_dir: |
87 _ProcessConfigFile() | 89 _ProcessConfigFile() |
88 | 90 |
89 cmd = [ | 91 cmd = [ |
90 _RelativizePath(lint_path), '-Werror', '--exitcode', '--showall', | 92 _RelativizePath(lint_path), '-Werror', '--exitcode', '--showall', |
91 '--xml', _RelativizePath(result_path), | 93 '--xml', _RelativizePath(result_path), |
92 ] | 94 ] |
93 if jar_path: | 95 if jar_path: |
96 # --classpath is just for .class files for this one target. | |
94 cmd.extend(['--classpath', _RelativizePath(jar_path)]) | 97 cmd.extend(['--classpath', _RelativizePath(jar_path)]) |
95 if processed_config_path: | 98 if processed_config_path: |
96 cmd.extend(['--config', _RelativizePath(processed_config_path)]) | 99 cmd.extend(['--config', _RelativizePath(processed_config_path)]) |
97 if resource_dir: | 100 if resource_dir: |
98 cmd.extend(['--resources', _RelativizePath(resource_dir)]) | 101 cmd.extend(['--resources', _RelativizePath(resource_dir)]) |
102 if classpath: | |
103 # --libraries is the classpath (excluding active target). | |
jbudorick
2016/03/31 20:05:26
this naming is now less than stellar, with jar_pat
agrieve
2016/04/01 00:45:06
Agree. Took me many minutes of reading through its
| |
104 cp = ':'.join(_RelativizePath(p) for p in classpath) | |
105 cmd.extend(['--libraries', cp]) | |
99 | 106 |
100 # There may be multiple source files with the same basename (but in | 107 # There may be multiple source files with the same basename (but in |
101 # different directories). It is difficult to determine what part of the path | 108 # different directories). It is difficult to determine what part of the path |
102 # corresponds to the java package, and so instead just link the source files | 109 # corresponds to the java package, and so instead just link the source files |
103 # into temporary directories (creating a new one whenever there is a name | 110 # into temporary directories (creating a new one whenever there is a name |
104 # conflict). | 111 # conflict). |
105 src_dirs = [] | 112 src_dirs = [] |
106 def NewSourceDir(): | 113 def NewSourceDir(): |
107 new_dir = os.path.join(temp_dir, str(len(src_dirs))) | 114 new_dir = os.path.join(temp_dir, str(len(src_dirs))) |
108 os.mkdir(new_dir) | 115 os.mkdir(new_dir) |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
228 parser.add_argument('--config-path', | 235 parser.add_argument('--config-path', |
229 help='Path to lint suppressions file.') | 236 help='Path to lint suppressions file.') |
230 parser.add_argument('--enable', action='store_true', | 237 parser.add_argument('--enable', action='store_true', |
231 help='Run lint instead of just touching stamp.') | 238 help='Run lint instead of just touching stamp.') |
232 parser.add_argument('--jar-path', | 239 parser.add_argument('--jar-path', |
233 help='Jar file containing class files.') | 240 help='Jar file containing class files.') |
234 parser.add_argument('--java-files', | 241 parser.add_argument('--java-files', |
235 help='Paths to java files.') | 242 help='Paths to java files.') |
236 parser.add_argument('--manifest-path', | 243 parser.add_argument('--manifest-path', |
237 help='Path to AndroidManifest.xml') | 244 help='Path to AndroidManifest.xml') |
245 parser.add_argument('--classpath', help='Classpath for the target') | |
238 parser.add_argument('--processed-config-path', | 246 parser.add_argument('--processed-config-path', |
239 help='Path to processed lint suppressions file.') | 247 help='Path to processed lint suppressions file.') |
240 parser.add_argument('--resource-dir', | 248 parser.add_argument('--resource-dir', |
241 help='Path to resource dir.') | 249 help='Path to resource dir.') |
242 parser.add_argument('--silent', action='store_true', | 250 parser.add_argument('--silent', action='store_true', |
243 help='If set, script will not log anything.') | 251 help='If set, script will not log anything.') |
244 parser.add_argument('--src-dirs', | 252 parser.add_argument('--src-dirs', |
245 help='Directories containing java files.') | 253 help='Directories containing java files.') |
246 parser.add_argument('--stamp', | 254 parser.add_argument('--stamp', |
247 help='Path to touch on success.') | 255 help='Path to touch on success.') |
248 | 256 |
249 args = parser.parse_args() | 257 args = parser.parse_args(build_utils.ExpandFileArgs(sys.argv[1:])) |
250 | 258 |
251 if args.enable: | 259 if args.enable: |
252 sources = [] | 260 sources = [] |
253 if args.src_dirs: | 261 if args.src_dirs: |
254 src_dirs = build_utils.ParseGypList(args.src_dirs) | 262 src_dirs = build_utils.ParseGypList(args.src_dirs) |
255 sources = build_utils.FindInDirectories(src_dirs, '*.java') | 263 sources = build_utils.FindInDirectories(src_dirs, '*.java') |
256 elif args.java_files: | 264 elif args.java_files: |
257 sources = build_utils.ParseGypList(args.java_files) | 265 sources = build_utils.ParseGypList(args.java_files) |
258 | 266 |
259 if args.config_path and not args.processed_config_path: | 267 if args.config_path and not args.processed_config_path: |
260 parser.error('--config-path specified without --processed-config-path') | 268 parser.error('--config-path specified without --processed-config-path') |
261 elif args.processed_config_path and not args.config_path: | 269 elif args.processed_config_path and not args.config_path: |
262 parser.error('--processed-config-path specified without --config-path') | 270 parser.error('--processed-config-path specified without --config-path') |
263 | 271 |
264 input_paths = [ | 272 input_paths = [ |
265 args.lint_path, | 273 args.lint_path, |
266 args.platform_xml_path, | 274 args.platform_xml_path, |
267 ] | 275 ] |
268 if args.config_path: | 276 if args.config_path: |
269 input_paths.append(args.config_path) | 277 input_paths.append(args.config_path) |
270 if args.jar_path: | 278 if args.jar_path: |
271 input_paths.append(args.jar_path) | 279 input_paths.append(args.jar_path) |
272 if args.manifest_path: | 280 if args.manifest_path: |
273 input_paths.append(args.manifest_path) | 281 input_paths.append(args.manifest_path) |
274 if args.resource_dir: | 282 if args.resource_dir: |
275 input_paths.extend(build_utils.FindInDirectory(args.resource_dir, '*')) | 283 input_paths.extend(build_utils.FindInDirectory(args.resource_dir, '*')) |
276 if sources: | 284 if sources: |
277 input_paths.extend(sources) | 285 input_paths.extend(sources) |
286 classpath = None | |
287 if args.classpath: | |
288 classpath = build_utils.ParseGypList(args.classpath) | |
289 # Faster to use .interface.jar. | |
290 classpath = [re.sub(r'\.jar$', '.interface.jar', p) for p in classpath] | |
jbudorick
2016/03/31 20:05:26
Do we know that a corresponding .interface.jar cla
agrieve
2016/04/01 00:45:06
Done, but had to rebase onto: https://codereview.c
| |
291 input_paths.extend(sources) | |
278 | 292 |
279 input_strings = [] | 293 input_strings = [] |
280 if args.processed_config_path: | 294 if args.processed_config_path: |
281 input_strings.append(args.processed_config_path) | 295 input_strings.append(args.processed_config_path) |
282 | 296 |
283 output_paths = [ args.result_path ] | 297 output_paths = [ args.result_path ] |
284 | 298 |
285 build_utils.CallAndWriteDepfileIfStale( | 299 build_utils.CallAndWriteDepfileIfStale( |
286 lambda changes: _OnStaleMd5(changes, args.lint_path, | 300 lambda changes: _OnStaleMd5(changes, args.lint_path, |
287 args.config_path, | 301 args.config_path, |
288 args.processed_config_path, | 302 args.processed_config_path, |
289 args.manifest_path, args.result_path, | 303 args.manifest_path, args.result_path, |
290 args.product_dir, sources, | 304 args.product_dir, sources, |
291 args.jar_path, | 305 args.jar_path, |
292 args.cache_dir, | 306 args.cache_dir, |
293 resource_dir=args.resource_dir, | 307 resource_dir=args.resource_dir, |
308 classpath=classpath, | |
294 can_fail_build=args.can_fail_build, | 309 can_fail_build=args.can_fail_build, |
295 silent=args.silent), | 310 silent=args.silent), |
296 args, | 311 args, |
297 input_paths=input_paths, | 312 input_paths=input_paths, |
298 input_strings=input_strings, | 313 input_strings=input_strings, |
299 output_paths=output_paths, | 314 output_paths=output_paths, |
300 pass_changes=True) | 315 pass_changes=True) |
301 | 316 |
302 | 317 |
303 if __name__ == '__main__': | 318 if __name__ == '__main__': |
304 sys.exit(main()) | 319 sys.exit(main()) |
OLD | NEW |