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

Unified Diff: third_party/closure_compiler/checker.py

Issue 369643002: Lay groudwork to Closure compile JavaScript (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: more compiled Created 6 years, 5 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 side-by-side diff with in-line comments
Download patch
Index: third_party/closure_compiler/checker.py
diff --git a/third_party/closure_compiler/checker.py b/third_party/closure_compiler/checker.py
new file mode 100644
index 0000000000000000000000000000000000000000..ef35ff407c6b44fc15cbd1114a2228c3ddc78d91
--- /dev/null
+++ b/third_party/closure_compiler/checker.py
@@ -0,0 +1,198 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import re
+import subprocess
+import sys
+import tempfile
+
+
+
+class LineNumber(object):
+ def __init__(self, file, line_number):
+ self.file = file
+ self.line_number = line_number
+
+
+class LineCount(object):
+ def __init__(self, file, line_count):
+ self.file = file
+ self.line_count = line_count
+
+
+class Checker(object):
+ _common_closure_args = [
+ "--accept_const_keyword",
+ "--language_in=ECMASCRIPT5",
+ "--summary_detail_level=3",
+ "--warning_level=VERBOSE",
+ "--jscomp_error=accessControls",
+ "--jscomp_error=ambiguousFunctionDecl",
+ "--jscomp_error=checkEventfulObjectDisposal",
arv (Not doing code reviews) 2014/07/16 18:33:02 We do not depend on dispose pattern. It is a bad p
Dan Beam 2014/07/19 02:28:39 Done.
+ "--jscomp_error=checkStructDictInheritance",
+ "--jscomp_error=checkTypes",
+ "--jscomp_error=checkVars",
+ "--jscomp_error=constantProperty",
+ "--jscomp_error=deprecated",
+ "--jscomp_error=duplicateMessage",
arv (Not doing code reviews) 2014/07/16 18:33:02 We do not use the MSG system
Dan Beam 2014/07/19 02:28:39 Done.
+ "--jscomp_error=es3",
arv (Not doing code reviews) 2014/07/16 18:33:02 ?
Dan Beam 2014/07/19 02:28:39 Done.
+ "--jscomp_error=externsValidation",
+ "--jscomp_error=globalThis",
+ "--jscomp_error=invalidCasts",
+ "--jscomp_error=misplacedTypeAnnotation",
+ "--jscomp_error=missingProperties",
+ "--jscomp_error=missingReturn",
+ "--jscomp_error=nonStandardJsDocs",
+ "--jscomp_error=suspiciousCode",
+ "--jscomp_error=undefinedNames",
+ "--jscomp_error=undefinedVars",
+ "--jscomp_error=unknownDefines",
+ "--jscomp_error=uselessCode",
+ "--jscomp_error=visibility",
+ ]
+
+ _found_java = False
+
+ _jar_command = [
+ "java",
+ "-jar",
+ "-Xms1024m",
+ "-server",
+ "-XX:+TieredCompilation"
+ ]
+
+ def __init__(self, verbose=False):
+ self._current_dir = os.path.dirname(__file__)
+ self._compiler_jar = os.path.join(self._current_dir, "lib", "compiler.jar")
+ self._runner_jar = os.path.join(self._current_dir, "runner", "runner.jar")
+ self._temp_files = []
+ self._verbose = verbose
+
+ def _clean_up(self):
+ if not self._temp_files:
+ return
+
+ self._debug("Deleting temporary files: " + ", ".join(self._temp_files))
+ for f in self._temp_files:
+ os.remove(f)
+ self._temp_files = []
+
+ def _debug(self, msg, error=False):
+ if self._verbose:
+ print "(INFO) " + msg
+
+ def _fatal(self, msg):
+ print >> sys.stderr, "(FATAL) " + msg
+ self._clean_up()
+ sys.exit(1)
+
+ def _run_command(self, cmd):
+ cmd_str = " ".join(cmd)
+ self._debug("Running command: " + cmd_str)
+
+ devnull = open(os.devnull, "w")
+ return subprocess.Popen(
+ cmd_str, stdout=devnull, stderr=subprocess.PIPE, shell=True)
+
+ def _check_java_path(self):
+ if self._found_java:
+ return
+
+ proc = self._run_command(["which", "java"])
+ proc.communicate()
+ if proc.returncode == 0:
+ self._found_java = True
+ else:
+ self._fatal("Cannot find java (`which java` => %s)" % proc.returncode)
+
+ def _run_jar(self, jar, args=[]):
+ self._check_java_path()
+ return self._run_command(self._jar_command + [jar] + args)
+
+ def _real_line_number_from_temp_line(self, line_number):
+ line_number = int(line_number)
+
+ total = 0
+ for d in self._dep_lines:
+ if line_number <= total + d.line_count:
+ return LineNumber(d.file, line_number - total)
+ total += d.line_count
+
+ assert line_number <= total + self._line_info.line_count
+ return LineNumber(self._line_info.file, line_number - total)
+
+ def _fix_line_number(self, match):
+ real_file = self._real_line_number_from_temp_line(match.group(1))
+ return "%s:%d" % (real_file.file, real_file.line_number)
+
+ def _fix_up_error(self, error):
+ if " first declared in " in error:
+ # Ignore "Variable x first declared in /same/file".
+ return ""
+
+ file = self._line_info.file
+ line_number = re.search(":(\d+)", error).group(1)
+ if file != self._real_line_number_from_temp_line(line_number).file:
+ # Ignore errors in dependent files.
+ return ""
+
+ source_file = self._temp_files[0]
+ lines_fixed = re.sub("%s:(\d+)" % source_file, self._fix_line_number, error)
+ return lines_fixed.replace(source_file, file)
+
+ def _external_script_output(self, output):
+ contents = (os.linesep + "## ").join("\n".join(output).splitlines())
+ return "## " + contents if contents else ""
+
+ def check(self, file, depends=[], externs=[]):
+ self._debug("FILE: " + file)
+
+ if file.endswith("_externs.js"):
+ self._debug("Skipping externs")
+ return
+
+ temp_file = tempfile.NamedTemporaryFile(mode='wt', delete=False)
+ self._temp_files.append(temp_file.name)
+
+ self._dep_lines = []
+
+ for d in depends:
+ dep_contents = open(d, "r").read()
+ self._dep_lines.append(LineCount(d, len(dep_contents.splitlines())))
+ temp_file.write(dep_contents)
+
+ file_contents = open(file, "r").read()
+ self._line_info = LineCount(file, len(file_contents.splitlines()))
+ temp_file.write(file_contents)
+
+ temp_file.close()
+
+ args = ["--js=" + temp_file.name] + ["--externs=" + e for e in externs]
+ args_file_content = " " + " ".join(self._common_closure_args + args)
+ self._debug("Args: " + args_file_content.strip())
+
+ args_file = tempfile.NamedTemporaryFile(mode='wt', delete=False)
+ self._temp_files.append(args_file.name)
+
+ self._debug("Args file: " + args_file.name)
+ args_file.write(args_file_content)
+ args_file.close()
+
+ runner_args = ["--compiler-args-file=" + args_file.name]
+ runner_cmd = self._run_jar(self._runner_jar, args=runner_args)
+ (_, stderr) = runner_cmd.communicate()
+
+ errors = stderr.strip().split("\n\n")
+ self._debug("Summary: " + errors.pop())
+
+ output = self._external_script_output(map(self._fix_up_error, errors))
+ if runner_cmd.returncode:
+ self._fatal("Error in: " + file + (os.linesep + output if output else ""))
+ elif output:
+ self._debug("Output: " + output)
+
+ self._clean_up()
+
+ return runner_cmd.returncode == 0

Powered by Google App Engine
This is Rietveld 408576698