Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(143)

Side by Side Diff: third_party/closure_compiler/checker.py

Issue 958383003: Output closure-compiled JavaScript files (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix a line wrap Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 a JavaScript file to check for errors.""" 6 """Runs Closure compiler on a JavaScript file to check for errors."""
7 7
8 import argparse 8 import argparse
9 import os 9 import os
10 import re 10 import re
11 import subprocess 11 import subprocess
12 import sys 12 import sys
13 import tempfile 13 import tempfile
14 14
15 import build.inputs 15 import build.inputs
16 import processor 16 import processor
17 import error_filter 17 import error_filter
18 18
19 19
20 class Checker(object): 20 class Checker(object):
Dan Beam 2015/03/07 01:55:26 i guess i'll have to rename this to Compile eventu
21 """Runs the Closure compiler on a given source file and returns the 21 """Runs the Closure compiler on a given source file and returns the
22 success/errors.""" 22 success/errors."""
23 23
24 _COMMON_CLOSURE_ARGS = [ 24 _COMMON_CLOSURE_ARGS = [
25 "--accept_const_keyword", 25 "--accept_const_keyword",
26 "--jscomp_error=accessControls", 26 "--jscomp_error=accessControls",
27 "--jscomp_error=ambiguousFunctionDecl", 27 "--jscomp_error=ambiguousFunctionDecl",
28 "--jscomp_error=checkStructDictInheritance", 28 "--jscomp_error=checkStructDictInheritance",
29 "--jscomp_error=checkTypes", 29 "--jscomp_error=checkTypes",
30 "--jscomp_error=checkVars", 30 "--jscomp_error=checkVars",
31 "--jscomp_error=constantProperty", 31 "--jscomp_error=constantProperty",
32 "--jscomp_error=deprecated", 32 "--jscomp_error=deprecated",
33 "--jscomp_error=externsValidation", 33 "--jscomp_error=externsValidation",
34 "--jscomp_error=globalThis", 34 "--jscomp_error=globalThis",
35 "--jscomp_error=invalidCasts", 35 "--jscomp_error=invalidCasts",
36 "--jscomp_error=missingProperties", 36 "--jscomp_error=missingProperties",
37 "--jscomp_error=missingReturn", 37 "--jscomp_error=missingReturn",
38 "--jscomp_error=nonStandardJsDocs", 38 "--jscomp_error=nonStandardJsDocs",
39 "--jscomp_error=suspiciousCode", 39 "--jscomp_error=suspiciousCode",
40 "--jscomp_error=undefinedNames", 40 "--jscomp_error=undefinedNames",
41 "--jscomp_error=undefinedVars", 41 "--jscomp_error=undefinedVars",
42 "--jscomp_error=unknownDefines", 42 "--jscomp_error=unknownDefines",
43 "--jscomp_error=uselessCode", 43 "--jscomp_error=uselessCode",
44 "--jscomp_error=visibility", 44 "--jscomp_error=visibility",
45 "--language_in=ECMASCRIPT5_STRICT", 45 "--language_in=ECMASCRIPT5_STRICT",
46 "--summary_detail_level=3", 46 "--summary_detail_level=3",
47 "--compilation_level=WHITESPACE_ONLY",
48 "--source_map_format=V3",
47 ] 49 ]
48 50
49 # These are the extra flags used when compiling in 'strict' mode. 51 # These are the extra flags used when compiling in 'strict' mode.
50 # Flags that are normally disabled are turned on for strict mode. 52 # Flags that are normally disabled are turned on for strict mode.
51 _STRICT_CLOSURE_ARGS = [ 53 _STRICT_CLOSURE_ARGS = [
52 "--jscomp_error=reportUnknownTypes", 54 "--jscomp_error=reportUnknownTypes",
53 "--jscomp_error=duplicate", 55 "--jscomp_error=duplicate",
54 "--jscomp_error=misplacedTypeAnnotation", 56 "--jscomp_error=misplacedTypeAnnotation",
55 ] 57 ]
56 58
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 errors = filter(None, errors) 172 errors = filter(None, errors)
171 contents = "\n## ".join("\n\n".join(errors).splitlines()) 173 contents = "\n## ".join("\n\n".join(errors).splitlines())
172 return "## %s" % contents if contents else "" 174 return "## %s" % contents if contents else ""
173 175
174 def _create_temp_file(self, contents): 176 def _create_temp_file(self, contents):
175 with tempfile.NamedTemporaryFile(mode="wt", delete=False) as tmp_file: 177 with tempfile.NamedTemporaryFile(mode="wt", delete=False) as tmp_file:
176 self._temp_files.append(tmp_file.name) 178 self._temp_files.append(tmp_file.name)
177 tmp_file.write(contents) 179 tmp_file.write(contents)
178 return tmp_file.name 180 return tmp_file.name
179 181
180 def run_js_check(self, sources, externs=None): 182 def _run_js_check(self, sources, out_file=None, externs=None):
181 if not self._check_java_path(): 183 if not self._check_java_path():
182 return 1, "" 184 return 1, ""
183 185
184 args = ["--js=%s" % s for s in sources] 186 args = ["--js=%s" % s for s in sources]
187
188 if out_file:
189 args += ["--js_output_file=%s" % out_file]
190 args += ["--create_source_map=%s.map" % out_file]
191
185 if externs: 192 if externs:
186 args += ["--externs=%s" % e for e in externs] 193 args += ["--externs=%s" % e for e in externs]
187 args_file_content = " %s" % " ".join(self._common_args() + args) 194 args_file_content = " %s" % " ".join(self._common_args() + args)
188 self._debug("Args: %s" % args_file_content.strip()) 195 self._debug("Args: %s" % args_file_content.strip())
189 196
190 args_file = self._create_temp_file(args_file_content) 197 args_file = self._create_temp_file(args_file_content)
191 self._debug("Args file: %s" % args_file) 198 self._debug("Args file: %s" % args_file)
192 199
193 runner_args = ["--compiler-args-file=%s" % args_file] 200 runner_args = ["--compiler-args-file=%s" % args_file]
194 runner_cmd = self._run_jar(self._runner_jar, args=runner_args) 201 runner_cmd = self._run_jar(self._runner_jar, args=runner_args)
195 _, stderr = runner_cmd.communicate() 202 _, stderr = runner_cmd.communicate()
196 203
197 errors = stderr.strip().split("\n\n") 204 errors = stderr.strip().split("\n\n")
198 self._debug("Summary: %s" % errors.pop()) 205 self._debug("Summary: %s" % errors.pop())
199 206
200 self._clean_up() 207 self._clean_up()
201 208
202 return errors, stderr 209 return errors, stderr
203 210
204 def check(self, source_file, depends=None, externs=None): 211 def check(self, source_file, out_file=None, depends=None, externs=None):
205 """Closure compile a file and check for errors. 212 """Closure compile a file and check for errors.
206 213
207 Args: 214 Args:
208 source_file: A file to check. 215 source_file: A file to check.
216 out_file: A file to output results.
Dan Beam 2015/03/07 01:55:26 A file where the compiled output is written to.
Theresa 2015/03/07 02:50:59 Done.
209 depends: Other files that would be included with a <script> earlier in 217 depends: Other files that would be included with a <script> earlier in
210 the page. 218 the page.
211 externs: @extern files that inform the compiler about custom globals. 219 externs: @extern files that inform the compiler about custom globals.
212 220
213 Returns: 221 Returns:
214 (has_errors, output) A boolean indicating if there were errors and the 222 (has_errors, output) A boolean indicating if there were errors and the
215 Closure compiler output (as a string). 223 Closure compiler output (as a string).
216 """ 224 """
217 depends = depends or [] 225 depends = depends or []
218 externs = externs or set() 226 externs = externs or set()
(...skipping 14 matching lines...) Expand all
233 241
234 includes = [rel_path(f) for f in depends + [source_file]] 242 includes = [rel_path(f) for f in depends + [source_file]]
235 contents = ['<include src="%s">' % i for i in includes] 243 contents = ['<include src="%s">' % i for i in includes]
236 meta_file = self._create_temp_file("\n".join(contents)) 244 meta_file = self._create_temp_file("\n".join(contents))
237 self._debug("Meta file: %s" % meta_file) 245 self._debug("Meta file: %s" % meta_file)
238 246
239 self._processor = processor.Processor(meta_file) 247 self._processor = processor.Processor(meta_file)
240 self._expanded_file = self._create_temp_file(self._processor.contents) 248 self._expanded_file = self._create_temp_file(self._processor.contents)
241 self._debug("Expanded file: %s" % self._expanded_file) 249 self._debug("Expanded file: %s" % self._expanded_file)
242 250
243 errors, stderr = self.run_js_check([self._expanded_file], externs) 251 errors, stderr = self._run_js_check([self._expanded_file],
252 out_file=out_file, externs=externs)
244 253
245 # Filter out false-positive promise chain errors. 254 # Filter out false-positive promise chain errors.
246 # See https://github.com/google/closure-compiler/issues/715 for details. 255 # See https://github.com/google/closure-compiler/issues/715 for details.
247 errors = self._error_filter.filter(errors); 256 errors = self._error_filter.filter(errors);
248 257
249 output = self._format_errors(map(self._fix_up_error, errors)) 258 output = self._format_errors(map(self._fix_up_error, errors))
250 if errors: 259 if errors:
251 prefix = "\n" if output else "" 260 prefix = "\n" if output else ""
252 self._error("Error in: %s%s%s" % (source_file, prefix, output)) 261 self._error("Error in: %s%s%s" % (source_file, prefix, output))
253 elif output: 262 elif output:
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 help="Enable strict type checking") 299 help="Enable strict type checking")
291 parser.add_argument("--success-stamp", 300 parser.add_argument("--success-stamp",
292 help="Timestamp file to update upon success") 301 help="Timestamp file to update upon success")
293 302
294 parser.set_defaults(single_file=True, strict=False) 303 parser.set_defaults(single_file=True, strict=False)
295 opts = parser.parse_args() 304 opts = parser.parse_args()
296 305
297 depends = opts.depends or [] 306 depends = opts.depends or []
298 externs = opts.externs or set() 307 externs = opts.externs or set()
299 308
309 if opts.out_file:
310 out_dir = os.path.dirname(opts.out_file)
311 if not os.path.exists(out_dir):
312 os.makedirs(out_dir)
313
300 checker = Checker(verbose=opts.verbose, strict=opts.strict) 314 checker = Checker(verbose=opts.verbose, strict=opts.strict)
301 if opts.single_file: 315 if opts.single_file:
302 for source in opts.sources: 316 for source in opts.sources:
303 depends, externs = build.inputs.resolve_recursive_dependencies( 317 depends, externs = build.inputs.resolve_recursive_dependencies(
304 source, 318 source,
305 depends, 319 depends,
306 externs) 320 externs)
307 has_errors, _ = checker.check(source, depends=depends, externs=externs) 321 has_errors, _ = checker.check(source, out_file=opts.out_file,
322 depends=depends, externs=externs)
308 if has_errors: 323 if has_errors:
309 sys.exit(1) 324 sys.exit(1)
310 325
311 if opts.out_file:
312 out_dir = os.path.dirname(opts.out_file)
313 if not os.path.exists(out_dir):
314 os.makedirs(out_dir)
315 # TODO(dbeam): write compiled file to |opts.out_file|.
316 open(opts.out_file, "w").write("")
317 else: 326 else:
318 has_errors, errors = checker.check_multiple(opts.sources) 327 has_errors, errors = checker.check_multiple(opts.sources)
319 if has_errors: 328 if has_errors:
320 print errors 329 print errors
321 sys.exit(1) 330 sys.exit(1)
322 331
323 if opts.success_stamp: 332 if opts.success_stamp:
324 with open(opts.success_stamp, 'w'): 333 with open(opts.success_stamp, 'w'):
325 os.utime(opts.success_stamp, None) 334 os.utime(opts.success_stamp, None)
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698