OLD | NEW |
1 # Copyright 2016 The Chromium Authors. All rights reserved. | 1 # Copyright 2016 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 import os.path | 5 import os.path |
6 import sys | 6 import sys |
7 import optparse | 7 import optparse |
8 import collections | 8 import collections |
9 import functools | 9 import functools |
| 10 import re |
10 try: | 11 try: |
11 import json | 12 import json |
12 except ImportError: | 13 except ImportError: |
13 import simplejson as json | 14 import simplejson as json |
14 | 15 |
15 # Path handling for libraries and templates | 16 # Path handling for libraries and templates |
16 # Paths have to be normalized because Jinja uses the exact template path to | 17 # Paths have to be normalized because Jinja uses the exact template path to |
17 # determine the hash used in the cache filename, and we need a pre-caching step | 18 # determine the hash used in the cache filename, and we need a pre-caching step |
18 # to be concurrency-safe. Use absolute path because __file__ is absolute if | 19 # to be concurrency-safe. Use absolute path because __file__ is absolute if |
19 # module is imported, and relative if executed directly. | 20 # module is imported, and relative if executed directly. |
(...skipping 25 matching lines...) Expand all Loading... |
45 if optional_key.find(".") == -1 and optional_key not in keys: | 46 if optional_key.find(".") == -1 and optional_key not in keys: |
46 keys.append(optional_key) | 47 keys.append(optional_key) |
47 values.append(defaults[optional]) | 48 values.append(defaults[optional]) |
48 return collections.namedtuple('X', keys)(*values) | 49 return collections.namedtuple('X', keys)(*values) |
49 | 50 |
50 try: | 51 try: |
51 cmdline_parser = optparse.OptionParser() | 52 cmdline_parser = optparse.OptionParser() |
52 cmdline_parser.add_option("--output_base") | 53 cmdline_parser.add_option("--output_base") |
53 cmdline_parser.add_option("--jinja_dir") | 54 cmdline_parser.add_option("--jinja_dir") |
54 cmdline_parser.add_option("--config") | 55 cmdline_parser.add_option("--config") |
| 56 cmdline_parser.add_option("--config_value", action="append", type="strin
g") |
55 arg_options, _ = cmdline_parser.parse_args() | 57 arg_options, _ = cmdline_parser.parse_args() |
56 jinja_dir = arg_options.jinja_dir | 58 jinja_dir = arg_options.jinja_dir |
57 if not jinja_dir: | 59 if not jinja_dir: |
58 raise Exception("jinja directory must be specified") | 60 raise Exception("jinja directory must be specified") |
59 output_base = arg_options.output_base | 61 output_base = arg_options.output_base |
60 if not output_base: | 62 if not output_base: |
61 raise Exception("Base output directory must be specified") | 63 raise Exception("Base output directory must be specified") |
62 config_file = arg_options.config | 64 config_file = arg_options.config |
63 if not config_file: | 65 if not config_file: |
64 raise Exception("Config file name must be specified") | 66 raise Exception("Config file name must be specified") |
65 config_base = os.path.dirname(config_file) | 67 config_base = os.path.dirname(config_file) |
| 68 config_values = arg_options.config_value |
| 69 if not config_values: |
| 70 config_values = [] |
66 except Exception: | 71 except Exception: |
67 # Work with python 2 and 3 http://docs.python.org/py3k/howto/pyporting.h
tml | 72 # Work with python 2 and 3 http://docs.python.org/py3k/howto/pyporting.h
tml |
68 exc = sys.exc_info()[1] | 73 exc = sys.exc_info()[1] |
69 sys.stderr.write("Failed to parse command-line arguments: %s\n\n" % exc) | 74 sys.stderr.write("Failed to parse command-line arguments: %s\n\n" % exc) |
70 exit(1) | 75 exit(1) |
71 | 76 |
72 try: | 77 try: |
73 config_json_file = open(config_file, "r") | 78 config_json_file = open(config_file, "r") |
74 config_json_string = config_json_file.read() | 79 config_json_string = config_json_file.read() |
75 config_partial = json_to_object(config_json_string, output_base, config_
base) | 80 config_partial = json_to_object(config_json_string, output_base, config_
base) |
76 config_json_file.close() | 81 config_json_file.close() |
77 defaults = { | 82 defaults = { |
| 83 ".use_snake_file_names": False, |
| 84 ".use_title_case_methods": False, |
78 ".imported": False, | 85 ".imported": False, |
79 ".imported.export_macro": "", | 86 ".imported.export_macro": "", |
80 ".imported.export_header": False, | 87 ".imported.export_header": False, |
81 ".imported.header": False, | 88 ".imported.header": False, |
82 ".imported.package": False, | 89 ".imported.package": False, |
83 ".protocol.export_macro": "", | 90 ".protocol.export_macro": "", |
84 ".protocol.export_header": False, | 91 ".protocol.export_header": False, |
| 92 ".protocol.options": False, |
85 ".exported": False, | 93 ".exported": False, |
86 ".exported.export_macro": "", | 94 ".exported.export_macro": "", |
87 ".exported.export_header": False, | 95 ".exported.export_header": False, |
88 ".lib": False, | 96 ".lib": False, |
89 ".lib.export_macro": "", | 97 ".lib.export_macro": "", |
90 ".lib.export_header": False, | 98 ".lib.export_header": False, |
91 } | 99 } |
| 100 for key_value in config_values: |
| 101 parts = key_value.split("=") |
| 102 if len(parts) == 2: |
| 103 defaults["." + parts[0]] = parts[1] |
92 return (jinja_dir, config_file, init_defaults(config_partial, "", defaul
ts)) | 104 return (jinja_dir, config_file, init_defaults(config_partial, "", defaul
ts)) |
93 except Exception: | 105 except Exception: |
94 # Work with python 2 and 3 http://docs.python.org/py3k/howto/pyporting.h
tml | 106 # Work with python 2 and 3 http://docs.python.org/py3k/howto/pyporting.h
tml |
95 exc = sys.exc_info()[1] | 107 exc = sys.exc_info()[1] |
96 sys.stderr.write("Failed to parse config file: %s\n\n" % exc) | 108 sys.stderr.write("Failed to parse config file: %s\n\n" % exc) |
97 exit(1) | 109 exit(1) |
98 | 110 |
99 | 111 |
100 def to_title_case(name): | 112 def to_title_case(name): |
101 return name[:1].upper() + name[1:] | 113 return name[:1].upper() + name[1:] |
102 | 114 |
103 | 115 |
104 def dash_to_camelcase(word): | 116 def dash_to_camelcase(word): |
105 prefix = "" | 117 prefix = "" |
106 if word[0] == "-": | 118 if word[0] == "-": |
107 prefix = "Negative" | 119 prefix = "Negative" |
108 word = word[1:] | 120 word = word[1:] |
109 return prefix + "".join(to_title_case(x) or "-" for x in word.split("-")) | 121 return prefix + "".join(to_title_case(x) or "-" for x in word.split("-")) |
110 | 122 |
111 | 123 |
112 def initialize_jinja_env(jinja_dir, cache_dir): | 124 def to_snake_case(name): |
| 125 return re.sub(r"([a-z0-9])([A-Z])", r"\1_\2", name, sys.maxint).lower() |
| 126 |
| 127 |
| 128 def to_method_case(config, name): |
| 129 if config.use_title_case_methods: |
| 130 return to_title_case(name) |
| 131 return name |
| 132 |
| 133 |
| 134 def initialize_jinja_env(jinja_dir, cache_dir, config): |
113 # pylint: disable=F0401 | 135 # pylint: disable=F0401 |
114 sys.path.insert(1, os.path.abspath(jinja_dir)) | 136 sys.path.insert(1, os.path.abspath(jinja_dir)) |
115 import jinja2 | 137 import jinja2 |
116 | 138 |
117 jinja_env = jinja2.Environment( | 139 jinja_env = jinja2.Environment( |
118 loader=jinja2.FileSystemLoader(module_path), | 140 loader=jinja2.FileSystemLoader(module_path), |
119 # Bytecode cache is not concurrency-safe unless pre-cached: | 141 # Bytecode cache is not concurrency-safe unless pre-cached: |
120 # if pre-cached this is read-only, but writing creates a race condition. | 142 # if pre-cached this is read-only, but writing creates a race condition. |
121 bytecode_cache=jinja2.FileSystemBytecodeCache(cache_dir), | 143 bytecode_cache=jinja2.FileSystemBytecodeCache(cache_dir), |
122 keep_trailing_newline=True, # newline-terminate generated files | 144 keep_trailing_newline=True, # newline-terminate generated files |
123 lstrip_blocks=True, # so can indent control flow tags | 145 lstrip_blocks=True, # so can indent control flow tags |
124 trim_blocks=True) | 146 trim_blocks=True) |
125 jinja_env.filters.update({"to_title_case": to_title_case, "dash_to_camelcase
": dash_to_camelcase}) | 147 jinja_env.filters.update({"to_title_case": to_title_case, "dash_to_camelcase
": dash_to_camelcase, "to_method_case": functools.partial(to_method_case, config
)}) |
126 jinja_env.add_extension("jinja2.ext.loopcontrols") | 148 jinja_env.add_extension("jinja2.ext.loopcontrols") |
127 return jinja_env | 149 return jinja_env |
128 | 150 |
129 | 151 |
130 def patch_full_qualified_refs(protocol): | 152 def patch_full_qualified_refs(protocol): |
131 def patch_full_qualified_refs_in_domain(json, domain_name): | 153 def patch_full_qualified_refs_in_domain(json, domain_name): |
132 if isinstance(json, list): | 154 if isinstance(json, list): |
133 for item in json: | 155 for item in json: |
134 patch_full_qualified_refs_in_domain(item, domain_name) | 156 patch_full_qualified_refs_in_domain(item, domain_name) |
135 | 157 |
136 if not isinstance(json, dict): | 158 if not isinstance(json, dict): |
137 return | 159 return |
138 for key in json: | 160 for key in json: |
139 if key == "type" and json[key] == "string": | 161 if key == "type" and json[key] == "string": |
140 json[key] = domain_name + ".string" | 162 json[key] = domain_name + ".string" |
141 if key != "$ref": | 163 if key != "$ref": |
142 patch_full_qualified_refs_in_domain(json[key], domain_name) | 164 patch_full_qualified_refs_in_domain(json[key], domain_name) |
143 continue | 165 continue |
144 if json["$ref"].find(".") == -1: | 166 if json["$ref"].find(".") == -1: |
145 json["$ref"] = domain_name + "." + json["$ref"] | 167 json["$ref"] = domain_name + "." + json["$ref"] |
146 return | 168 return |
147 | 169 |
148 for domain in protocol.json_api["domains"]: | 170 for domain in protocol.json_api["domains"]: |
149 patch_full_qualified_refs_in_domain(domain, domain["domain"]) | 171 patch_full_qualified_refs_in_domain(domain, domain["domain"]) |
150 | 172 |
151 | 173 |
152 def calculate_exports(protocol): | 174 def calculate_imports_and_exports(config, protocol): |
153 def calculate_exports_in_json(json_value): | 175 def has_exports(json_value, clear): |
154 has_exports = False | 176 result = False |
155 if isinstance(json_value, list): | 177 if isinstance(json_value, list): |
156 for item in json_value: | 178 for item in json_value: |
157 has_exports = calculate_exports_in_json(item) or has_exports | 179 result = has_exports(item, clear) or result |
158 if isinstance(json_value, dict): | 180 if isinstance(json_value, dict): |
159 has_exports = ("exported" in json_value and json_value["exported"])
or has_exports | 181 if "exported" in json_value and json_value["exported"]: |
| 182 result = True |
| 183 if "exported" in json_value and clear: |
| 184 del json_value["exported"] |
160 for key in json_value: | 185 for key in json_value: |
161 has_exports = calculate_exports_in_json(json_value[key]) or has_
exports | 186 result = has_exports(json_value[key], clear) or result |
162 return has_exports | 187 return result |
163 | 188 |
164 protocol.json_api["has_exports"] = False | 189 imported_domains = protocol.imported_domains |
| 190 if config.protocol.options: |
| 191 protocol.generate_domains = [rule.domain for rule in config.protocol.opt
ions] |
| 192 imported_domains = list(set(protocol.imported_domains) - set(protocol.ge
nerate_domains)) |
| 193 exported_domains = protocol.generate_domains |
| 194 |
| 195 protocol.imported_domains = [] |
| 196 protocol.exported_domains = [] |
165 for domain_json in protocol.json_api["domains"]: | 197 for domain_json in protocol.json_api["domains"]: |
166 domain_json["has_exports"] = calculate_exports_in_json(domain_json) | 198 domain = domain_json["domain"] |
167 if domain_json["has_exports"] and domain_json["domain"] in protocol.gene
rate_domains: | 199 clear = domain not in exported_domains and domain not in imported_domain
s |
168 protocol.json_api["has_exports"] = True | 200 if not has_exports(domain_json, clear): |
| 201 continue |
| 202 if domain in exported_domains: |
| 203 domain_json["has_exports"] = True |
| 204 protocol.exported_domains.append(domain) |
| 205 if domain in imported_domains: |
| 206 protocol.imported_domains.append(domain) |
169 | 207 |
170 | 208 |
171 def create_imported_type_definition(domain_name, type, imported_namespace): | 209 def create_imported_type_definition(domain_name, type, imported_namespace): |
172 # pylint: disable=W0622 | 210 # pylint: disable=W0622 |
173 return { | 211 return { |
174 "return_type": "std::unique_ptr<%s::%s::API::%s>" % (imported_namespace,
domain_name, type["id"]), | 212 "return_type": "std::unique_ptr<%s::%s::API::%s>" % (imported_namespace,
domain_name, type["id"]), |
175 "pass_type": "std::unique_ptr<%s::%s::API::%s>" % (imported_namespace, d
omain_name, type["id"]), | 213 "pass_type": "std::unique_ptr<%s::%s::API::%s>" % (imported_namespace, d
omain_name, type["id"]), |
176 "to_raw_type": "%s.get()", | 214 "to_raw_type": "%s.get()", |
177 "to_pass_type": "std::move(%s)", | 215 "to_pass_type": "std::move(%s)", |
178 "to_rvalue": "std::move(%s)", | 216 "to_rvalue": "std::move(%s)", |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
279 return { | 317 return { |
280 "return_type": "std::unique_ptr<protocol::Array<%s>>" % type["raw_type"]
, | 318 "return_type": "std::unique_ptr<protocol::Array<%s>>" % type["raw_type"]
, |
281 "pass_type": "std::unique_ptr<protocol::Array<%s>>" % type["raw_type"], | 319 "pass_type": "std::unique_ptr<protocol::Array<%s>>" % type["raw_type"], |
282 "to_raw_type": "%s.get()", | 320 "to_raw_type": "%s.get()", |
283 "to_pass_type": "std::move(%s)", | 321 "to_pass_type": "std::move(%s)", |
284 "to_rvalue": "std::move(%s)", | 322 "to_rvalue": "std::move(%s)", |
285 "type": "std::unique_ptr<protocol::Array<%s>>" % type["raw_type"], | 323 "type": "std::unique_ptr<protocol::Array<%s>>" % type["raw_type"], |
286 "raw_type": "protocol::Array<%s>" % type["raw_type"], | 324 "raw_type": "protocol::Array<%s>" % type["raw_type"], |
287 "raw_pass_type": "protocol::Array<%s>*" % type["raw_type"], | 325 "raw_pass_type": "protocol::Array<%s>*" % type["raw_type"], |
288 "raw_return_type": "protocol::Array<%s>*" % type["raw_type"], | 326 "raw_return_type": "protocol::Array<%s>*" % type["raw_type"], |
289 "create_type": "wrapUnique(new protocol::Array<%s>())" % type["raw_type"
], | |
290 "out_type": "protocol::Array<%s>&" % type["raw_type"], | 327 "out_type": "protocol::Array<%s>&" % type["raw_type"], |
291 } | 328 } |
292 | 329 |
293 | 330 |
294 def create_type_definitions(protocol, imported_namespace): | 331 def create_type_definitions(protocol, imported_namespace): |
295 protocol.type_definitions = {} | 332 protocol.type_definitions = {} |
296 protocol.type_definitions["number"] = create_primitive_type_definition("numb
er") | 333 protocol.type_definitions["number"] = create_primitive_type_definition("numb
er") |
297 protocol.type_definitions["integer"] = create_primitive_type_definition("int
eger") | 334 protocol.type_definitions["integer"] = create_primitive_type_definition("int
eger") |
298 protocol.type_definitions["boolean"] = create_primitive_type_definition("boo
lean") | 335 protocol.type_definitions["boolean"] = create_primitive_type_definition("boo
lean") |
299 protocol.type_definitions["object"] = create_object_type_definition() | 336 protocol.type_definitions["object"] = create_object_type_definition() |
(...skipping 30 matching lines...) Expand all Loading... |
330 | 367 |
331 | 368 |
332 def join_arrays(dict, keys): | 369 def join_arrays(dict, keys): |
333 result = [] | 370 result = [] |
334 for key in keys: | 371 for key in keys: |
335 if key in dict: | 372 if key in dict: |
336 result += dict[key] | 373 result += dict[key] |
337 return result | 374 return result |
338 | 375 |
339 | 376 |
340 def has_disable(commands): | 377 def generate_command(protocol, config, domain, command): |
341 for command in commands: | 378 if not config.protocol.options: |
342 if command["name"] == "disable" and (not ("handlers" in command) or "ren
derer" in command["handlers"]): | 379 return domain in protocol.generate_domains |
343 return True | 380 for rule in config.protocol.options: |
| 381 if rule.domain != domain: |
| 382 continue |
| 383 if hasattr(rule, "include"): |
| 384 return command in rule.include |
| 385 if hasattr(rule, "exclude"): |
| 386 return command not in rule.exclude |
| 387 return True |
344 return False | 388 return False |
345 | 389 |
346 | 390 |
347 def format_include(header): | 391 def generate_event(protocol, config, domain, event): |
348 return "\"" + header + "\"" if header[0] not in "<\"" else header | 392 if not config.protocol.options: |
| 393 return domain in protocol.generate_domains |
| 394 for rule in config.protocol.options: |
| 395 if rule.domain != domain: |
| 396 continue |
| 397 if hasattr(rule, "include_events"): |
| 398 return event in rule.include_events |
| 399 if hasattr(rule, "exclude_events"): |
| 400 return event not in rule.exclude_events |
| 401 return True |
| 402 return False |
| 403 |
| 404 |
| 405 def is_async_command(protocol, config, domain, command): |
| 406 if not config.protocol.options: |
| 407 return False |
| 408 for rule in config.protocol.options: |
| 409 if rule.domain != domain: |
| 410 continue |
| 411 if hasattr(rule, "async"): |
| 412 return command in rule.async |
| 413 return False |
| 414 return False |
| 415 |
| 416 |
| 417 def generate_disable(protocol, config, domain): |
| 418 if "commands" not in domain: |
| 419 return True |
| 420 for command in domain["commands"]: |
| 421 if command["name"] == "disable" and generate_command(protocol, config, d
omain["domain"], "disable"): |
| 422 return False |
| 423 return True |
| 424 |
| 425 |
| 426 def format_include(config, header, file_name=None): |
| 427 if file_name is not None: |
| 428 header = header + "/" + file_name + ".h" |
| 429 header = "\"" + header + "\"" if header[0] not in "<\"" else header |
| 430 if config.use_snake_file_names: |
| 431 header = to_snake_case(header) |
| 432 return header |
| 433 |
| 434 |
| 435 def to_file_name(config, file_name): |
| 436 if config.use_snake_file_names: |
| 437 return to_snake_case(file_name).replace(".cpp", ".cc") |
| 438 return file_name |
349 | 439 |
350 | 440 |
351 def read_protocol_file(file_name, json_api): | 441 def read_protocol_file(file_name, json_api): |
352 input_file = open(file_name, "r") | 442 input_file = open(file_name, "r") |
353 json_string = input_file.read() | 443 json_string = input_file.read() |
354 input_file.close() | 444 input_file.close() |
355 parsed_json = json.loads(json_string) | 445 parsed_json = json.loads(json_string) |
356 version = parsed_json["version"]["major"] + "." + parsed_json["version"]["mi
nor"] | 446 version = parsed_json["version"]["major"] + "." + parsed_json["version"]["mi
nor"] |
357 domains = [] | 447 domains = [] |
358 for domain in parsed_json["domains"]: | 448 for domain in parsed_json["domains"]: |
359 domains.append(domain["domain"]) | 449 domains.append(domain["domain"]) |
360 domain["version"] = version | 450 domain["version"] = version |
361 json_api["domains"] += parsed_json["domains"] | 451 json_api["domains"] += parsed_json["domains"] |
362 return domains | 452 return domains |
363 | 453 |
364 | 454 |
365 class Protocol(object): | 455 class Protocol(object): |
366 def __init__(self): | 456 def __init__(self): |
367 self.json_api = {} | 457 self.json_api = {} |
368 self.generate_domains = [] | 458 self.generate_domains = [] |
369 self.imported_domains = [] | 459 self.imported_domains = [] |
| 460 self.exported_domains = [] |
370 | 461 |
371 | 462 |
372 def main(): | 463 def main(): |
373 jinja_dir, config_file, config = read_config() | 464 jinja_dir, config_file, config = read_config() |
374 | 465 |
375 protocol = Protocol() | 466 protocol = Protocol() |
376 protocol.json_api = {"domains": []} | 467 protocol.json_api = {"domains": []} |
377 protocol.generate_domains = read_protocol_file(config.protocol.path, protoco
l.json_api) | 468 protocol.generate_domains = read_protocol_file(config.protocol.path, protoco
l.json_api) |
378 protocol.imported_domains = read_protocol_file(config.imported.path, protoco
l.json_api) if config.imported else [] | 469 protocol.imported_domains = read_protocol_file(config.imported.path, protoco
l.json_api) if config.imported else [] |
379 patch_full_qualified_refs(protocol) | 470 patch_full_qualified_refs(protocol) |
380 calculate_exports(protocol) | 471 calculate_imports_and_exports(config, protocol) |
381 create_type_definitions(protocol, "::".join(config.imported.namespace) if co
nfig.imported else "") | 472 create_type_definitions(protocol, "::".join(config.imported.namespace) if co
nfig.imported else "") |
382 | 473 |
383 if not config.exported: | 474 if not config.exported and len(protocol.exported_domains): |
384 for domain_json in protocol.json_api["domains"]: | 475 sys.stderr.write("Domains [%s] are exported, but config is missing expor
t entry\n\n" % ", ".join(protocol.exported_domains)) |
385 if domain_json["has_exports"] and domain_json["domain"] in protocol.
generate_domains: | 476 exit(1) |
386 sys.stderr.write("Domain %s is exported, but config is missing e
xport entry\n\n" % domain_json["domain"]) | |
387 exit(1) | |
388 | 477 |
389 if not os.path.exists(config.protocol.output): | 478 if not os.path.exists(config.protocol.output): |
390 os.mkdir(config.protocol.output) | 479 os.mkdir(config.protocol.output) |
391 if protocol.json_api["has_exports"] and not os.path.exists(config.exported.o
utput): | 480 if len(protocol.exported_domains) and not os.path.exists(config.exported.out
put): |
392 os.mkdir(config.exported.output) | 481 os.mkdir(config.exported.output) |
393 jinja_env = initialize_jinja_env(jinja_dir, config.protocol.output) | 482 jinja_env = initialize_jinja_env(jinja_dir, config.protocol.output, config) |
394 | 483 |
395 inputs = [] | 484 inputs = [] |
396 inputs.append(__file__) | 485 inputs.append(__file__) |
397 inputs.append(config_file) | 486 inputs.append(config_file) |
398 inputs.append(config.protocol.path) | 487 inputs.append(config.protocol.path) |
399 if config.imported: | 488 if config.imported: |
400 inputs.append(config.imported.path) | 489 inputs.append(config.imported.path) |
401 templates_dir = os.path.join(module_path, "templates") | 490 templates_dir = os.path.join(module_path, "templates") |
402 inputs.append(os.path.join(templates_dir, "TypeBuilder_h.template")) | 491 inputs.append(os.path.join(templates_dir, "TypeBuilder_h.template")) |
403 inputs.append(os.path.join(templates_dir, "TypeBuilder_cpp.template")) | 492 inputs.append(os.path.join(templates_dir, "TypeBuilder_cpp.template")) |
404 inputs.append(os.path.join(templates_dir, "Exported_h.template")) | 493 inputs.append(os.path.join(templates_dir, "Exported_h.template")) |
405 inputs.append(os.path.join(templates_dir, "Imported_h.template")) | 494 inputs.append(os.path.join(templates_dir, "Imported_h.template")) |
406 | 495 |
407 h_template = jinja_env.get_template("templates/TypeBuilder_h.template") | 496 h_template = jinja_env.get_template("templates/TypeBuilder_h.template") |
408 cpp_template = jinja_env.get_template("templates/TypeBuilder_cpp.template") | 497 cpp_template = jinja_env.get_template("templates/TypeBuilder_cpp.template") |
409 exported_template = jinja_env.get_template("templates/Exported_h.template") | 498 exported_template = jinja_env.get_template("templates/Exported_h.template") |
410 imported_template = jinja_env.get_template("templates/Imported_h.template") | 499 imported_template = jinja_env.get_template("templates/Imported_h.template") |
411 | 500 |
412 outputs = dict() | 501 outputs = dict() |
413 | 502 |
414 for domain in protocol.json_api["domains"]: | 503 for domain in protocol.json_api["domains"]: |
415 class_name = domain["domain"] | 504 class_name = domain["domain"] |
416 template_context = { | 505 template_context = { |
417 "config": config, | 506 "config": config, |
418 "domain": domain, | 507 "domain": domain, |
419 "join_arrays": join_arrays, | 508 "join_arrays": join_arrays, |
420 "resolve_type": functools.partial(resolve_type, protocol), | 509 "resolve_type": functools.partial(resolve_type, protocol), |
421 "type_definition": functools.partial(type_definition, protocol), | 510 "type_definition": functools.partial(type_definition, protocol), |
422 "has_disable": has_disable, | 511 "generate_command": functools.partial(generate_command, protocol, co
nfig), |
423 "format_include": format_include | 512 "generate_event": functools.partial(generate_event, protocol, config
), |
| 513 "is_async_command": functools.partial(is_async_command, protocol, co
nfig), |
| 514 "generate_disable": functools.partial(generate_disable, protocol, co
nfig), |
| 515 "format_include": functools.partial(format_include, config), |
424 } | 516 } |
425 | 517 |
426 if domain["domain"] in protocol.generate_domains: | 518 if domain["domain"] in protocol.generate_domains: |
427 outputs[os.path.join(config.protocol.output, class_name + ".h")] = h
_template.render(template_context) | 519 outputs[os.path.join(config.protocol.output, to_file_name(config, cl
ass_name + ".h"))] = h_template.render(template_context) |
428 outputs[os.path.join(config.protocol.output, class_name + ".cpp")] =
cpp_template.render(template_context) | 520 outputs[os.path.join(config.protocol.output, to_file_name(config, cl
ass_name + ".cpp"))] = cpp_template.render(template_context) |
429 if domain["has_exports"]: | 521 if domain["domain"] in protocol.exported_domains: |
430 outputs[os.path.join(config.exported.output, class_name + ".h")]
= exported_template.render(template_context) | 522 outputs[os.path.join(config.exported.output, to_file_name(config
, class_name + ".h"))] = exported_template.render(template_context) |
431 if domain["domain"] in protocol.imported_domains and domain["has_exports
"]: | 523 if domain["domain"] in protocol.imported_domains: |
432 outputs[os.path.join(config.protocol.output, class_name + ".h")] = i
mported_template.render(template_context) | 524 outputs[os.path.join(config.protocol.output, to_file_name(config, cl
ass_name + ".h"))] = imported_template.render(template_context) |
433 | 525 |
434 if config.lib: | 526 if config.lib: |
435 template_context = { | 527 template_context = { |
436 "config": config, | 528 "config": config, |
437 "format_include": format_include, | 529 "format_include": functools.partial(format_include, config), |
438 } | 530 } |
439 | 531 |
440 lib_templates_dir = os.path.join(module_path, "lib") | 532 lib_templates_dir = os.path.join(module_path, "lib") |
441 # Note these should be sorted in the right order. | 533 # Note these should be sorted in the right order. |
442 # TODO(dgozman): sort them programmatically based on commented includes. | 534 # TODO(dgozman): sort them programmatically based on commented includes. |
443 lib_h_templates = [ | 535 lib_h_templates = [ |
444 "Collections_h.template", | 536 "Collections_h.template", |
445 "ErrorSupport_h.template", | 537 "ErrorSupport_h.template", |
446 "Values_h.template", | 538 "Values_h.template", |
447 "Object_h.template", | 539 "Object_h.template", |
(...skipping 20 matching lines...) Expand all Loading... |
468 ] | 560 ] |
469 | 561 |
470 def generate_lib_file(file_name, template_files): | 562 def generate_lib_file(file_name, template_files): |
471 parts = [] | 563 parts = [] |
472 for template_file in template_files: | 564 for template_file in template_files: |
473 inputs.append(os.path.join(lib_templates_dir, template_file)) | 565 inputs.append(os.path.join(lib_templates_dir, template_file)) |
474 template = jinja_env.get_template("lib/" + template_file) | 566 template = jinja_env.get_template("lib/" + template_file) |
475 parts.append(template.render(template_context)) | 567 parts.append(template.render(template_context)) |
476 outputs[file_name] = "\n\n".join(parts) | 568 outputs[file_name] = "\n\n".join(parts) |
477 | 569 |
478 generate_lib_file(os.path.join(config.lib.output, "Forward.h"), forward_
h_templates) | 570 generate_lib_file(os.path.join(config.lib.output, to_file_name(config, "
Forward.h")), forward_h_templates) |
479 generate_lib_file(os.path.join(config.lib.output, "Protocol.h"), lib_h_t
emplates) | 571 generate_lib_file(os.path.join(config.lib.output, to_file_name(config, "
Protocol.h")), lib_h_templates) |
480 generate_lib_file(os.path.join(config.lib.output, "Protocol.cpp"), lib_c
pp_templates) | 572 generate_lib_file(os.path.join(config.lib.output, to_file_name(config, "
Protocol.cpp")), lib_cpp_templates) |
481 | 573 |
482 # Make gyp / make generatos happy, otherwise make rebuilds world. | 574 # Make gyp / make generatos happy, otherwise make rebuilds world. |
483 inputs_ts = max(map(os.path.getmtime, inputs)) | 575 inputs_ts = max(map(os.path.getmtime, inputs)) |
484 up_to_date = True | 576 up_to_date = True |
485 for output_file in outputs.iterkeys(): | 577 for output_file in outputs.iterkeys(): |
486 if not os.path.exists(output_file) or os.path.getmtime(output_file) < in
puts_ts: | 578 if not os.path.exists(output_file) or os.path.getmtime(output_file) < in
puts_ts: |
487 up_to_date = False | 579 up_to_date = False |
488 break | 580 break |
489 if up_to_date: | 581 if up_to_date: |
490 sys.exit() | 582 sys.exit() |
491 | 583 |
492 for file_name, content in outputs.iteritems(): | 584 for file_name, content in outputs.iteritems(): |
493 out_file = open(file_name, "w") | 585 out_file = open(file_name, "w") |
494 out_file.write(content) | 586 out_file.write(content) |
495 out_file.close() | 587 out_file.close() |
496 | 588 |
497 | 589 |
498 main() | 590 main() |
OLD | NEW |