| 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 sys | 12 import sys |
| 13 import traceback | 13 import traceback |
| 14 from xml.dom import minidom | 14 from xml.dom import minidom |
| 15 | 15 |
| 16 from util import build_utils | 16 from util import build_utils |
| 17 | 17 |
| 18 | 18 |
| 19 _SRC_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), | 19 _SRC_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), |
| 20 '..', '..', '..')) | 20 '..', '..', '..')) |
| 21 | 21 |
| 22 | 22 |
| 23 def _OnStaleMd5(changes, lint_path, config_path, processed_config_path, | 23 def _OnStaleMd5(changes, lint_path, config_path, processed_config_path, |
| 24 manifest_path, result_path, product_dir, sources, jar_path, | 24 manifest_path, result_path, product_dir, sources, jar_path, |
| 25 cache_dir, resource_dir=None, can_fail_build=False, | 25 cache_dir, resource_dir=None, classpath=None, |
| 26 silent=False): | 26 can_fail_build=False, silent=False): |
| 27 | 27 |
| 28 def _RelativizePath(path): | 28 def _RelativizePath(path): |
| 29 """Returns relative path to top-level src dir. | 29 """Returns relative path to top-level src dir. |
| 30 | 30 |
| 31 Args: | 31 Args: |
| 32 path: A path relative to cwd. | 32 path: A path relative to cwd. |
| 33 """ | 33 """ |
| 34 return os.path.relpath(os.path.abspath(path), _SRC_ROOT) | 34 return os.path.relpath(os.path.abspath(path), _SRC_ROOT) |
| 35 | 35 |
| 36 def _ProcessConfigFile(): | 36 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) | 72 error = '%s %s: %s [warning]' % (path, message, issue_id) |
| 73 print >> sys.stderr, error.encode('utf-8') | 73 print >> sys.stderr, error.encode('utf-8') |
| 74 for attr in ['errorLine1', 'errorLine2']: | 74 for attr in ['errorLine1', 'errorLine2']: |
| 75 error_line = issue.getAttribute(attr) | 75 error_line = issue.getAttribute(attr) |
| 76 if error_line: | 76 if error_line: |
| 77 print >> sys.stderr, error_line.encode('utf-8') | 77 print >> sys.stderr, error_line.encode('utf-8') |
| 78 return len(issues) | 78 return len(issues) |
| 79 | 79 |
| 80 # Need to include all sources when a resource_dir is set so that resources are | 80 # Need to include all sources when a resource_dir is set so that resources are |
| 81 # not marked as unused. | 81 # not marked as unused. |
| 82 # TODO(agrieve): Figure out how IDEs do incremental linting. |
| 82 if not resource_dir and changes.AddedOrModifiedOnly(): | 83 if not resource_dir and changes.AddedOrModifiedOnly(): |
| 83 changed_paths = set(changes.IterChangedPaths()) | 84 changed_paths = set(changes.IterChangedPaths()) |
| 84 sources = [s for s in sources if s in changed_paths] | 85 sources = [s for s in sources if s in changed_paths] |
| 85 | 86 |
| 86 with build_utils.TempDir() as temp_dir: | 87 with build_utils.TempDir() as temp_dir: |
| 87 _ProcessConfigFile() | 88 _ProcessConfigFile() |
| 88 | 89 |
| 89 cmd = [ | 90 cmd = [ |
| 90 _RelativizePath(lint_path), '-Werror', '--exitcode', '--showall', | 91 _RelativizePath(lint_path), '-Werror', '--exitcode', '--showall', |
| 91 '--xml', _RelativizePath(result_path), | 92 '--xml', _RelativizePath(result_path), |
| 92 ] | 93 ] |
| 93 if jar_path: | 94 if jar_path: |
| 95 # --classpath is just for .class files for this one target. |
| 94 cmd.extend(['--classpath', _RelativizePath(jar_path)]) | 96 cmd.extend(['--classpath', _RelativizePath(jar_path)]) |
| 95 if processed_config_path: | 97 if processed_config_path: |
| 96 cmd.extend(['--config', _RelativizePath(processed_config_path)]) | 98 cmd.extend(['--config', _RelativizePath(processed_config_path)]) |
| 97 if resource_dir: | 99 if resource_dir: |
| 98 cmd.extend(['--resources', _RelativizePath(resource_dir)]) | 100 cmd.extend(['--resources', _RelativizePath(resource_dir)]) |
| 101 if classpath: |
| 102 # --libraries is the classpath (excluding active target). |
| 103 cp = ':'.join(_RelativizePath(p) for p in classpath) |
| 104 cmd.extend(['--libraries', cp]) |
| 99 | 105 |
| 100 # There may be multiple source files with the same basename (but in | 106 # 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 | 107 # 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 | 108 # 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 | 109 # into temporary directories (creating a new one whenever there is a name |
| 104 # conflict). | 110 # conflict). |
| 105 src_dirs = [] | 111 src_dirs = [] |
| 106 def NewSourceDir(): | 112 def NewSourceDir(): |
| 107 new_dir = os.path.join(temp_dir, str(len(src_dirs))) | 113 new_dir = os.path.join(temp_dir, str(len(src_dirs))) |
| 108 os.mkdir(new_dir) | 114 os.mkdir(new_dir) |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 228 parser.add_argument('--config-path', | 234 parser.add_argument('--config-path', |
| 229 help='Path to lint suppressions file.') | 235 help='Path to lint suppressions file.') |
| 230 parser.add_argument('--enable', action='store_true', | 236 parser.add_argument('--enable', action='store_true', |
| 231 help='Run lint instead of just touching stamp.') | 237 help='Run lint instead of just touching stamp.') |
| 232 parser.add_argument('--jar-path', | 238 parser.add_argument('--jar-path', |
| 233 help='Jar file containing class files.') | 239 help='Jar file containing class files.') |
| 234 parser.add_argument('--java-files', | 240 parser.add_argument('--java-files', |
| 235 help='Paths to java files.') | 241 help='Paths to java files.') |
| 236 parser.add_argument('--manifest-path', | 242 parser.add_argument('--manifest-path', |
| 237 help='Path to AndroidManifest.xml') | 243 help='Path to AndroidManifest.xml') |
| 244 parser.add_argument('--classpath', default=[], action='append', |
| 245 help='GYP-list of classpath .jar files') |
| 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 = [] |
| 287 for gyp_list in args.classpath: |
| 288 classpath.extend(build_utils.ParseGypList(gyp_list)) |
| 289 input_paths.extend(classpath) |
| 278 | 290 |
| 279 input_strings = [] | 291 input_strings = [] |
| 280 if args.processed_config_path: | 292 if args.processed_config_path: |
| 281 input_strings.append(args.processed_config_path) | 293 input_strings.append(args.processed_config_path) |
| 282 | 294 |
| 283 output_paths = [ args.result_path ] | 295 output_paths = [ args.result_path ] |
| 284 | 296 |
| 285 build_utils.CallAndWriteDepfileIfStale( | 297 build_utils.CallAndWriteDepfileIfStale( |
| 286 lambda changes: _OnStaleMd5(changes, args.lint_path, | 298 lambda changes: _OnStaleMd5(changes, args.lint_path, |
| 287 args.config_path, | 299 args.config_path, |
| 288 args.processed_config_path, | 300 args.processed_config_path, |
| 289 args.manifest_path, args.result_path, | 301 args.manifest_path, args.result_path, |
| 290 args.product_dir, sources, | 302 args.product_dir, sources, |
| 291 args.jar_path, | 303 args.jar_path, |
| 292 args.cache_dir, | 304 args.cache_dir, |
| 293 resource_dir=args.resource_dir, | 305 resource_dir=args.resource_dir, |
| 306 classpath=classpath, |
| 294 can_fail_build=args.can_fail_build, | 307 can_fail_build=args.can_fail_build, |
| 295 silent=args.silent), | 308 silent=args.silent), |
| 296 args, | 309 args, |
| 297 input_paths=input_paths, | 310 input_paths=input_paths, |
| 298 input_strings=input_strings, | 311 input_strings=input_strings, |
| 299 output_paths=output_paths, | 312 output_paths=output_paths, |
| 300 pass_changes=True) | 313 pass_changes=True, |
| 314 depfile_deps=classpath) |
| 301 | 315 |
| 302 | 316 |
| 303 if __name__ == '__main__': | 317 if __name__ == '__main__': |
| 304 sys.exit(main()) | 318 sys.exit(main()) |
| OLD | NEW |