OLD | NEW |
| (Empty) |
1 #!/usr/bin/python | |
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 | |
4 # found in the LICENSE file. | |
5 | |
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. | |
8 | |
9 # This script analyzes a set of entrypoints specified with the --entrypoints | |
10 # flag. The location of the Dart SDK must be specified with the --dart-sdk | |
11 # flag. A stamp file can optionally be written with the location given by the | |
12 # --stamp-file flag. Any command line arguments not recognized by this script | |
13 # are passed on to the Dart analyzer. | |
14 | |
15 import argparse | |
16 import glob | |
17 import os | |
18 import re | |
19 import shutil | |
20 import subprocess | |
21 import sys | |
22 import tempfile | |
23 | |
24 _IGNORED_PATTERNS = [ | |
25 # Ignored because they're not indicative of specific errors. | |
26 re.compile(r'^$'), | |
27 re.compile(r'^Analyzing \['), | |
28 re.compile(r'^No issues found'), | |
29 re.compile(r'^[0-9]+ errors? and [0-9]+ warnings? found.'), | |
30 re.compile(r'^([0-9]+|No) (error|warning|issue)s? found.'), | |
31 | |
32 # TODO: It seems like this should be re-enabled evenutally. | |
33 re.compile(r'.*is a part and can not|^Only libraries can be analyzed'), | |
34 # TODO: Remove this once dev SDK includes Uri.directory constructor. | |
35 re.compile(r'.*The class \'Uri\' does not have a constructor \'directory\''), | |
36 # TODO: Remove this once Sky no longer generates this warning. | |
37 # dartbug.com/22836 | |
38 re.compile(r'.*cannot both be unnamed'), | |
39 | |
40 # The Dart SDK seems to generate some hints and lints. | |
41 re.compile(r'.*\/dart-sdk\/'), | |
42 ] | |
43 | |
44 | |
45 def _success(stamp_file): | |
46 # We passed cleanly, so touch the stamp file so that we don't run again. | |
47 with open(stamp_file, 'a'): | |
48 os.utime(stamp_file, None) | |
49 return 0 | |
50 | |
51 | |
52 def analyze_and_filter(cmd, temp_dir=None, dirname=None): | |
53 errors = None | |
54 try: | |
55 subprocess.check_output(cmd, shell=False, stderr=subprocess.STDOUT) | |
56 except subprocess.CalledProcessError as e: | |
57 errors = set(l for l in e.output.split('\n') | |
58 if not any(p.match(l) for p in _IGNORED_PATTERNS)) | |
59 for error in sorted(errors): | |
60 if dirname is None: | |
61 print >> sys.stderr, error | |
62 else: | |
63 print >> sys.stderr, error.replace(temp_dir + "/", dirname) | |
64 return errors | |
65 | |
66 | |
67 def analyze_entrypoints(dart_sdk, entrypoints, args): | |
68 cmd = [ os.path.join(dart_sdk, 'bin', 'dartanalyzer') ] | |
69 cmd.extend(entrypoints) | |
70 cmd.extend(args) | |
71 cmd.append("--fatal-warnings") | |
72 cmd.append("--fatal-lints") | |
73 cmd.append("--fatal-hints") | |
74 errors = analyze_and_filter(cmd) | |
75 if errors is None: | |
76 return 0 | |
77 return min(255, len(errors)) | |
78 | |
79 | |
80 def main(): | |
81 parser = argparse.ArgumentParser(description='Run the Dart analyzer.') | |
82 parser.add_argument('--dart-sdk', | |
83 action='store', | |
84 type=str, | |
85 metavar='dart_sdk', | |
86 help='Path to the Dart SDK', | |
87 required=True) | |
88 parser.add_argument('--stamp-file', | |
89 action='store', | |
90 type=str, | |
91 metavar='stamp_file', | |
92 help='Stamp file to write on success.', | |
93 default=None) | |
94 parser.add_argument('--entrypoints', | |
95 help='Entry points to analyze', | |
96 nargs='*', | |
97 default=[]) | |
98 args, remainder = parser.parse_known_args() | |
99 | |
100 if args.entrypoints == []: | |
101 parser.print_help() | |
102 return 1 | |
103 | |
104 return analyze_entrypoints(args.dart_sdk, args.entrypoints, remainder) | |
105 | |
106 if __name__ == '__main__': | |
107 sys.exit(main()) | |
OLD | NEW |