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

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

Issue 2712893002: Closure compiler: fix incremental builds (Closed)
Patch Set: because everybody likes **kwargs! 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
« no previous file with comments | « third_party/closure_compiler/compile.py ('k') | 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 2015 The Chromium Authors. All rights reserved. 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 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 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 content: A string of the file contens to write to a temporary file. 181 content: A string of the file contens to write to a temporary file.
182 182
183 Return: 183 Return:
184 The filepath of the newly created, written, and closed temporary file. 184 The filepath of the newly created, written, and closed temporary file.
185 """ 185 """
186 with tempfile.NamedTemporaryFile(mode="wt", delete=False) as tmp_file: 186 with tempfile.NamedTemporaryFile(mode="wt", delete=False) as tmp_file:
187 self._temp_files.append(tmp_file.name) 187 self._temp_files.append(tmp_file.name)
188 tmp_file.write(contents) 188 tmp_file.write(contents)
189 return tmp_file.name 189 return tmp_file.name
190 190
191 def check(self, sources, out_file=None, closure_args=None, 191 def check(self, sources, out_file, closure_args=None,
192 custom_sources=True): 192 custom_sources=True):
193 """Closure compile |sources| while checking for errors. 193 """Closure compile |sources| while checking for errors.
194 194
195 Args: 195 Args:
196 sources: Files to check. sources[0] is the typically the target file. 196 sources: Files to check. sources[0] is the typically the target file.
197 sources[1:] are externs and dependencies in topological order. Order 197 sources[1:] are externs and dependencies in topological order. Order
198 is not guaranteed if custom_sources is True. 198 is not guaranteed if custom_sources is True.
199 out_file: A file where the compiled output is written to. 199 out_file: A file where the compiled output is written to.
200 closure_args: Arguments passed directly to the Closure compiler. 200 closure_args: Arguments passed directly to the Closure compiler.
201 custom_sources: Whether |sources| was customized by the target (e.g. not 201 custom_sources: Whether |sources| was customized by the target (e.g. not
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 243
244 js_args = [self._expanded_file] 244 js_args = [self._expanded_file]
245 245
246 closure_args = closure_args or [] 246 closure_args = closure_args or []
247 closure_args += ["summary_detail_level=3", "continue_after_errors"] 247 closure_args += ["summary_detail_level=3", "continue_after_errors"]
248 248
249 args = ["--externs=%s" % e for e in externs] + \ 249 args = ["--externs=%s" % e for e in externs] + \
250 ["--js=%s" % s for s in js_args] + \ 250 ["--js=%s" % s for s in js_args] + \
251 ["--%s" % arg for arg in closure_args] 251 ["--%s" % arg for arg in closure_args]
252 252
253 if out_file: 253 assert out_file
254 out_dir = os.path.dirname(out_file) 254
255 if not os.path.exists(out_dir): 255 out_dir = os.path.dirname(out_file)
256 os.makedirs(out_dir) 256 if not os.path.exists(out_dir):
257 os.makedirs(out_dir)
258
259 checks_only = 'checks_only' in closure_args
260
261 if not checks_only:
257 args += ["--js_output_file=%s" % out_file] 262 args += ["--js_output_file=%s" % out_file]
258 args += ["--create_source_map=%s" % (self._MAP_FILE_FORMAT % out_file)] 263 args += ["--create_source_map=%s" % (self._MAP_FILE_FORMAT % out_file)]
259 264
260 self._log_debug("Args: %s" % " ".join(args)) 265 self._log_debug("Args: %s" % " ".join(args))
261 266
262 _, stderr = self._run_jar(self._compiler_jar, args) 267 _, stderr = self._run_jar(self._compiler_jar, args)
263 268
264 errors = stderr.strip().split("\n\n") 269 errors = stderr.strip().split("\n\n")
265 maybe_summary = errors.pop() 270 maybe_summary = errors.pop()
266 271
267 summary = re.search("(?P<error_count>\d+).*error.*warning", maybe_summary) 272 summary = re.search("(?P<error_count>\d+).*error.*warning", maybe_summary)
268 if summary: 273 if summary:
269 self._log_debug("Summary: %s" % maybe_summary) 274 self._log_debug("Summary: %s" % maybe_summary)
270 else: 275 else:
271 # Not a summary. Running the jar failed. Bail. 276 # Not a summary. Running the jar failed. Bail.
272 self._log_error(stderr) 277 self._log_error(stderr)
273 self._nuke_temp_files() 278 self._nuke_temp_files()
274 sys.exit(1) 279 sys.exit(1)
275 280
276 if summary.group('error_count') != "0" and out_file: 281 if summary.group('error_count') != "0":
277 if os.path.exists(out_file): 282 if os.path.exists(out_file):
278 os.remove(out_file) 283 os.remove(out_file)
279 if os.path.exists(self._MAP_FILE_FORMAT % out_file): 284 if os.path.exists(self._MAP_FILE_FORMAT % out_file):
280 os.remove(self._MAP_FILE_FORMAT % out_file) 285 os.remove(self._MAP_FILE_FORMAT % out_file)
286 elif checks_only:
287 # Compile succeeded but --checks_only disables --js_output_file from
288 # actually writing a file. Write a file ourselves so incremental builds
289 # still work.
290 with open(out_file, 'w') as f:
291 f.write('')
281 292
282 if not custom_sources: 293 if not custom_sources:
283 filtered_errors = self._filter_errors(errors) 294 filtered_errors = self._filter_errors(errors)
284 errors = map(self._clean_up_error, filtered_errors) 295 errors = map(self._clean_up_error, filtered_errors)
285 output = self._format_errors(errors) 296 output = self._format_errors(errors)
286 297
287 if errors: 298 if errors:
288 prefix = "\n" if output else "" 299 prefix = "\n" if output else ""
289 self._log_error("Error in: %s%s%s" % (self._target, prefix, output)) 300 self._log_error("Error in: %s%s%s" % (self._target, prefix, output))
290 elif output: 301 elif output:
291 self._log_debug("Output: %s" % output) 302 self._log_debug("Output: %s" % output)
292 303
293 self._nuke_temp_files() 304 self._nuke_temp_files()
294 return bool(errors), stderr 305 return bool(errors), stderr
295 306
296 307
297 if __name__ == "__main__": 308 if __name__ == "__main__":
298 parser = argparse.ArgumentParser( 309 parser = argparse.ArgumentParser(
299 description="Typecheck JavaScript using Closure compiler") 310 description="Typecheck JavaScript using Closure compiler")
300 parser.add_argument("sources", nargs=argparse.ONE_OR_MORE, 311 parser.add_argument("sources", nargs=argparse.ONE_OR_MORE,
301 help="Path to a source file to typecheck") 312 help="Path to a source file to typecheck")
302 parser.add_argument("--custom_sources", action="store_true", 313 parser.add_argument("--custom_sources", action="store_true",
303 help="Whether this rules has custom sources.") 314 help="Whether this rules has custom sources.")
304 parser.add_argument("-o", "--out_file", 315 parser.add_argument("-o", "--out_file", required=True,
305 help="A file where the compiled output is written to") 316 help="A file where the compiled output is written to")
306 parser.add_argument("-c", "--closure_args", nargs=argparse.ZERO_OR_MORE, 317 parser.add_argument("-c", "--closure_args", nargs=argparse.ZERO_OR_MORE,
307 help="Arguments passed directly to the Closure compiler") 318 help="Arguments passed directly to the Closure compiler")
308 parser.add_argument("-v", "--verbose", action="store_true", 319 parser.add_argument("-v", "--verbose", action="store_true",
309 help="Show more information as this script runs") 320 help="Show more information as this script runs")
310 opts = parser.parse_args() 321 opts = parser.parse_args()
311 322
312 checker = Checker(verbose=opts.verbose) 323 checker = Checker(verbose=opts.verbose)
313 324
314 found_errors, stderr = checker.check(opts.sources, out_file=opts.out_file, 325 found_errors, stderr = checker.check(opts.sources, out_file=opts.out_file,
315 closure_args=opts.closure_args, 326 closure_args=opts.closure_args,
316 custom_sources=opts.custom_sources) 327 custom_sources=opts.custom_sources)
317 328
318 if found_errors: 329 if found_errors:
319 if opts.custom_sources: 330 if opts.custom_sources:
320 print stderr 331 print stderr
321 sys.exit(1) 332 sys.exit(1)
OLDNEW
« no previous file with comments | « third_party/closure_compiler/compile.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698