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

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

Issue 2629323002: Remove Chromium's custom closure runner. (Closed)
Patch Set: merge Created 3 years, 10 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 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
(...skipping 22 matching lines...) Expand all
33 "-XX:+TieredCompilation" 33 "-XX:+TieredCompilation"
34 ] 34 ]
35 35
36 _MAP_FILE_FORMAT = "%s.map" 36 _MAP_FILE_FORMAT = "%s.map"
37 37
38 def __init__(self, verbose=False): 38 def __init__(self, verbose=False):
39 """ 39 """
40 Args: 40 Args:
41 verbose: Whether this class should output diagnostic messages. 41 verbose: Whether this class should output diagnostic messages.
42 """ 42 """
43 self._runner_jar = os.path.join(_CURRENT_DIR, "runner", "runner.jar") 43 self._compiler_jar = os.path.join(_CURRENT_DIR, "compiler", "compiler.jar")
44 self._temp_files = [] 44 self._temp_files = []
45 self._verbose = verbose 45 self._verbose = verbose
46 self._error_filter = error_filter.PromiseErrorFilter() 46 self._error_filter = error_filter.PromiseErrorFilter()
47 47
48 def _nuke_temp_files(self): 48 def _nuke_temp_files(self):
49 """Deletes any temp files this class knows about.""" 49 """Deletes any temp files this class knows about."""
50 if not self._temp_files: 50 if not self._temp_files:
51 return 51 return
52 52
53 self._log_debug("Deleting temp files: %s" % ", ".join(self._temp_files)) 53 self._log_debug("Deleting temp files: %s" % ", ".join(self._temp_files))
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 177
178 Return: 178 Return:
179 The filepath of the newly created, written, and closed temporary file. 179 The filepath of the newly created, written, and closed temporary file.
180 """ 180 """
181 with tempfile.NamedTemporaryFile(mode="wt", delete=False) as tmp_file: 181 with tempfile.NamedTemporaryFile(mode="wt", delete=False) as tmp_file:
182 self._temp_files.append(tmp_file.name) 182 self._temp_files.append(tmp_file.name)
183 tmp_file.write(contents) 183 tmp_file.write(contents)
184 return tmp_file.name 184 return tmp_file.name
185 185
186 def _run_js_check(self, sources, out_file=None, externs=None, 186 def _run_js_check(self, sources, out_file=None, externs=None,
187 runner_args=None, closure_args=None): 187 closure_args=None):
188 """Check |sources| for type errors. 188 """Check |sources| for type errors.
189 189
190 Args: 190 Args:
191 sources: Files to check. 191 sources: Files to check.
192 out_file: A file where the compiled output is written to. 192 out_file: A file where the compiled output is written to.
193 externs: @extern files that inform the compiler about custom globals. 193 externs: @extern files that inform the compiler about custom globals.
194 runner_args: Arguments passed to runner.jar.
195 closure_args: Arguments passed directly to the Closure compiler. 194 closure_args: Arguments passed directly to the Closure compiler.
196 195
197 Returns: 196 Returns:
198 (errors, stderr) A parsed list of errors (strings) found by the compiler 197 (errors, stderr) A parsed list of errors (strings) found by the compiler
199 and the raw stderr (as a string). 198 and the raw stderr (as a string).
200 """ 199 """
201 args = ["--js=%s" % s for s in sources] 200 args = ["--js=%s" % s for s in sources]
202 201
203 if out_file: 202 if out_file:
204 out_dir = os.path.dirname(out_file) 203 out_dir = os.path.dirname(out_file)
205 if not os.path.exists(out_dir): 204 if not os.path.exists(out_dir):
206 os.makedirs(out_dir) 205 os.makedirs(out_dir)
207 args += ["--js_output_file=%s" % out_file] 206 args += ["--js_output_file=%s" % out_file]
208 args += ["--create_source_map=%s" % (self._MAP_FILE_FORMAT % out_file)] 207 args += ["--create_source_map=%s" % (self._MAP_FILE_FORMAT % out_file)]
209 208
210 args += ["--externs=%s" % e for e in externs or []] 209 args += ["--externs=%s" % e for e in externs or []]
211 210
212 closure_args = closure_args or [] 211 closure_args = closure_args or []
213 closure_args += ["summary_detail_level=3"] 212 closure_args += ["summary_detail_level=3", "continue_after_errors"]
214 args += ["--%s" % arg for arg in closure_args] 213 args += ["--%s" % arg for arg in closure_args]
215 214
216 args_file_content = " %s" % " ".join(args) 215 self._log_debug("Args: %s" % " ".join(args))
217 self._log_debug("Args: %s" % args_file_content.strip())
218 216
219 args_file = self._create_temp_file(args_file_content) 217 _, stderr = self._run_jar(self._compiler_jar, args)
220 self._log_debug("Args file: %s" % args_file)
221
222 processed_runner_args = ["--%s" % arg for arg in runner_args or []]
223 processed_runner_args += ["--compiler-args-file=%s" % args_file]
224 _, stderr = self._run_jar(self._runner_jar, processed_runner_args)
225 218
226 errors = stderr.strip().split("\n\n") 219 errors = stderr.strip().split("\n\n")
227 maybe_summary = errors.pop() 220 maybe_summary = errors.pop()
228 221
229 if re.search(".*error.*warning.*typed", maybe_summary): 222 if re.search(".*error.*warning.*typed", maybe_summary):
230 self._log_debug("Summary: %s" % maybe_summary) 223 self._log_debug("Summary: %s" % maybe_summary)
231 else: 224 else:
232 # Not a summary. Running the jar failed. Bail. 225 # Not a summary. Running the jar failed. Bail.
233 self._log_error(stderr) 226 self._log_error(stderr)
234 self._nuke_temp_files() 227 self._nuke_temp_files()
235 sys.exit(1) 228 sys.exit(1)
236 229
237 if errors and out_file: 230 if errors and out_file:
238 if os.path.exists(out_file): 231 if os.path.exists(out_file):
239 os.remove(out_file) 232 os.remove(out_file)
240 if os.path.exists(self._MAP_FILE_FORMAT % out_file): 233 if os.path.exists(self._MAP_FILE_FORMAT % out_file):
241 os.remove(self._MAP_FILE_FORMAT % out_file) 234 os.remove(self._MAP_FILE_FORMAT % out_file)
242 235
243 return errors, stderr 236 return errors, stderr
244 237
245 def check(self, source_file, out_file=None, depends=None, externs=None, 238 def check(self, source_file, out_file=None, depends=None, externs=None,
246 runner_args=None, closure_args=None): 239 closure_args=None):
247 """Closure compiler |source_file| while checking for errors. 240 """Closure compiler |source_file| while checking for errors.
248 241
249 Args: 242 Args:
250 source_file: A file to check. 243 source_file: A file to check.
251 out_file: A file where the compiled output is written to. 244 out_file: A file where the compiled output is written to.
252 depends: Files that |source_file| requires to run (e.g. earlier <script>). 245 depends: Files that |source_file| requires to run (e.g. earlier <script>).
253 externs: @extern files that inform the compiler about custom globals. 246 externs: @extern files that inform the compiler about custom globals.
254 runner_args: Arguments passed to runner.jar.
255 closure_args: Arguments passed directly to the Closure compiler. 247 closure_args: Arguments passed directly to the Closure compiler.
256 248
257 Returns: 249 Returns:
258 (found_errors, stderr) A boolean indicating whether errors were found and 250 (found_errors, stderr) A boolean indicating whether errors were found and
259 the raw Closure compiler stderr (as a string). 251 the raw Closure compiler stderr (as a string).
260 """ 252 """
261 self._log_debug("FILE: %s" % source_file) 253 self._log_debug("FILE: %s" % source_file)
262 254
263 if source_file.endswith("_externs.js"): 255 if source_file.endswith("_externs.js"):
264 self._log_debug("Skipping externs: %s" % source_file) 256 self._log_debug("Skipping externs: %s" % source_file)
265 return 257 return
266 258
267 self._file_arg = source_file 259 self._file_arg = source_file
268 260
269 cwd, tmp_dir = os.getcwd(), tempfile.gettempdir() 261 cwd, tmp_dir = os.getcwd(), tempfile.gettempdir()
270 rel_path = lambda f: os.path.join(os.path.relpath(cwd, tmp_dir), f) 262 rel_path = lambda f: os.path.join(os.path.relpath(cwd, tmp_dir), f)
271 263
272 depends = depends or [] 264 depends = depends or []
273 includes = [rel_path(f) for f in depends + [source_file]] 265 includes = [rel_path(f) for f in depends + [source_file]]
274 contents = ['<include src="%s">' % i for i in includes] 266 contents = ['<include src="%s">' % i for i in includes]
275 meta_file = self._create_temp_file("\n".join(contents)) 267 meta_file = self._create_temp_file("\n".join(contents))
276 self._log_debug("Meta file: %s" % meta_file) 268 self._log_debug("Meta file: %s" % meta_file)
277 269
278 self._processor = processor.Processor(meta_file) 270 self._processor = processor.Processor(meta_file)
279 self._expanded_file = self._create_temp_file(self._processor.contents) 271 self._expanded_file = self._create_temp_file(self._processor.contents)
280 self._log_debug("Expanded file: %s" % self._expanded_file) 272 self._log_debug("Expanded file: %s" % self._expanded_file)
281 273
282 errors, stderr = self._run_js_check([self._expanded_file], 274 errors, stderr = self._run_js_check([self._expanded_file],
283 out_file=out_file, externs=externs, 275 out_file=out_file, externs=externs,
284 runner_args=runner_args,
285 closure_args=closure_args) 276 closure_args=closure_args)
286 filtered_errors = self._filter_errors(errors) 277 filtered_errors = self._filter_errors(errors)
287 cleaned_errors = map(self._clean_up_error, filtered_errors) 278 cleaned_errors = map(self._clean_up_error, filtered_errors)
288 output = self._format_errors(cleaned_errors) 279 output = self._format_errors(cleaned_errors)
289 280
290 if cleaned_errors: 281 if cleaned_errors:
291 prefix = "\n" if output else "" 282 prefix = "\n" if output else ""
292 self._log_error("Error in: %s%s%s" % (source_file, prefix, output)) 283 self._log_error("Error in: %s%s%s" % (source_file, prefix, output))
293 elif output: 284 elif output:
294 self._log_debug("Output: %s" % output) 285 self._log_debug("Output: %s" % output)
295 286
296 self._nuke_temp_files() 287 self._nuke_temp_files()
297 return bool(cleaned_errors), stderr 288 return bool(cleaned_errors), stderr
298 289
299 def check_multiple(self, sources, out_file=None, externs=None, 290 def check_multiple(self, sources, out_file=None, externs=None,
300 runner_args=None, closure_args=None): 291 closure_args=None):
301 """Closure compile a set of files and check for errors. 292 """Closure compile a set of files and check for errors.
302 293
303 Args: 294 Args:
304 sources: An array of files to check. 295 sources: An array of files to check.
305 out_file: A file where the compiled output is written to. 296 out_file: A file where the compiled output is written to.
306 externs: @extern files that inform the compiler about custom globals. 297 externs: @extern files that inform the compiler about custom globals.
307 runner_args: Arguments passed to runner.jar.
308 closure_args: Arguments passed directly to the Closure compiler. 298 closure_args: Arguments passed directly to the Closure compiler.
309 299
310 Returns: 300 Returns:
311 (found_errors, stderr) A boolean indicating whether errors were found and 301 (found_errors, stderr) A boolean indicating whether errors were found and
312 the raw Closure Compiler stderr (as a string). 302 the raw Closure Compiler stderr (as a string).
313 """ 303 """
314 errors, stderr = self._run_js_check(sources, out_file=out_file, 304 errors, stderr = self._run_js_check(sources, out_file=out_file,
315 externs=externs, 305 externs=externs,
316 runner_args=runner_args,
317 closure_args=closure_args) 306 closure_args=closure_args)
318 self._nuke_temp_files() 307 self._nuke_temp_files()
319 return bool(errors), stderr 308 return bool(errors), stderr
320 309
321 310
322 if __name__ == "__main__": 311 if __name__ == "__main__":
323 parser = argparse.ArgumentParser( 312 parser = argparse.ArgumentParser(
324 description="Typecheck JavaScript using Closure compiler") 313 description="Typecheck JavaScript using Closure compiler")
325 parser.add_argument("sources", nargs=argparse.ONE_OR_MORE, 314 parser.add_argument("sources", nargs=argparse.ONE_OR_MORE,
326 help="Path to a source file to typecheck") 315 help="Path to a source file to typecheck")
327 single_file_group = parser.add_mutually_exclusive_group() 316 single_file_group = parser.add_mutually_exclusive_group()
328 single_file_group.add_argument("--single_file", dest="single_file", 317 single_file_group.add_argument("--single_file", dest="single_file",
329 action="store_true", 318 action="store_true",
330 help="Process each source file individually") 319 help="Process each source file individually")
331 # TODO(twellington): remove --no_single_file and use len(opts.sources). 320 # TODO(twellington): remove --no_single_file and use len(opts.sources).
332 single_file_group.add_argument("--no_single_file", dest="single_file", 321 single_file_group.add_argument("--no_single_file", dest="single_file",
333 action="store_false", 322 action="store_false",
334 help="Process all source files as a group") 323 help="Process all source files as a group")
335 parser.add_argument("-d", "--depends", nargs=argparse.ZERO_OR_MORE) 324 parser.add_argument("-d", "--depends", nargs=argparse.ZERO_OR_MORE)
336 parser.add_argument("-e", "--externs", nargs=argparse.ZERO_OR_MORE) 325 parser.add_argument("-e", "--externs", nargs=argparse.ZERO_OR_MORE)
337 parser.add_argument("-o", "--out_file", 326 parser.add_argument("-o", "--out_file",
338 help="A file where the compiled output is written to") 327 help="A file where the compiled output is written to")
339 parser.add_argument("-r", "--runner_args", nargs=argparse.ZERO_OR_MORE,
340 help="Arguments passed to runner.jar")
341 parser.add_argument("-c", "--closure_args", nargs=argparse.ZERO_OR_MORE, 328 parser.add_argument("-c", "--closure_args", nargs=argparse.ZERO_OR_MORE,
342 help="Arguments passed directly to the Closure compiler") 329 help="Arguments passed directly to the Closure compiler")
343 parser.add_argument("-v", "--verbose", action="store_true", 330 parser.add_argument("-v", "--verbose", action="store_true",
344 help="Show more information as this script runs") 331 help="Show more information as this script runs")
345 332
346 parser.set_defaults(single_file=True) 333 parser.set_defaults(single_file=True)
347 opts = parser.parse_args() 334 opts = parser.parse_args()
348 335
349 depends = opts.depends or [] 336 depends = opts.depends or []
350 # TODO(devlin): should we run normpath() on this first and/or do this for 337 # TODO(devlin): should we run normpath() on this first and/or do this for
351 # depends as well? 338 # depends as well?
352 externs = set(opts.externs or []) 339 externs = set(opts.externs or [])
353 sources = set(opts.sources) 340 sources = set(opts.sources)
354 341
355 externs.add(os.path.join(_CURRENT_DIR, "externs", "polymer-1.0.js")) 342 externs.add(os.path.join(_CURRENT_DIR, "externs", "polymer-1.0.js"))
356 343
357 checker = Checker(verbose=opts.verbose) 344 checker = Checker(verbose=opts.verbose)
358 if opts.single_file: 345 if opts.single_file:
359 for source in sources: 346 for source in sources:
360 # Normalize source to the current directory. 347 # Normalize source to the current directory.
361 source = os.path.normpath(os.path.join(os.getcwd(), source)) 348 source = os.path.normpath(os.path.join(os.getcwd(), source))
362 depends, externs = build.inputs.resolve_recursive_dependencies( 349 depends, externs = build.inputs.resolve_recursive_dependencies(
363 source, depends, externs) 350 source, depends, externs)
364 351
365 found_errors, _ = checker.check(source, out_file=opts.out_file, 352 found_errors, _ = checker.check(source, out_file=opts.out_file,
366 depends=depends, externs=externs, 353 depends=depends, externs=externs,
367 runner_args=opts.runner_args,
368 closure_args=opts.closure_args) 354 closure_args=opts.closure_args)
369 if found_errors: 355 if found_errors:
370 sys.exit(1) 356 sys.exit(1)
371 else: 357 else:
372 found_errors, stderr = checker.check_multiple( 358 found_errors, stderr = checker.check_multiple(
373 sources, 359 sources,
374 out_file=opts.out_file, 360 out_file=opts.out_file,
375 externs=externs, 361 externs=externs,
376 runner_args=opts.runner_args,
377 closure_args=opts.closure_args) 362 closure_args=opts.closure_args)
378 if found_errors: 363 if found_errors:
379 print stderr 364 print stderr
380 sys.exit(1) 365 sys.exit(1)
OLDNEW
« no previous file with comments | « third_party/closure_compiler/closure_args.gypi ('k') | third_party/closure_compiler/compile2.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698