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

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: Always generate source map if minified js is output 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
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
(...skipping 26 matching lines...) Expand all
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'
Dan Beam 2015/03/06 02:57:29 ' -> "
Dan Beam 2015/03/06 02:57:29 nit: trailing ,
Theresa 2015/03/06 18:09:19 Done.
Theresa 2015/03/06 18:09:19 Done.
47 ] 48 ]
48 49
49 # These are the extra flags used when compiling in 'strict' mode. 50 # These are the extra flags used when compiling in 'strict' mode.
50 # Flags that are normally disabled are turned on for strict mode. 51 # Flags that are normally disabled are turned on for strict mode.
51 _STRICT_CLOSURE_ARGS = [ 52 _STRICT_CLOSURE_ARGS = [
52 "--jscomp_error=reportUnknownTypes", 53 "--jscomp_error=reportUnknownTypes",
53 "--jscomp_error=duplicate", 54 "--jscomp_error=duplicate",
54 "--jscomp_error=misplacedTypeAnnotation", 55 "--jscomp_error=misplacedTypeAnnotation",
55 ] 56 ]
56 57
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 errors = filter(None, errors) 171 errors = filter(None, errors)
171 contents = "\n## ".join("\n\n".join(errors).splitlines()) 172 contents = "\n## ".join("\n\n".join(errors).splitlines())
172 return "## %s" % contents if contents else "" 173 return "## %s" % contents if contents else ""
173 174
174 def _create_temp_file(self, contents): 175 def _create_temp_file(self, contents):
175 with tempfile.NamedTemporaryFile(mode="wt", delete=False) as tmp_file: 176 with tempfile.NamedTemporaryFile(mode="wt", delete=False) as tmp_file:
176 self._temp_files.append(tmp_file.name) 177 self._temp_files.append(tmp_file.name)
177 tmp_file.write(contents) 178 tmp_file.write(contents)
178 return tmp_file.name 179 return tmp_file.name
179 180
180 def run_js_check(self, sources, externs=None): 181 def run_js_check(self, sources, externs=None, out_file=None,
Dan Beam 2015/03/06 02:57:29 i think if the code will be modified, there should
Theresa 2015/03/06 03:07:19 Right now, the out_file is never empty. I'll look
Dan Beam 2015/03/06 03:41:38 why not just write the output for all files?
182 generate_output=False):
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 generate_output:
189 args += ["--js_output_file=%s" % out_file]
190 args += ["--source_map_format=V3"]
191 args += ["--create_source_map=%s.map" % out_file]
192
185 if externs: 193 if externs:
186 args += ["--externs=%s" % e for e in externs] 194 args += ["--externs=%s" % e for e in externs]
187 args_file_content = " %s" % " ".join(self._common_args() + args) 195 args_file_content = " %s" % " ".join(self._common_args() + args)
188 self._debug("Args: %s" % args_file_content.strip()) 196 self._debug("Args: %s" % args_file_content.strip())
189 197
190 args_file = self._create_temp_file(args_file_content) 198 args_file = self._create_temp_file(args_file_content)
191 self._debug("Args file: %s" % args_file) 199 self._debug("Args file: %s" % args_file)
192 200
193 runner_args = ["--compiler-args-file=%s" % args_file] 201 runner_args = ["--compiler-args-file=%s" % args_file]
194 runner_cmd = self._run_jar(self._runner_jar, args=runner_args) 202 runner_cmd = self._run_jar(self._runner_jar, args=runner_args)
195 _, stderr = runner_cmd.communicate() 203 _, stderr = runner_cmd.communicate()
196 204
197 errors = stderr.strip().split("\n\n") 205 errors = stderr.strip().split("\n\n")
198 self._debug("Summary: %s" % errors.pop()) 206 self._debug("Summary: %s" % errors.pop())
199 207
200 self._clean_up() 208 self._clean_up()
201 209
202 return errors, stderr 210 return errors, stderr
203 211
204 def check(self, source_file, depends=None, externs=None): 212 def check(self, source_file, depends=None, externs=None,
213 out_file=None, generate_output=False):
205 """Closure compile a file and check for errors. 214 """Closure compile a file and check for errors.
206 215
207 Args: 216 Args:
208 source_file: A file to check. 217 source_file: A file to check.
209 depends: Other files that would be included with a <script> earlier in 218 depends: Other files that would be included with a <script> earlier in
210 the page. 219 the page.
211 externs: @extern files that inform the compiler about custom globals. 220 externs: @extern files that inform the compiler about custom globals.
212 221
213 Returns: 222 Returns:
214 (has_errors, output) A boolean indicating if there were errors and the 223 (has_errors, output) A boolean indicating if there were errors and the
(...skipping 18 matching lines...) Expand all
233 242
234 includes = [rel_path(f) for f in depends + [source_file]] 243 includes = [rel_path(f) for f in depends + [source_file]]
235 contents = ['<include src="%s">' % i for i in includes] 244 contents = ['<include src="%s">' % i for i in includes]
236 meta_file = self._create_temp_file("\n".join(contents)) 245 meta_file = self._create_temp_file("\n".join(contents))
237 self._debug("Meta file: %s" % meta_file) 246 self._debug("Meta file: %s" % meta_file)
238 247
239 self._processor = processor.Processor(meta_file) 248 self._processor = processor.Processor(meta_file)
240 self._expanded_file = self._create_temp_file(self._processor.contents) 249 self._expanded_file = self._create_temp_file(self._processor.contents)
241 self._debug("Expanded file: %s" % self._expanded_file) 250 self._debug("Expanded file: %s" % self._expanded_file)
242 251
243 errors, stderr = self.run_js_check([self._expanded_file], externs) 252 errors, stderr = self.run_js_check([self._expanded_file], externs,
253 out_file, generate_output)
244 254
245 # Filter out false-positive promise chain errors. 255 # Filter out false-positive promise chain errors.
246 # See https://github.com/google/closure-compiler/issues/715 for details. 256 # See https://github.com/google/closure-compiler/issues/715 for details.
247 errors = self._error_filter.filter(errors); 257 errors = self._error_filter.filter(errors);
248 258
249 output = self._format_errors(map(self._fix_up_error, errors)) 259 output = self._format_errors(map(self._fix_up_error, errors))
250 if errors: 260 if errors:
251 prefix = "\n" if output else "" 261 prefix = "\n" if output else ""
252 self._error("Error in: %s%s%s" % (source_file, prefix, output)) 262 self._error("Error in: %s%s%s" % (source_file, prefix, output))
253 elif output: 263 elif output:
(...skipping 23 matching lines...) Expand all
277 single_file_group = parser.add_mutually_exclusive_group() 287 single_file_group = parser.add_mutually_exclusive_group()
278 single_file_group.add_argument("--single-file", dest="single_file", 288 single_file_group.add_argument("--single-file", dest="single_file",
279 action="store_true", 289 action="store_true",
280 help="Process each source file individually") 290 help="Process each source file individually")
281 single_file_group.add_argument("--no-single-file", dest="single_file", 291 single_file_group.add_argument("--no-single-file", dest="single_file",
282 action="store_false", 292 action="store_false",
283 help="Process all source files as a group") 293 help="Process all source files as a group")
284 parser.add_argument("-d", "--depends", nargs=argparse.ZERO_OR_MORE) 294 parser.add_argument("-d", "--depends", nargs=argparse.ZERO_OR_MORE)
285 parser.add_argument("-e", "--externs", nargs=argparse.ZERO_OR_MORE) 295 parser.add_argument("-e", "--externs", nargs=argparse.ZERO_OR_MORE)
286 parser.add_argument("-o", "--out_file", help="A place to output results") 296 parser.add_argument("-o", "--out_file", help="A place to output results")
297 parser.add_argument("-g", "--generate_output",
298 help="Whether or not an output file should be generated")
287 parser.add_argument("-v", "--verbose", action="store_true", 299 parser.add_argument("-v", "--verbose", action="store_true",
288 help="Show more information as this script runs") 300 help="Show more information as this script runs")
289 parser.add_argument("--strict", action="store_true", 301 parser.add_argument("--strict", action="store_true",
290 help="Enable strict type checking") 302 help="Enable strict type checking")
291 parser.add_argument("--success-stamp", 303 parser.add_argument("--success-stamp",
292 help="Timestamp file to update upon success") 304 help="Timestamp file to update upon success")
293 305
294 parser.set_defaults(single_file=True, strict=False) 306 parser.set_defaults(single_file=True, strict=False)
295 opts = parser.parse_args() 307 opts = parser.parse_args()
296 308
297 depends = opts.depends or [] 309 depends = opts.depends or []
298 externs = opts.externs or set() 310 externs = opts.externs or set()
311 generate_output = False if (opts.generate_output == '0') else True
Dan Beam 2015/03/06 02:57:29 False if (condition) else True => can always be sh
312
313 # Clean up intermediate folders that get created by output.py or create the di rs if needed
Dan Beam 2015/03/06 02:57:29 end with .
Dan Beam 2015/03/06 02:57:29 80 col wrap
314 out_dir = os.path.dirname(opts.out_file)
315 if not generate_output:
316 if os.path.exists(out_dir) and os.listdir(out_dir) == []:
Dan Beam 2015/03/06 02:57:29 why are we making empty directories?
Theresa 2015/03/06 03:07:19 I think output.py is creating them when it generat
317 os.removedirs(out_dir)
318 else:
319 if not os.path.exists(out_dir):
320 os.makedirs(out_dir)
Dan Beam 2015/03/06 02:57:28 so closure doesn't do this automatically? make a
Theresa 2015/03/06 03:07:19 It might. I'll try removing this. I had copied it
299 321
300 checker = Checker(verbose=opts.verbose, strict=opts.strict) 322 checker = Checker(verbose=opts.verbose, strict=opts.strict)
301 if opts.single_file: 323 if opts.single_file:
302 for source in opts.sources: 324 for source in opts.sources:
303 depends, externs = build.inputs.resolve_recursive_dependencies( 325 depends, externs = build.inputs.resolve_recursive_dependencies(
304 source, 326 source,
305 depends, 327 depends,
306 externs) 328 externs)
307 has_errors, _ = checker.check(source, depends=depends, externs=externs) 329 has_errors, _ = checker.check(source, depends=depends, externs=externs,
330 out_file=opts.out_file, generate_output=gene rate_output)
Dan Beam 2015/03/06 02:57:29 80 col wrap
308 if has_errors: 331 if has_errors:
309 sys.exit(1) 332 sys.exit(1)
310 333
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: 334 else:
318 has_errors, errors = checker.check_multiple(opts.sources) 335 has_errors, errors = checker.check_multiple(opts.sources)
319 if has_errors: 336 if has_errors:
320 print errors 337 print errors
321 sys.exit(1) 338 sys.exit(1)
322 339
323 if opts.success_stamp: 340 if opts.success_stamp:
324 with open(opts.success_stamp, 'w'): 341 with open(opts.success_stamp, 'w'):
325 os.utime(opts.success_stamp, None) 342 os.utime(opts.success_stamp, None)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698