| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # Copyright 2015 The Chromium Authors. All rights reserved. | 2 # Copyright 2015 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 # To integrate dartanalyze with our build system, we take an input file, run | 6 # To integrate dartanalyze with our build system, we take an input file, run |
| 7 # the analyzer on it, and write a stamp file if it passed. | 7 # the analyzer on it, and write a stamp file if it passed. |
| 8 | 8 |
| 9 # This script can either analyze a dartzip package, specified with the | 9 # This script analyzes a set of entrypoints specified with the --entrypoints |
| 10 # --dartzip-file flag, or a set of entrypoints specified with the --entrypoints | |
| 11 # flag. The location of the Dart SDK must be specified with the --dart-sdk | 10 # flag. The location of the Dart SDK must be specified with the --dart-sdk |
| 12 # flag. A stamp file can optionally be written with the location given by the | 11 # flag. A stamp file can optionally be written with the location given by the |
| 13 # --stamp-file flag. Any command line arguments not recognized by this script | 12 # --stamp-file flag. Any command line arguments not recognized by this script |
| 14 # are passed on to the Dart analyzer. | 13 # are passed on to the Dart analyzer. |
| 15 | 14 |
| 16 import argparse | 15 import argparse |
| 17 import glob | 16 import glob |
| 18 import os | 17 import os |
| 19 import re | 18 import re |
| 20 import shutil | 19 import shutil |
| 21 import subprocess | 20 import subprocess |
| 22 import sys | 21 import sys |
| 23 import tempfile | 22 import tempfile |
| 24 import zipfile | |
| 25 | 23 |
| 26 _IGNORED_PATTERNS = [ | 24 _IGNORED_PATTERNS = [ |
| 27 # Ignored because they're not indicative of specific errors. | 25 # Ignored because they're not indicative of specific errors. |
| 28 re.compile(r'^$'), | 26 re.compile(r'^$'), |
| 29 re.compile(r'^Analyzing \['), | 27 re.compile(r'^Analyzing \['), |
| 30 re.compile(r'^No issues found'), | 28 re.compile(r'^No issues found'), |
| 31 re.compile(r'^[0-9]+ errors? and [0-9]+ warnings? found.'), | 29 re.compile(r'^[0-9]+ errors? and [0-9]+ warnings? found.'), |
| 32 re.compile(r'^([0-9]+|No) (error|warning|issue)s? found.'), | 30 re.compile(r'^([0-9]+|No) (error|warning|issue)s? found.'), |
| 33 | 31 |
| 34 # TODO: It seems like this should be re-enabled evenutally. | 32 # TODO: It seems like this should be re-enabled evenutally. |
| (...skipping 21 matching lines...) Expand all Loading... |
| 56 errors = set(l for l in e.output.split('\n') | 54 errors = set(l for l in e.output.split('\n') |
| 57 if not any(p.match(l) for p in _IGNORED_PATTERNS)) | 55 if not any(p.match(l) for p in _IGNORED_PATTERNS)) |
| 58 for error in sorted(errors): | 56 for error in sorted(errors): |
| 59 if dirname is None: | 57 if dirname is None: |
| 60 print >> sys.stderr, error | 58 print >> sys.stderr, error |
| 61 else: | 59 else: |
| 62 print >> sys.stderr, error.replace(temp_dir + "/", dirname) | 60 print >> sys.stderr, error.replace(temp_dir + "/", dirname) |
| 63 return errors | 61 return errors |
| 64 | 62 |
| 65 | 63 |
| 66 def analyze_dartzip(dart_sdk, dartzip_file, stamp_file, args): | |
| 67 dartzip_basename = os.path.basename(dartzip_file) + ":" | |
| 68 | |
| 69 # Unzip |dartzip_file| to a temporary directory. | |
| 70 try: | |
| 71 temp_dir = tempfile.mkdtemp() | |
| 72 zipfile.ZipFile(dartzip_file).extractall(temp_dir) | |
| 73 | |
| 74 cmd = [ os.path.join(dart_sdk, 'bin', 'dartanalyzer') ] | |
| 75 | |
| 76 # Grab all the toplevel dart files in the archive. | |
| 77 dart_files = glob.glob(os.path.join(temp_dir, "*.dart")) | |
| 78 | |
| 79 if not dart_files: | |
| 80 return _success(stamp_file) | |
| 81 | |
| 82 cmd.extend(dart_files) | |
| 83 cmd.extend(args) | |
| 84 cmd.append("--package-root=%s/packages" % temp_dir) | |
| 85 cmd.append("--fatal-warnings") | |
| 86 | |
| 87 errors = analyze_and_filter(cmd, temp_dir, dartzip_basename) | |
| 88 | |
| 89 if errors is None: | |
| 90 return _success(stamp_file) | |
| 91 return min(255, len(errors)) | |
| 92 finally: | |
| 93 shutil.rmtree(temp_dir) | |
| 94 | |
| 95 | |
| 96 def analyze_entrypoints(dart_sdk, entrypoints, args): | 64 def analyze_entrypoints(dart_sdk, entrypoints, args): |
| 97 cmd = [ os.path.join(dart_sdk, 'bin', 'dartanalyzer') ] | 65 cmd = [ os.path.join(dart_sdk, 'bin', 'dartanalyzer') ] |
| 98 cmd.extend(entrypoints) | 66 cmd.extend(entrypoints) |
| 99 cmd.extend(args) | 67 cmd.extend(args) |
| 100 cmd.append("--fatal-warnings") | 68 cmd.append("--fatal-warnings") |
| 101 errors = analyze_and_filter(cmd) | 69 errors = analyze_and_filter(cmd) |
| 102 if errors is None: | 70 if errors is None: |
| 103 return 0 | 71 return 0 |
| 104 return min(255, len(errors)) | 72 return min(255, len(errors)) |
| 105 | 73 |
| 106 | 74 |
| 107 def main(): | 75 def main(): |
| 108 parser = argparse.ArgumentParser(description='Run the Dart analyzer.') | 76 parser = argparse.ArgumentParser(description='Run the Dart analyzer.') |
| 109 parser.add_argument('--dart-sdk', | 77 parser.add_argument('--dart-sdk', |
| 110 action='store', | 78 action='store', |
| 111 type=str, | 79 type=str, |
| 112 metavar='dart_sdk', | 80 metavar='dart_sdk', |
| 113 help='Path to the Dart SDK', | 81 help='Path to the Dart SDK', |
| 114 required=True) | 82 required=True) |
| 115 parser.add_argument('--dartzip-file', | |
| 116 action='store', | |
| 117 type=str, | |
| 118 metavar='dartzip_file', | |
| 119 help='dartzip file whose contents to analyze', | |
| 120 default=None) | |
| 121 parser.add_argument('--stamp-file', | 83 parser.add_argument('--stamp-file', |
| 122 action='store', | 84 action='store', |
| 123 type=str, | 85 type=str, |
| 124 metavar='stamp_file', | 86 metavar='stamp_file', |
| 125 help='Stamp file to write on success.', | 87 help='Stamp file to write on success.', |
| 126 default=None) | 88 default=None) |
| 127 parser.add_argument('--entrypoints', | 89 parser.add_argument('--entrypoints', |
| 128 help='Entry points to analyze', | 90 help='Entry points to analyze', |
| 129 nargs='*', | 91 nargs='*', |
| 130 default=[]) | 92 default=[]) |
| 131 args, remainder = parser.parse_known_args() | 93 args, remainder = parser.parse_known_args() |
| 132 | 94 |
| 133 if args.dartzip_file is None and args.entrypoints == []: | 95 if args.entrypoints == []: |
| 134 parser.print_help() | 96 parser.print_help() |
| 135 return 1 | 97 return 1 |
| 136 | 98 |
| 137 if args.dartzip_file is not None: | 99 return analyze_entrypoints(args.dart_sdk, args.entrypoints, remainder) |
| 138 # Do not run dart analyzer on third_party sources. | |
| 139 if "/third_party/" in args.dartzip_file: | |
| 140 return _success(args.stamp_file) | |
| 141 return analyze_dartzip(args.dart_sdk, args.dartzip_file, args.stamp_file, | |
| 142 remainder) | |
| 143 | |
| 144 if args.entrypoints != []: | |
| 145 return analyze_entrypoints(args.dart_sdk, args.entrypoints, remainder) | |
| 146 | 100 |
| 147 if __name__ == '__main__': | 101 if __name__ == '__main__': |
| 148 sys.exit(main()) | 102 sys.exit(main()) |
| OLD | NEW |