forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
compile_modules.py
executable file
·127 lines (95 loc) · 3.91 KB
/
compile_modules.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#!/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
import sys
try:
import json
except:
import simplejson as json
class Module(object):
def __init__(self, name, sources, depends=[], externs=[]):
self.name = name
self.sources = sources
# TODO(dbeam): support depending on other modules/dependency flattening.
self.depends = depends
self.externs = externs
@staticmethod
def from_dict(d):
keys = d.keys()
required = ["name", "sources"]
assert all(r in keys for r in required), "Module missing name or sources"
allowed = required + ["depends", "externs"]
assert all(k in allowed for k in keys), "Module has unknown key"
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 but 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)
current_dir = os.getcwd()
module_dir = os.path.dirname(module_file)
rel_path = lambda f: f
if current_dir and module_dir:
here_to_module_dir = os.path.relpath(module_dir, current_dir)
if here_to_module_dir:
rel_path = lambda f: os.path.join(here_to_module_dir, f)
modules = self._parser.parse(module_file)
for m in modules:
self._debug("MODULE: " + m.name, prefix="", suffix=os.linesep)
for s in m.sources:
depends = [rel_path(d) for d in m.depends]
externs = [rel_path(e) for e in m.externs]
exit_code, _ = self._checker.check(rel_path(s), depends=depends,
externs=externs)
if exit_code:
sys.exit(exit_code)
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 __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())