OLD | NEW |
---|---|
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # Copyright 2014 The Chromium Authors. All rights reserved. | 2 # Copyright 2014 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 """Runs Closure compiler on JavaScript files to check for errors and produce | 6 """Runs Closure compiler on JavaScript files to check for errors and produce |
7 minified output.""" | 7 minified output.""" |
8 | 8 |
9 import argparse | 9 import argparse |
10 import os | 10 import os |
11 import re | 11 import re |
12 import subprocess | 12 import subprocess |
13 import sys | 13 import sys |
14 import tempfile | 14 import tempfile |
15 | 15 |
16 import build.inputs | 16 import build.inputs |
17 import processor | 17 import processor |
18 import error_filter | 18 import error_filter |
19 | 19 |
20 CURRENT_DIR = os.path.join(os.path.dirname(__file__)) | |
Dan Beam
2015/05/12 04:22:37
_CURRENT_DIR
Jeremy Klein
2015/05/12 04:47:49
Done.
| |
21 | |
20 | 22 |
21 class Checker(object): | 23 class Checker(object): |
22 """Runs the Closure compiler on given source files to typecheck them | 24 """Runs the Closure compiler on given source files to typecheck them |
23 and produce minified output.""" | 25 and produce minified output.""" |
24 | 26 |
27 _COMMON_JSCOMP_ERROR = [ | |
Dan Beam
2015/05/12 04:22:37
I don't think you really need _COMMON unless there
Jeremy Klein
2015/05/12 04:47:49
There are a few in _STRICT_CLOSURE_ARGS.
Worth do
| |
28 "accessControls", | |
29 "ambiguousFunctionDecl", | |
30 "checkStructDictInheritance", | |
31 "checkTypes", | |
32 "checkVars", | |
33 "constantProperty", | |
34 "deprecated", | |
35 "externsValidation", | |
36 "globalThis", | |
37 "invalidCasts", | |
38 "missingProperties", | |
39 "missingReturn", | |
40 "nonStandardJsDocs", | |
41 "suspiciousCode", | |
42 "undefinedNames", | |
43 "undefinedVars", | |
44 "unknownDefines", | |
45 "uselessCode", | |
46 "visibility", | |
47 ] | |
48 | |
25 _COMMON_CLOSURE_ARGS = [ | 49 _COMMON_CLOSURE_ARGS = [ |
26 "--accept_const_keyword", | 50 "--accept_const_keyword", |
27 "--jscomp_error=accessControls", | |
28 "--jscomp_error=ambiguousFunctionDecl", | |
29 "--jscomp_error=checkStructDictInheritance", | |
30 "--jscomp_error=checkTypes", | |
31 "--jscomp_error=checkVars", | |
32 "--jscomp_error=constantProperty", | |
33 "--jscomp_error=deprecated", | |
34 "--jscomp_error=externsValidation", | |
35 "--jscomp_error=globalThis", | |
36 "--jscomp_error=invalidCasts", | |
37 "--jscomp_error=missingProperties", | |
38 "--jscomp_error=missingReturn", | |
39 "--jscomp_error=nonStandardJsDocs", | |
40 "--jscomp_error=suspiciousCode", | |
41 "--jscomp_error=undefinedNames", | |
42 "--jscomp_error=undefinedVars", | |
43 "--jscomp_error=unknownDefines", | |
44 "--jscomp_error=uselessCode", | |
45 "--jscomp_error=visibility", | |
46 "--language_in=ECMASCRIPT5_STRICT", | 51 "--language_in=ECMASCRIPT5_STRICT", |
47 "--summary_detail_level=3", | 52 "--summary_detail_level=3", |
48 "--compilation_level=SIMPLE_OPTIMIZATIONS", | 53 "--compilation_level=SIMPLE_OPTIMIZATIONS", |
49 "--source_map_format=V3", | 54 "--source_map_format=V3", |
55 ] + ["--jscomp_error=%s" % err for err in _COMMON_JSCOMP_ERROR] | |
56 | |
57 # Extra flags used when compiling polymer code. | |
Dan Beam
2015/05/12 04:22:37
Extra @jsDocAnnotations used when compiling Polyme
Jeremy Klein
2015/05/12 04:47:49
Done.
| |
58 _POLYMER_EXTRA_ANNOTATIONS = [ | |
59 "attribute", | |
60 "status", | |
61 "element", | |
62 "homepage", | |
63 "submodule", | |
64 "group", | |
65 ] | |
66 | |
67 _POLYMER_ARGS = [ | |
68 "--polymer_pass", | |
69 ] + [ | |
70 "--extra_annotation_name=%s" % annotation for annotation in | |
71 _POLYMER_EXTRA_ANNOTATIONS | |
Dan Beam
2015/05/12 04:22:37
2 "annotations" in the same line (e.g.
"--extra
Jeremy Klein
2015/05/12 04:47:49
Done.
| |
50 ] | 72 ] |
51 | 73 |
52 # These are the extra flags used when compiling in strict mode. | 74 # These are the extra flags used when compiling in strict mode. |
53 # Flags that are normally disabled are turned on for strict mode. | 75 # Flags that are normally disabled are turned on for strict mode. |
54 _STRICT_CLOSURE_ARGS = [ | 76 _STRICT_CLOSURE_ARGS = [ |
55 "--jscomp_error=reportUnknownTypes", | 77 "--jscomp_error=reportUnknownTypes", |
56 "--jscomp_error=duplicate", | 78 "--jscomp_error=duplicate", |
57 "--jscomp_error=misplacedTypeAnnotation", | 79 "--jscomp_error=misplacedTypeAnnotation", |
58 ] | 80 ] |
59 | 81 |
60 _DISABLED_CLOSURE_ARGS = [ | 82 _DISABLED_CLOSURE_ARGS = [ |
61 # TODO(dbeam): happens when the same file is <include>d multiple times. | 83 # TODO(dbeam): happens when the same file is <include>d multiple times. |
62 "--jscomp_off=duplicate", | 84 "--jscomp_off=duplicate", |
63 # TODO(fukino): happens when cr.defineProperty() has a type annotation. | 85 # TODO(fukino): happens when cr.defineProperty() has a type annotation. |
64 # Avoiding parse-time warnings needs 2 pass compiling. crbug.com/421562. | 86 # Avoiding parse-time warnings needs 2 pass compiling. crbug.com/421562. |
65 "--jscomp_off=misplacedTypeAnnotation", | 87 "--jscomp_off=misplacedTypeAnnotation", |
66 ] | 88 ] |
67 | 89 |
68 _JAR_COMMAND = [ | 90 _JAR_COMMAND = [ |
69 "java", | 91 "java", |
70 "-jar", | 92 "-jar", |
71 "-Xms1024m", | 93 "-Xms1024m", |
72 "-client", | 94 "-client", |
73 "-XX:+TieredCompilation" | 95 "-XX:+TieredCompilation" |
74 ] | 96 ] |
75 | 97 |
76 _MAP_FILE_FORMAT = "%s.map" | 98 _MAP_FILE_FORMAT = "%s.map" |
77 | 99 |
78 def __init__(self, verbose=False, strict=False): | 100 def __init__(self, verbose=False, strict=False, polymer=False): |
79 """ | 101 """ |
80 Args: | 102 Args: |
81 verbose: Whether this class should output diagnostic messages. | 103 verbose: Whether this class should output diagnostic messages. |
82 strict: Whether the Closure Compiler should be invoked more strictly. | 104 strict: Whether the Closure Compiler should be invoked more strictly. |
105 polymer: Whether the Polymer pass is being run. | |
Dan Beam
2015/05/12 04:22:37
polymer: Whether the code requires Polymer support
Jeremy Klein
2015/05/12 04:47:49
Removed.
| |
83 """ | 106 """ |
84 current_dir = os.path.join(os.path.dirname(__file__)) | 107 self._runner_jar = os.path.join(CURRENT_DIR, "runner", "runner.jar") |
85 self._runner_jar = os.path.join(current_dir, "runner", "runner.jar") | |
86 self._temp_files = [] | 108 self._temp_files = [] |
87 self._verbose = verbose | 109 self._verbose = verbose |
88 self._strict = strict | 110 self._strict = strict |
111 self._polymer = polymer | |
89 self._error_filter = error_filter.PromiseErrorFilter() | 112 self._error_filter = error_filter.PromiseErrorFilter() |
90 | 113 |
91 def _nuke_temp_files(self): | 114 def _nuke_temp_files(self): |
92 """Deletes any temp files this class knows about.""" | 115 """Deletes any temp files this class knows about.""" |
93 if not self._temp_files: | 116 if not self._temp_files: |
94 return | 117 return |
95 | 118 |
96 self._log_debug("Deleting temp files: %s" % ", ".join(self._temp_files)) | 119 self._log_debug("Deleting temp files: %s" % ", ".join(self._temp_files)) |
97 for f in self._temp_files: | 120 for f in self._temp_files: |
98 os.remove(f) | 121 os.remove(f) |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
252 if out_file: | 275 if out_file: |
253 args += ["--js_output_file=%s" % out_file] | 276 args += ["--js_output_file=%s" % out_file] |
254 args += ["--create_source_map=%s" % (self._MAP_FILE_FORMAT % out_file)] | 277 args += ["--create_source_map=%s" % (self._MAP_FILE_FORMAT % out_file)] |
255 | 278 |
256 if externs: | 279 if externs: |
257 args += ["--externs=%s" % e for e in externs] | 280 args += ["--externs=%s" % e for e in externs] |
258 | 281 |
259 if output_wrapper: | 282 if output_wrapper: |
260 args += ['--output_wrapper="%s"' % output_wrapper] | 283 args += ['--output_wrapper="%s"' % output_wrapper] |
261 | 284 |
285 if self._polymer: | |
286 args += self._POLYMER_ARGS | |
287 | |
262 args_file_content = " %s" % " ".join(self._common_args() + args) | 288 args_file_content = " %s" % " ".join(self._common_args() + args) |
263 self._log_debug("Args: %s" % args_file_content.strip()) | 289 self._log_debug("Args: %s" % args_file_content.strip()) |
264 | 290 |
265 args_file = self._create_temp_file(args_file_content) | 291 args_file = self._create_temp_file(args_file_content) |
266 self._log_debug("Args file: %s" % args_file) | 292 self._log_debug("Args file: %s" % args_file) |
267 | 293 |
268 runner_args = ["--compiler-args-file=%s" % args_file] | 294 runner_args = ["--compiler-args-file=%s" % args_file] |
269 _, stderr = self._run_jar(self._runner_jar, runner_args) | 295 _, stderr = self._run_jar(self._runner_jar, runner_args) |
270 | 296 |
271 errors = stderr.strip().split("\n\n") | 297 errors = stderr.strip().split("\n\n") |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
375 parser.add_argument("-e", "--externs", nargs=argparse.ZERO_OR_MORE) | 401 parser.add_argument("-e", "--externs", nargs=argparse.ZERO_OR_MORE) |
376 parser.add_argument("-o", "--out_file", | 402 parser.add_argument("-o", "--out_file", |
377 help="A file where the compiled output is written to") | 403 help="A file where the compiled output is written to") |
378 parser.add_argument("-w", "--output_wrapper", | 404 parser.add_argument("-w", "--output_wrapper", |
379 help="Wraps output into this string at the place" | 405 help="Wraps output into this string at the place" |
380 + " denoted by the marker token %output%") | 406 + " denoted by the marker token %output%") |
381 parser.add_argument("-v", "--verbose", action="store_true", | 407 parser.add_argument("-v", "--verbose", action="store_true", |
382 help="Show more information as this script runs") | 408 help="Show more information as this script runs") |
383 parser.add_argument("--strict", action="store_true", | 409 parser.add_argument("--strict", action="store_true", |
384 help="Enable strict type checking") | 410 help="Enable strict type checking") |
411 parser.add_argument("-p", "--polymer", type=int, | |
412 help="'1' to run polymer-specific checks.") | |
385 parser.add_argument("--success-stamp", | 413 parser.add_argument("--success-stamp", |
386 help="Timestamp file to update upon success") | 414 help="Timestamp file to update upon success") |
387 | 415 |
388 parser.set_defaults(single_file=True, strict=False) | 416 parser.set_defaults(single_file=True, strict=False) |
389 opts = parser.parse_args() | 417 opts = parser.parse_args() |
390 | 418 |
391 depends = opts.depends or [] | 419 depends = opts.depends or [] |
392 externs = opts.externs or set() | 420 externs = set(opts.externs) or set() |
421 | |
422 if opts.polymer: | |
423 polymer_externs = os.path.join(CURRENT_DIR, os.pardir, 'polymer', | |
424 'v0_8', 'components-chromium', | |
425 'polymer-externs', 'polymer.externs.js') | |
426 externs.add(os.path.abspath(polymer_externs)) | |
393 | 427 |
394 if opts.out_file: | 428 if opts.out_file: |
395 out_dir = os.path.dirname(opts.out_file) | 429 out_dir = os.path.dirname(opts.out_file) |
396 if not os.path.exists(out_dir): | 430 if not os.path.exists(out_dir): |
397 os.makedirs(out_dir) | 431 os.makedirs(out_dir) |
398 | 432 |
399 checker = Checker(verbose=opts.verbose, strict=opts.strict) | 433 checker = Checker(verbose=opts.verbose, strict=opts.strict, |
434 polymer=opts.polymer) | |
400 if opts.single_file: | 435 if opts.single_file: |
401 for source in opts.sources: | 436 for source in opts.sources: |
402 depends, externs = build.inputs.resolve_recursive_dependencies( | 437 depends, externs = build.inputs.resolve_recursive_dependencies( |
403 source, depends, externs) | 438 source, depends, externs) |
404 found_errors, _ = checker.check(source, out_file=opts.out_file, | 439 found_errors, _ = checker.check(source, out_file=opts.out_file, |
405 depends=depends, externs=externs, | 440 depends=depends, externs=externs, |
406 output_wrapper=opts.output_wrapper) | 441 output_wrapper=opts.output_wrapper) |
407 if found_errors: | 442 if found_errors: |
408 sys.exit(1) | 443 sys.exit(1) |
409 else: | 444 else: |
410 found_errors, stderr = checker.check_multiple( | 445 found_errors, stderr = checker.check_multiple( |
411 opts.sources, | 446 opts.sources, |
412 out_file=opts.out_file, | 447 out_file=opts.out_file, |
413 output_wrapper=opts.output_wrapper) | 448 output_wrapper=opts.output_wrapper) |
414 if found_errors: | 449 if found_errors: |
415 print stderr | 450 print stderr |
416 sys.exit(1) | 451 sys.exit(1) |
417 | 452 |
418 if opts.success_stamp: | 453 if opts.success_stamp: |
419 with open(opts.success_stamp, "w"): | 454 with open(opts.success_stamp, "w"): |
420 os.utime(opts.success_stamp, None) | 455 os.utime(opts.success_stamp, None) |
OLD | NEW |