| 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 string | 7 import string |
| 8 import optparse | 8 import optparse |
| 9 import re | 9 import re |
| 10 try: | 10 try: |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 module_path, os.pardir, os.pardir, os.pardir, os.pardir)) | 26 module_path, os.pardir, os.pardir, os.pardir, os.pardir)) |
| 27 | 27 |
| 28 # jinja2 is in chromium's third_party directory. | 28 # jinja2 is in chromium's third_party directory. |
| 29 # Insert at 1 so at front to override system libraries, and | 29 # Insert at 1 so at front to override system libraries, and |
| 30 # after path[0] == invoking script dir | 30 # after path[0] == invoking script dir |
| 31 | 31 |
| 32 sys.path.insert(1, third_party_dir) | 32 sys.path.insert(1, third_party_dir) |
| 33 import jinja2 | 33 import jinja2 |
| 34 | 34 |
| 35 cmdline_parser = optparse.OptionParser() | 35 cmdline_parser = optparse.OptionParser() |
| 36 cmdline_parser.add_option("--domains") |
| 36 cmdline_parser.add_option("--output_dir") | 37 cmdline_parser.add_option("--output_dir") |
| 37 cmdline_parser.add_option("--generate_dispatcher") | 38 cmdline_parser.add_option("--output_package") |
| 39 cmdline_parser.add_option("--string_type") |
| 40 cmdline_parser.add_option("--export_macro") |
| 41 |
| 42 generate_domains = set() |
| 38 | 43 |
| 39 try: | 44 try: |
| 40 arg_options, arg_values = cmdline_parser.parse_args() | 45 arg_options, arg_values = cmdline_parser.parse_args() |
| 41 if (len(arg_values) == 0): | 46 if (len(arg_values) == 0): |
| 42 raise Exception("At least one plain argument expected (found %s)" % len(
arg_values)) | 47 raise Exception("At least one plain argument expected (found %s)" % len(
arg_values)) |
| 43 output_dirname = arg_options.output_dir | 48 output_dirname = arg_options.output_dir |
| 44 generate_dispatcher = arg_options.generate_dispatcher | |
| 45 if not output_dirname: | 49 if not output_dirname: |
| 46 raise Exception("Output directory must be specified") | 50 raise Exception("Output directory must be specified") |
| 51 output_package = arg_options.output_package |
| 52 if not output_package: |
| 53 raise Exception("Output package must be specified") |
| 54 string_type = arg_options.string_type |
| 55 if not string_type: |
| 56 raise Exception("String type must be specified") |
| 57 export_macro = arg_options.export_macro |
| 58 if not export_macro: |
| 59 raise Exception("Export macro must be specified") |
| 60 output_domains = arg_options.domains |
| 61 if output_domains and len(output_domains): |
| 62 for domain in output_domains.split(","): |
| 63 generate_domains.add(domain) |
| 47 except Exception: | 64 except Exception: |
| 48 # Work with python 2 and 3 http://docs.python.org/py3k/howto/pyporting.html | 65 # Work with python 2 and 3 http://docs.python.org/py3k/howto/pyporting.html |
| 49 exc = sys.exc_info()[1] | 66 exc = sys.exc_info()[1] |
| 50 sys.stderr.write("Failed to parse command-line arguments: %s\n\n" % exc) | 67 sys.stderr.write("Failed to parse command-line arguments: %s\n\n" % exc) |
| 51 sys.stderr.write("Usage: <script> --output_dir <output_dir> blink_protocol.j
son v8_protocol.json ...\n") | 68 sys.stderr.write("Usage: <script> --output_dir <output_dir> protocol.json ..
.\n") |
| 52 exit(1) | 69 exit(1) |
| 53 | 70 |
| 54 json_api = {"domains": []} | 71 json_api = {"domains": []} |
| 55 | 72 |
| 56 json_timestamp = 0 | 73 json_timestamp = 0 |
| 57 | 74 |
| 58 for filename in arg_values: | 75 for filename in arg_values: |
| 59 json_timestamp = max(os.path.getmtime(filename), json_timestamp) | 76 json_timestamp = max(os.path.getmtime(filename), json_timestamp) |
| 60 input_file = open(filename, "r") | 77 input_file = open(filename, "r") |
| 61 json_string = input_file.read() | 78 json_string = input_file.read() |
| (...skipping 19 matching lines...) Expand all Loading... |
| 81 trim_blocks=True) | 98 trim_blocks=True) |
| 82 jinja_env.filters.update({"to_title_case": to_title_case, "dash_to_camelcase
": dash_to_camelcase}) | 99 jinja_env.filters.update({"to_title_case": to_title_case, "dash_to_camelcase
": dash_to_camelcase}) |
| 83 jinja_env.add_extension('jinja2.ext.loopcontrols') | 100 jinja_env.add_extension('jinja2.ext.loopcontrols') |
| 84 return jinja_env | 101 return jinja_env |
| 85 | 102 |
| 86 | 103 |
| 87 def output_file(file_name): | 104 def output_file(file_name): |
| 88 return open(file_name, "w") | 105 return open(file_name, "w") |
| 89 | 106 |
| 90 | 107 |
| 91 def topsort_domains(): | |
| 92 domains = {} | |
| 93 for domain in json_api["domains"]: | |
| 94 domains[domain["domain"]] = domain | |
| 95 | |
| 96 processed = set() | |
| 97 result = [] | |
| 98 | |
| 99 def process(name): | |
| 100 if name in processed: | |
| 101 return | |
| 102 domain = domains[name] | |
| 103 deps = [] | |
| 104 if "depends" in domain: | |
| 105 for dep in domain["depends"]: | |
| 106 process(dep) | |
| 107 result.append(domain) | |
| 108 processed.add(name) | |
| 109 | |
| 110 for domain in json_api["domains"]: | |
| 111 process(domain["domain"]) | |
| 112 json_api["domains"] = result | |
| 113 | |
| 114 | |
| 115 def patch_full_qualified_refs(): | 108 def patch_full_qualified_refs(): |
| 116 def patch_full_qualified_refs_in_domain(json, domain_name): | 109 def patch_full_qualified_refs_in_domain(json, domain_name): |
| 117 if isinstance(json, list): | 110 if isinstance(json, list): |
| 118 for item in json: | 111 for item in json: |
| 119 patch_full_qualified_refs_in_domain(item, domain_name) | 112 patch_full_qualified_refs_in_domain(item, domain_name) |
| 120 | 113 |
| 121 if not isinstance(json, dict): | 114 if not isinstance(json, dict): |
| 122 return | 115 return |
| 123 for key in json: | 116 for key in json: |
| 124 if key == "type" and json[key] == "string": | 117 if key == "type" and json[key] == "string": |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 169 "to_pass_type": "std::move(%s)", | 162 "to_pass_type": "std::move(%s)", |
| 170 "to_rvalue": "std::move(%s)", | 163 "to_rvalue": "std::move(%s)", |
| 171 "type": "std::unique_ptr<protocol::Value>", | 164 "type": "std::unique_ptr<protocol::Value>", |
| 172 "raw_type": "protocol::Value", | 165 "raw_type": "protocol::Value", |
| 173 "raw_pass_type": "protocol::Value*", | 166 "raw_pass_type": "protocol::Value*", |
| 174 "raw_return_type": "protocol::Value*", | 167 "raw_return_type": "protocol::Value*", |
| 175 } | 168 } |
| 176 | 169 |
| 177 | 170 |
| 178 def create_string_type_definition(domain): | 171 def create_string_type_definition(domain): |
| 179 if domain in ["Runtime", "Debugger", "Profiler", "HeapProfiler"]: | |
| 180 return { | |
| 181 "return_type": "String16", | |
| 182 "pass_type": "const String16&", | |
| 183 "to_pass_type": "%s", | |
| 184 "to_raw_type": "%s", | |
| 185 "to_rvalue": "%s", | |
| 186 "type": "String16", | |
| 187 "raw_type": "String16", | |
| 188 "raw_pass_type": "const String16&", | |
| 189 "raw_return_type": "String16", | |
| 190 } | |
| 191 return { | 172 return { |
| 192 "return_type": "String", | 173 "return_type": string_type, |
| 193 "pass_type": "const String&", | 174 "pass_type": ("const %s&" % string_type), |
| 194 "to_pass_type": "%s", | 175 "to_pass_type": "%s", |
| 195 "to_raw_type": "%s", | 176 "to_raw_type": "%s", |
| 196 "to_rvalue": "%s", | 177 "to_rvalue": "%s", |
| 197 "type": "String", | 178 "type": string_type, |
| 198 "raw_type": "String", | 179 "raw_type": string_type, |
| 199 "raw_pass_type": "const String&", | 180 "raw_pass_type": ("const %s&" % string_type), |
| 200 "raw_return_type": "String", | 181 "raw_return_type": string_type, |
| 201 } | 182 } |
| 202 | 183 |
| 203 | 184 |
| 204 def create_primitive_type_definition(type): | 185 def create_primitive_type_definition(type): |
| 205 typedefs = { | 186 typedefs = { |
| 206 "number": "double", | 187 "number": "double", |
| 207 "integer": "int", | 188 "integer": "int", |
| 208 "boolean": "bool" | 189 "boolean": "bool" |
| 209 } | 190 } |
| 210 jsontypes = { | 191 jsontypes = { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 256 if type["type"] == "object": | 237 if type["type"] == "object": |
| 257 type_definitions[domain["domain"] + "." + type["id"]] = create_u
ser_type_definition(domain["domain"], type) | 238 type_definitions[domain["domain"] + "." + type["id"]] = create_u
ser_type_definition(domain["domain"], type) |
| 258 elif type["type"] == "array": | 239 elif type["type"] == "array": |
| 259 items_type = type["items"]["type"] | 240 items_type = type["items"]["type"] |
| 260 type_definitions[domain["domain"] + "." + type["id"]] = wrap_arr
ay_definition(type_definitions[items_type]) | 241 type_definitions[domain["domain"] + "." + type["id"]] = wrap_arr
ay_definition(type_definitions[items_type]) |
| 261 elif type["type"] == domain["domain"] + ".string": | 242 elif type["type"] == domain["domain"] + ".string": |
| 262 type_definitions[domain["domain"] + "." + type["id"]] = create_s
tring_type_definition(domain["domain"]) | 243 type_definitions[domain["domain"] + "." + type["id"]] = create_s
tring_type_definition(domain["domain"]) |
| 263 else: | 244 else: |
| 264 type_definitions[domain["domain"] + "." + type["id"]] = create_p
rimitive_type_definition(type["type"]) | 245 type_definitions[domain["domain"] + "." + type["id"]] = create_p
rimitive_type_definition(type["type"]) |
| 265 | 246 |
| 266 topsort_domains() | |
| 267 patch_full_qualified_refs() | 247 patch_full_qualified_refs() |
| 268 create_type_definitions() | 248 create_type_definitions() |
| 269 | 249 |
| 270 | 250 |
| 271 def type_definition(name): | 251 def type_definition(name): |
| 272 return type_definitions[name] | 252 return type_definitions[name] |
| 273 | 253 |
| 274 | 254 |
| 275 def resolve_type(property): | 255 def resolve_type(property): |
| 276 if "$ref" in property: | 256 if "$ref" in property: |
| (...skipping 24 matching lines...) Expand all Loading... |
| 301 current_script_timestamp = 0 | 281 current_script_timestamp = 0 |
| 302 | 282 |
| 303 | 283 |
| 304 def is_up_to_date(file, template): | 284 def is_up_to_date(file, template): |
| 305 if not os.path.exists(file): | 285 if not os.path.exists(file): |
| 306 return False | 286 return False |
| 307 timestamp = os.path.getmtime(file) | 287 timestamp = os.path.getmtime(file) |
| 308 return timestamp > max(os.path.getmtime(module_path + template), | 288 return timestamp > max(os.path.getmtime(module_path + template), |
| 309 current_script_timestamp, json_timestamp) | 289 current_script_timestamp, json_timestamp) |
| 310 | 290 |
| 291 if not os.path.exists(output_dirname): |
| 292 os.mkdir(output_dirname) |
| 293 jinja_env = initialize_jinja_env(output_dirname) |
| 311 | 294 |
| 312 def generate(class_name): | 295 h_template_name = "/TypeBuilder_h.template" |
| 313 h_template_name = "/%s_h.template" % class_name | 296 cpp_template_name = "/TypeBuilder_cpp.template" |
| 314 cpp_template_name = "/%s_cpp.template" % class_name | 297 h_template = jinja_env.get_template(h_template_name) |
| 298 cpp_template = jinja_env.get_template(cpp_template_name) |
| 299 |
| 300 |
| 301 def generate(domain): |
| 302 class_name = domain["domain"] |
| 315 h_file_name = output_dirname + "/" + class_name + ".h" | 303 h_file_name = output_dirname + "/" + class_name + ".h" |
| 316 cpp_file_name = output_dirname + "/" + class_name + ".cpp" | 304 cpp_file_name = output_dirname + "/" + class_name + ".cpp" |
| 317 | 305 |
| 318 if (is_up_to_date(cpp_file_name, cpp_template_name) and | 306 if (is_up_to_date(cpp_file_name, cpp_template_name) and |
| 319 is_up_to_date(h_file_name, h_template_name)): | 307 is_up_to_date(h_file_name, h_template_name)): |
| 320 return | 308 return |
| 321 | 309 |
| 322 template_context = { | 310 template_context = { |
| 323 "class_name": class_name, | 311 "domain": domain, |
| 324 "api": json_api, | |
| 325 "join_arrays": join_arrays, | 312 "join_arrays": join_arrays, |
| 326 "resolve_type": resolve_type, | 313 "resolve_type": resolve_type, |
| 327 "type_definition": type_definition, | 314 "type_definition": type_definition, |
| 328 "has_disable": has_disable | 315 "has_disable": has_disable, |
| 316 "export_macro": export_macro, |
| 317 "output_package": output_package, |
| 329 } | 318 } |
| 330 h_template = jinja_env.get_template(h_template_name) | |
| 331 cpp_template = jinja_env.get_template(cpp_template_name) | |
| 332 h_file = output_file(h_file_name) | 319 h_file = output_file(h_file_name) |
| 333 cpp_file = output_file(cpp_file_name) | 320 cpp_file = output_file(cpp_file_name) |
| 334 h_file.write(h_template.render(template_context)) | 321 h_file.write(h_template.render(template_context)) |
| 335 cpp_file.write(cpp_template.render(template_context)) | 322 cpp_file.write(cpp_template.render(template_context)) |
| 336 h_file.close() | 323 h_file.close() |
| 337 cpp_file.close() | 324 cpp_file.close() |
| 338 | 325 |
| 339 | 326 |
| 340 jinja_env = initialize_jinja_env(output_dirname) | 327 for domain in json_api["domains"]: |
| 341 generate("TypeBuilder") | 328 if domain["domain"] in generate_domains: |
| 329 generate(domain) |
| OLD | NEW |