Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / closure_compiler / compile_modules.py
1 #!/usr/bin/env python
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
4 # found in the LICENSE file.
5
6 import argparse
7 from checker import Checker as Checker
8 import os
9 import sys
10
11 try:
12   import json
13 except:
14   import simplejson as json
15
16
17 class Module(object):
18   def __init__(self, name, sources, depends=[], externs=[]):
19     self.name = name
20     self.sources = sources
21     # TODO(dbeam): support depending on other modules/dependency flattening.
22     self.depends = depends
23     self.externs = externs
24
25   @staticmethod
26   def from_dict(d):
27     keys = d.keys()
28
29     required = ["name", "sources"]
30     assert all(r in keys for r in required), "Module missing name or sources"
31
32     allowed = required + ["depends", "externs"]
33     assert all(k in allowed for k in keys), "Module has unknown key"
34
35     depends = d["depends"] if "depends" in d else []
36     externs = d["externs"] if "externs" in d else []
37     return Module(d["name"], d["sources"], depends=depends, externs=externs)
38
39
40 # TODO(dbeam): should ModuleParser be internal to ModuleCompiler or should we
41 # pass Modules into ModuleCompiler.compile()? Maybe this is fine?
42 class ModuleParser(object):
43   _cache = {}
44
45   def __init__(self, verbose=False):
46     self._verbose = verbose
47
48   def parse(self, file_path):
49     if file_path in self._cache:
50       print "(INFO) Found module file %s in the cache" % file_path
51       return self._cache[file_path]
52
53     file = open(file_path, "r")
54     data = json.load(file)
55     file.close()
56
57     if self._verbose:
58       pretty_json = json.dumps(data, indent=2, separators=(',', ': ')).strip()
59       print "(INFO) Layout: " + os.linesep + pretty_json + os.linesep
60
61     self._cache[file_path] = [Module.from_dict(m) for m in data]
62     return self._cache[file_path]
63
64
65 class ModuleCompiler(object):
66   _checker = None
67   _parser = None
68
69   def __init__(self, verbose=False):
70     self._verbose = verbose
71
72   def _debug(self, msg, prefix="(INFO) ", suffix=""):
73     if self._verbose:
74       print prefix + msg.strip() + suffix
75
76   def compile(self, module_file):
77     self._debug("MODULE FILE: " + module_file, prefix="")
78
79     # NOTE: It's possible but unlikely that |_checker| or |_parser|'s verbosity
80     # isn't the same as |self._verbose| due to this class being called with
81     # verbose=False then verbose=True in the same program.
82     self._parser = self._parser or ModuleParser(verbose=self._verbose)
83     self._checker = self._checker or Checker(verbose=self._verbose)
84
85     current_dir = os.getcwd()
86     module_dir = os.path.dirname(module_file)
87     rel_path = lambda f: f
88
89     if current_dir and module_dir:
90       here_to_module_dir = os.path.relpath(module_dir, current_dir)
91       if here_to_module_dir:
92         rel_path = lambda f: os.path.join(here_to_module_dir, f)
93
94     modules = self._parser.parse(module_file)
95
96     for m in modules:
97       self._debug("MODULE: " + m.name, prefix="", suffix=os.linesep)
98
99       for s in m.sources:
100         depends = [rel_path(d) for d in m.depends]
101         externs = [rel_path(e) for e in m.externs]
102         exit_code, _ = self._checker.check(rel_path(s), depends=depends,
103                                            externs=externs)
104         if exit_code:
105           sys.exit(exit_code)
106
107         if s != m.sources[-1]:
108           self._debug(os.linesep, prefix="")
109
110       if m != modules[-1]:
111         self._debug(os.linesep, prefix="")
112
113
114 def main(opts):
115   module_compiler = ModuleCompiler(verbose=opts.verbose)
116   for module_file in opts.module_file:
117     module_compiler.compile(module_file)
118
119
120 if __name__ == "__main__":
121   parser = argparse.ArgumentParser(
122       description="Typecheck JavaScript using Closure compiler")
123   parser.add_argument("-v", "--verbose", action="store_true",
124                       help="Show more information as this script runs")
125   parser.add_argument("module_file", nargs=argparse.ONE_OR_MORE,
126                       help="Path to a modules file to check")
127   main(parser.parse_args())