| 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 |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 176 content: A string of the file contens to write to a temporary file. | 176 content: A string of the file contens to write to a temporary file. |
| 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, externs=None, |
| 187 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 closure_args: Arguments passed directly to the Closure compiler. | 194 closure_args: Arguments passed directly to the Closure compiler. |
| 195 | 195 |
| 196 Returns: | 196 Returns: |
| 197 (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 |
| 198 and the raw stderr (as a string). | 198 and the raw stderr (as a string). |
| 199 """ | 199 """ |
| 200 args = ["--js=%s" % s for s in sources] | 200 args = ["--js=%s" % s for s in sources] |
| 201 | 201 |
| 202 if out_file: | 202 assert out_file |
| 203 out_dir = os.path.dirname(out_file) | 203 |
| 204 if not os.path.exists(out_dir): | 204 out_dir = os.path.dirname(out_file) |
| 205 os.makedirs(out_dir) | 205 if not os.path.exists(out_dir): |
| 206 os.makedirs(out_dir) |
| 207 |
| 208 checks_only = 'checks_only' in closure_args |
| 209 |
| 210 if not checks_only: |
| 206 args += ["--js_output_file=%s" % out_file] | 211 args += ["--js_output_file=%s" % out_file] |
| 207 args += ["--create_source_map=%s" % (self._MAP_FILE_FORMAT % out_file)] | 212 args += ["--create_source_map=%s" % (self._MAP_FILE_FORMAT % out_file)] |
| 208 | 213 |
| 209 args += ["--externs=%s" % e for e in externs or []] | 214 args += ["--externs=%s" % e for e in externs or []] |
| 210 | 215 |
| 211 closure_args = closure_args or [] | 216 closure_args = closure_args or [] |
| 212 closure_args += ["summary_detail_level=3", "continue_after_errors"] | 217 closure_args += ["summary_detail_level=3", "continue_after_errors"] |
| 213 args += ["--%s" % arg for arg in closure_args] | 218 args += ["--%s" % arg for arg in closure_args] |
| 214 | 219 |
| 215 self._log_debug("Args: %s" % " ".join(args)) | 220 self._log_debug("Args: %s" % " ".join(args)) |
| 216 | 221 |
| 217 _, stderr = self._run_jar(self._compiler_jar, args) | 222 _, stderr = self._run_jar(self._compiler_jar, args) |
| 218 | 223 |
| 219 errors = stderr.strip().split("\n\n") | 224 errors = stderr.strip().split("\n\n") |
| 220 maybe_summary = errors.pop() | 225 maybe_summary = errors.pop() |
| 221 | 226 |
| 222 if re.search(".*error.*warning.*typed", maybe_summary): | 227 if re.search(".*error.*warning.*typed", maybe_summary): |
| 223 self._log_debug("Summary: %s" % maybe_summary) | 228 self._log_debug("Summary: %s" % maybe_summary) |
| 224 else: | 229 else: |
| 225 # Not a summary. Running the jar failed. Bail. | 230 # Not a summary. Running the jar failed. Bail. |
| 226 self._log_error(stderr) | 231 self._log_error(stderr) |
| 227 self._nuke_temp_files() | 232 self._nuke_temp_files() |
| 228 sys.exit(1) | 233 sys.exit(1) |
| 229 | 234 |
| 230 if errors and out_file: | 235 if errors: |
| 231 if os.path.exists(out_file): | 236 if os.path.exists(out_file): |
| 232 os.remove(out_file) | 237 os.remove(out_file) |
| 233 if os.path.exists(self._MAP_FILE_FORMAT % out_file): | 238 if os.path.exists(self._MAP_FILE_FORMAT % out_file): |
| 234 os.remove(self._MAP_FILE_FORMAT % out_file) | 239 os.remove(self._MAP_FILE_FORMAT % out_file) |
| 240 elif checks_only: |
| 241 # Compile succeeded but --checks_only disables --js_output_file from |
| 242 # actually writing a file. Write a file ourselves so incremental builds |
| 243 # still work. |
| 244 with open(out_file, 'w') as f: |
| 245 f.write('') |
| 235 | 246 |
| 236 return errors, stderr | 247 return errors, stderr |
| 237 | 248 |
| 238 def check(self, source_file, out_file=None, depends=None, externs=None, | 249 def check(self, source_file, out_file=None, depends=None, externs=None, |
| 239 closure_args=None): | 250 closure_args=None): |
| 240 """Closure compiler |source_file| while checking for errors. | 251 """Closure compiler |source_file| while checking for errors. |
| 241 | 252 |
| 242 Args: | 253 Args: |
| 243 source_file: A file to check. | 254 source_file: A file to check. |
| 244 out_file: A file where the compiled output is written to. | 255 out_file: A file where the compiled output is written to. |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 316 single_file_group = parser.add_mutually_exclusive_group() | 327 single_file_group = parser.add_mutually_exclusive_group() |
| 317 single_file_group.add_argument("--single_file", dest="single_file", | 328 single_file_group.add_argument("--single_file", dest="single_file", |
| 318 action="store_true", | 329 action="store_true", |
| 319 help="Process each source file individually") | 330 help="Process each source file individually") |
| 320 # TODO(twellington): remove --no_single_file and use len(opts.sources). | 331 # TODO(twellington): remove --no_single_file and use len(opts.sources). |
| 321 single_file_group.add_argument("--no_single_file", dest="single_file", | 332 single_file_group.add_argument("--no_single_file", dest="single_file", |
| 322 action="store_false", | 333 action="store_false", |
| 323 help="Process all source files as a group") | 334 help="Process all source files as a group") |
| 324 parser.add_argument("-d", "--depends", nargs=argparse.ZERO_OR_MORE) | 335 parser.add_argument("-d", "--depends", nargs=argparse.ZERO_OR_MORE) |
| 325 parser.add_argument("-e", "--externs", nargs=argparse.ZERO_OR_MORE) | 336 parser.add_argument("-e", "--externs", nargs=argparse.ZERO_OR_MORE) |
| 326 parser.add_argument("-o", "--out_file", | 337 parser.add_argument("-o", "--out_file", required=True, |
| 327 help="A file where the compiled output is written to") | 338 help="A file where the compiled output is written to") |
| 328 parser.add_argument("-c", "--closure_args", nargs=argparse.ZERO_OR_MORE, | 339 parser.add_argument("-c", "--closure_args", nargs=argparse.ZERO_OR_MORE, |
| 329 help="Arguments passed directly to the Closure compiler") | 340 help="Arguments passed directly to the Closure compiler") |
| 330 parser.add_argument("-v", "--verbose", action="store_true", | 341 parser.add_argument("-v", "--verbose", action="store_true", |
| 331 help="Show more information as this script runs") | 342 help="Show more information as this script runs") |
| 332 | 343 |
| 333 parser.set_defaults(single_file=True) | 344 parser.set_defaults(single_file=True) |
| 334 opts = parser.parse_args() | 345 opts = parser.parse_args() |
| 335 | 346 |
| 336 depends = opts.depends or [] | 347 depends = opts.depends or [] |
| (...skipping 19 matching lines...) Expand all Loading... |
| 356 sys.exit(1) | 367 sys.exit(1) |
| 357 else: | 368 else: |
| 358 found_errors, stderr = checker.check_multiple( | 369 found_errors, stderr = checker.check_multiple( |
| 359 sources, | 370 sources, |
| 360 out_file=opts.out_file, | 371 out_file=opts.out_file, |
| 361 externs=externs, | 372 externs=externs, |
| 362 closure_args=opts.closure_args) | 373 closure_args=opts.closure_args) |
| 363 if found_errors: | 374 if found_errors: |
| 364 print stderr | 375 print stderr |
| 365 sys.exit(1) | 376 sys.exit(1) |
| OLD | NEW |