Index: third_party/closure_compiler/compile_modules.py
|
diff --git a/third_party/closure_compiler/compile_modules.py b/third_party/closure_compiler/compile_modules.py
|
new file mode 100755
|
index 0000000000000000000000000000000000000000..a6839d687f5647fb10989afb8c7eb88055f9c650
|
--- /dev/null
|
+++ b/third_party/closure_compiler/compile_modules.py
|
@@ -0,0 +1,117 @@
|
+#!/usr/bin/env python
|
+# 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 argparse
|
+from checker import Checker as Checker
|
+import os
|
+try:
|
+ import json
|
+except:
|
+ import simplejson as json
|
+
|
+
|
+
|
+class Module(object):
|
+ def __init__(self, name, sources, depends=[], externs=[]):
|
+ self._name = name
|
+ self._sources = sources
|
+ self._depends = depends
|
+ self._externs = externs
|
+
|
+ def name(self):
|
+ return self._name
|
+
|
+ def sources(self):
|
+ return self._sources
|
+
|
+ def depends(self):
|
+ return self._depends
|
+
|
+ def externs(self):
|
+ return self._externs
|
+
|
+ @staticmethod
|
+ def from_dict(d):
|
+ depends = d["depends"] if "depends" in d else []
|
+ externs = d["externs"] if "externs" in d else []
|
+ return Module(d["name"], d["sources"], depends=depends, externs=externs)
|
+
|
+
|
+# TODO(dbeam): should ModuleParser be internal to ModuleCompiler or should we
|
+# pass Modules into ModuleCompiler.compile()? Maybe this is fine?
|
+class ModuleParser(object):
|
+ _cache = {}
|
+
|
+ def __init__(self, verbose=False):
|
+ self._verbose = verbose
|
+
|
+ def parse(self, file_path):
|
+ if file_path in self._cache:
|
+ print "(INFO) Found module file %s in the cache" % file_path
|
+ return self._cache[file_path]
|
+
|
+ file = open(file_path, "r")
|
+ data = json.load(file)
|
+ file.close()
|
+
|
+ if self._verbose:
|
+ pretty_json = json.dumps(data, indent=2, separators=(',', ': ')).strip()
|
+ print "(INFO) Layout: " + os.linesep + pretty_json + os.linesep
|
+
|
+ self._cache[file_path] = [Module.from_dict(m) for m in data]
|
+ return self._cache[file_path]
|
+
|
+
|
+class ModuleCompiler(object):
|
+ _checker = None
|
+ _parser = None
|
+
|
+ def __init__(self, verbose=False):
|
+ self._verbose = verbose
|
+
|
+ def _debug(self, msg, prefix="(INFO) ", suffix=""):
|
+ if self._verbose:
|
+ print prefix + msg.strip() + suffix
|
+
|
+ def compile(self, module_file):
|
+ self._debug("MODULE FILE: " + module_file, prefix="")
|
+
|
+ # NOTE: It's possible by unlikely that |_checker| or |_parser|'s verbosity
|
+ # isn't the same as |self._verbose| due to this class being called with
|
+ # verbose=False then verbose=True in the same program.
|
+ self._parser = self._parser or ModuleParser(verbose=self._verbose)
|
+ self._checker = self._checker or Checker(verbose=self._verbose)
|
+
|
+ modules = self._parser.parse(module_file)
|
+ for m in modules:
|
+ self._debug("MODULE: " + m.name(), prefix="", suffix=os.linesep)
|
+
|
+ for s in m.sources():
|
+ f = os.path.join(os.path.dirname(module_file), s)
|
+ self._checker.check(f, depends=m.depends(), externs=m.externs())
|
+
|
+ if s != m.sources()[-1]:
|
+ self._debug(os.linesep, prefix="")
|
+
|
+ if m != modules[-1]:
|
+ self._debug(os.linesep, prefix="")
|
+
|
+
|
+def main(opts):
|
+ module_compiler = ModuleCompiler(verbose=opts.verbose)
|
+ for module_file in opts.module_file:
|
+ module_compiler.compile(module_file)
|
+ if module_file != opts.module_file[-1]:
|
+ print
|
+
|
+
|
+if __name__ == "__main__":
|
+ parser = argparse.ArgumentParser(
|
+ description="Typecheck JavaScript using Closure compiler")
|
+ parser.add_argument("-v", "--verbose", action="store_true",
|
+ help="Show more information as this script runs")
|
+ parser.add_argument("module_file", nargs=argparse.ONE_OR_MORE,
|
+ help="Path to a modules file to check")
|
+ main(parser.parse_args())
|
|