Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2011 Google Inc. All rights reserved. | 2 |
| 3 # Copyright (c) 2012 Intel Corporation. All rights reserved. | 3 # Copyright 2016 The Chromium Authors. All rights reserved. |
| 4 # | 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # Redistribution and use in source and binary forms, with or without | 5 # found in the LICENSE file. |
| 6 # modification, are permitted provided that the following conditions are | |
| 7 # met: | |
| 8 # | |
| 9 # * Redistributions of source code must retain the above copyright | |
| 10 # notice, this list of conditions and the following disclaimer. | |
| 11 # * Redistributions in binary form must reproduce the above | |
| 12 # copyright notice, this list of conditions and the following disclaimer | |
| 13 # in the documentation and/or other materials provided with the | |
| 14 # distribution. | |
| 15 # * Neither the name of Google Inc. nor the names of its | |
| 16 # contributors may be used to endorse or promote products derived from | |
| 17 # this software without specific prior written permission. | |
| 18 # | |
| 19 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 20 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 21 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| 22 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| 23 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| 24 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| 25 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| 26 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| 27 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 28 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| 29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 30 | 6 |
| 31 import os.path | 7 import os.path |
| 32 import sys | 8 import sys |
| 33 import string | 9 import string |
| 34 import optparse | 10 import optparse |
| 35 import re | 11 import re |
| 36 try: | 12 try: |
| 37 import json | 13 import json |
| 38 except ImportError: | 14 except ImportError: |
| 39 import simplejson as json | 15 import simplejson as json |
| 40 | 16 |
| 41 import CodeGeneratorStrings | 17 # Path handling for libraries and templates |
| 18 # Paths have to be normalized because Jinja uses the exact template path to | |
| 19 # determine the hash used in the cache filename, and we need a pre-caching step | |
| 20 # to be concurrency-safe. Use absolute path because __file__ is absolute if | |
| 21 # module is imported, and relative if executed directly. | |
| 22 # If paths differ between pre-caching and individual file compilation, the cache | |
| 23 # is regenerated, which causes a race condition and breaks concurrent build, | |
| 24 # since some compile processes will try to read the partially written cache. | |
| 25 module_path, module_filename = os.path.split(os.path.realpath(__file__)) | |
| 26 templates_dir = module_path | |
| 27 third_party_dir = os.path.normpath(os.path.join( | |
| 28 module_path, os.pardir, os.pardir, os.pardir, os.pardir)) | |
| 42 | 29 |
| 43 # Manually-filled map of type name replacements. | 30 # jinja2 is in chromium's third_party directory. |
| 44 TYPE_NAME_FIX_MAP = { | 31 # Insert at 1 so at front to override system libraries, and |
| 45 "RGBA": "Rgba", # RGBA is reported to be conflicting with a define name in Windows CE. | 32 # after path[0] == invoking script dir |
| 46 "": "Empty", | 33 sys.path.insert(1, third_party_dir) |
| 47 } | 34 import jinja2 |
| 48 | |
| 49 | |
| 50 TYPES_WITH_RUNTIME_CAST_SET = frozenset(["Runtime.RemoteObject", "Runtime.Proper tyDescriptor", "Runtime.InternalPropertyDescriptor", | |
| 51 "Debugger.FunctionDetails", "Debugger.G eneratorObjectDetails", "Debugger.CollectionEntry", "Debugger.CallFrame", "Debug ger.Location"]) | |
| 52 | 35 |
| 53 cmdline_parser = optparse.OptionParser() | 36 cmdline_parser = optparse.OptionParser() |
| 54 cmdline_parser.add_option("--output_dir") | 37 cmdline_parser.add_option("--output_dir") |
| 38 cmdline_parser.add_option("--template_dir") | |
| 55 | 39 |
| 56 try: | 40 try: |
| 57 arg_options, arg_values = cmdline_parser.parse_args() | 41 arg_options, arg_values = cmdline_parser.parse_args() |
| 58 if (len(arg_values) != 1): | 42 if (len(arg_values) != 1): |
| 59 raise Exception("Exactly one plain argument expected (found %s)" % len(a rg_values)) | 43 raise Exception("Exactly one plain argument expected (found %s)" % len(a rg_values)) |
| 60 input_json_filename = arg_values[0] | 44 input_json_filename = arg_values[0] |
| 61 output_dirname = arg_options.output_dir | 45 output_dirname = arg_options.output_dir |
| 62 if not output_dirname: | 46 if not output_dirname: |
| 63 raise Exception("Output directory must be specified") | 47 raise Exception("Output directory must be specified") |
| 64 except Exception: | 48 except Exception: |
| 65 # Work with python 2 and 3 http://docs.python.org/py3k/howto/pyporting.html | 49 # Work with python 2 and 3 http://docs.python.org/py3k/howto/pyporting.html |
| 66 exc = sys.exc_info()[1] | 50 exc = sys.exc_info()[1] |
| 67 sys.stderr.write("Failed to parse command-line arguments: %s\n\n" % exc) | 51 sys.stderr.write("Failed to parse command-line arguments: %s\n\n" % exc) |
| 68 sys.stderr.write("Usage: <script> --output_dir <output_dir> protocol.json\n" ) | 52 sys.stderr.write("Usage: <script> --output_dir <output_dir> protocol.json\n" ) |
| 69 exit(1) | 53 exit(1) |
| 70 | 54 |
| 71 | |
| 72 # FIXME: move this methods under Capitalizer class below and remove duplications . | |
| 73 def dash_to_camelcase(word): | |
| 74 return ''.join(x.capitalize() or '-' for x in word.split('-')) | |
| 75 | |
| 76 | |
| 77 def fix_camel_case(name): | |
| 78 refined = re.sub(r'-(\w)', lambda pat: pat.group(1).upper(), name) | |
| 79 refined = to_title_case(refined) | |
| 80 return re.sub(r'(?i)HTML|XML|WML|API', lambda pat: pat.group(0).upper(), ref ined) | |
| 81 | |
| 82 | |
| 83 def to_title_case(name): | |
| 84 return name[:1].upper() + name[1:] | |
| 85 | |
| 86 | |
| 87 class Capitalizer: | |
| 88 @staticmethod | |
| 89 def lower_camel_case_to_upper(str): | |
| 90 if len(str) > 0 and str[0].islower(): | |
| 91 str = str[0].upper() + str[1:] | |
| 92 return str | |
| 93 | |
| 94 @staticmethod | |
| 95 def upper_camel_case_to_lower(str): | |
| 96 pos = 0 | |
| 97 while pos < len(str) and str[pos].isupper(): | |
| 98 pos += 1 | |
| 99 if pos == 0: | |
| 100 return str | |
| 101 if pos == 1: | |
| 102 return str[0].lower() + str[1:] | |
| 103 if pos < len(str): | |
| 104 pos -= 1 | |
| 105 possible_abbreviation = str[0:pos] | |
| 106 if possible_abbreviation not in Capitalizer.ABBREVIATION: | |
| 107 raise Exception("Unknown abbreviation %s" % possible_abbreviation) | |
| 108 str = possible_abbreviation.lower() + str[pos:] | |
| 109 return str | |
| 110 | |
| 111 ABBREVIATION = frozenset(["XHR", "DOM", "CSS", "IO"]) | |
| 112 | |
| 113 VALIDATOR_IFDEF_NAME = "ENABLE(ASSERT)" | |
| 114 | |
| 115 | |
| 116 class DomainNameFixes: | |
| 117 @staticmethod | |
| 118 def get_fixed_data(domain_name): | |
| 119 return Capitalizer.upper_camel_case_to_lower(domain_name) + "Agent" | |
| 120 | |
| 121 class RawTypes(object): | |
| 122 @staticmethod | |
| 123 def get(json_type): | |
| 124 if json_type == "boolean": | |
| 125 return RawTypes.Bool | |
| 126 elif json_type == "string": | |
| 127 return RawTypes.String | |
| 128 elif json_type == "array": | |
| 129 return RawTypes.Array | |
| 130 elif json_type == "object": | |
| 131 return RawTypes.Object | |
| 132 elif json_type == "integer": | |
| 133 return RawTypes.Int | |
| 134 elif json_type == "number": | |
| 135 return RawTypes.Number | |
| 136 elif json_type == "any": | |
| 137 return RawTypes.Any | |
| 138 else: | |
| 139 raise Exception("Unknown type: %s" % json_type) | |
| 140 | |
| 141 class BaseType(object): | |
| 142 @classmethod | |
| 143 def get_raw_validator_call_text(cls): | |
| 144 return "RuntimeCastHelper::assertType<JSONValue::Type%s>" % cls.get_ getter_name() | |
| 145 | |
| 146 @staticmethod | |
| 147 def get_getter_name(): | |
| 148 raise Exception("Unsupported") | |
| 149 | |
| 150 class String(BaseType): | |
| 151 @staticmethod | |
| 152 def get_getter_name(): | |
| 153 return "String" | |
| 154 | |
| 155 get_setter_name = get_getter_name | |
| 156 | |
| 157 @staticmethod | |
| 158 def get_constructor_pattern(): | |
| 159 return "InspectorString::create(%s)" | |
| 160 | |
| 161 @staticmethod | |
| 162 def is_heavy_value(): | |
| 163 return True | |
| 164 | |
| 165 @staticmethod | |
| 166 def get_array_item_raw_c_type_text(): | |
| 167 return "String" | |
| 168 | |
| 169 @staticmethod | |
| 170 def get_raw_type_model(): | |
| 171 return TypeModel.String | |
| 172 | |
| 173 class Int(BaseType): | |
| 174 @staticmethod | |
| 175 def get_getter_name(): | |
| 176 return "Int" | |
| 177 | |
| 178 @staticmethod | |
| 179 def get_setter_name(): | |
| 180 return "Number" | |
| 181 | |
| 182 @staticmethod | |
| 183 def get_constructor_pattern(): | |
| 184 return "InspectorBasicValue::create(%s)" | |
| 185 | |
| 186 @classmethod | |
| 187 def get_raw_validator_call_text(cls): | |
| 188 return "RuntimeCastHelper::assertInt" | |
| 189 | |
| 190 @staticmethod | |
| 191 def is_heavy_value(): | |
| 192 return False | |
| 193 | |
| 194 @staticmethod | |
| 195 def get_array_item_raw_c_type_text(): | |
| 196 return "int" | |
| 197 | |
| 198 @staticmethod | |
| 199 def get_raw_type_model(): | |
| 200 return TypeModel.Int | |
| 201 | |
| 202 class Number(BaseType): | |
| 203 @staticmethod | |
| 204 def get_getter_name(): | |
| 205 return "Double" | |
| 206 | |
| 207 @staticmethod | |
| 208 def get_setter_name(): | |
| 209 return "Number" | |
| 210 | |
| 211 @staticmethod | |
| 212 def get_constructor_pattern(): | |
| 213 return "InspectorBasicValue::create(%s)" | |
| 214 | |
| 215 @staticmethod | |
| 216 def get_raw_validator_call_text(): | |
| 217 return "RuntimeCastHelper::assertType<JSONValue::TypeNumber>" | |
| 218 | |
| 219 @staticmethod | |
| 220 def is_heavy_value(): | |
| 221 return False | |
| 222 | |
| 223 @staticmethod | |
| 224 def get_array_item_raw_c_type_text(): | |
| 225 return "double" | |
| 226 | |
| 227 @staticmethod | |
| 228 def get_raw_type_model(): | |
| 229 return TypeModel.Number | |
| 230 | |
| 231 class Bool(BaseType): | |
| 232 @staticmethod | |
| 233 def get_getter_name(): | |
| 234 return "Boolean" | |
| 235 | |
| 236 get_setter_name = get_getter_name | |
| 237 | |
| 238 @staticmethod | |
| 239 def get_constructor_pattern(): | |
| 240 return "InspectorBasicValue::create(%s)" | |
| 241 | |
| 242 @staticmethod | |
| 243 def is_heavy_value(): | |
| 244 return False | |
| 245 | |
| 246 @staticmethod | |
| 247 def get_array_item_raw_c_type_text(): | |
| 248 return "bool" | |
| 249 | |
| 250 @staticmethod | |
| 251 def get_raw_type_model(): | |
| 252 return TypeModel.Bool | |
| 253 | |
| 254 class Object(BaseType): | |
| 255 @staticmethod | |
| 256 def get_getter_name(): | |
| 257 return "Object" | |
| 258 | |
| 259 @staticmethod | |
| 260 def get_setter_name(): | |
| 261 return "Value" | |
| 262 | |
| 263 @staticmethod | |
| 264 def get_constructor_pattern(): | |
| 265 return "%s" | |
| 266 | |
| 267 @staticmethod | |
| 268 def get_output_argument_prefix(): | |
| 269 return "" | |
| 270 | |
| 271 @staticmethod | |
| 272 def is_heavy_value(): | |
| 273 return True | |
| 274 | |
| 275 @staticmethod | |
| 276 def get_array_item_raw_c_type_text(): | |
| 277 return "JSONObject" | |
| 278 | |
| 279 @staticmethod | |
| 280 def get_raw_type_model(): | |
| 281 return TypeModel.Object | |
| 282 | |
| 283 class Any(BaseType): | |
| 284 @staticmethod | |
| 285 def get_getter_name(): | |
| 286 return "Value" | |
| 287 | |
| 288 get_setter_name = get_getter_name | |
| 289 | |
| 290 @staticmethod | |
| 291 def get_constructor_pattern(): | |
| 292 raise Exception("Unsupported") | |
| 293 | |
| 294 @staticmethod | |
| 295 def get_raw_validator_call_text(): | |
| 296 return "RuntimeCastHelper::assertAny" | |
| 297 | |
| 298 @staticmethod | |
| 299 def is_heavy_value(): | |
| 300 return True | |
| 301 | |
| 302 @staticmethod | |
| 303 def get_array_item_raw_c_type_text(): | |
| 304 return "JSONValue" | |
| 305 | |
| 306 @staticmethod | |
| 307 def get_raw_type_model(): | |
| 308 return TypeModel.Any | |
| 309 | |
| 310 class Array(BaseType): | |
| 311 @staticmethod | |
| 312 def get_getter_name(): | |
| 313 return "Array" | |
| 314 | |
| 315 @staticmethod | |
| 316 def get_setter_name(): | |
| 317 return "Value" | |
| 318 | |
| 319 @staticmethod | |
| 320 def get_constructor_pattern(): | |
| 321 return "%s" | |
| 322 | |
| 323 @staticmethod | |
| 324 def get_output_argument_prefix(): | |
| 325 return "" | |
| 326 | |
| 327 @staticmethod | |
| 328 def is_heavy_value(): | |
| 329 return True | |
| 330 | |
| 331 @staticmethod | |
| 332 def get_array_item_raw_c_type_text(): | |
| 333 return "JSONArray" | |
| 334 | |
| 335 @staticmethod | |
| 336 def get_raw_type_model(): | |
| 337 return TypeModel.Array | |
| 338 | |
| 339 | |
| 340 class CommandReturnPassModel: | |
| 341 class ByReference: | |
| 342 def __init__(self, var_type, set_condition): | |
| 343 self.var_type = var_type | |
| 344 self.set_condition = set_condition | |
| 345 | |
| 346 def get_return_var_type(self): | |
| 347 return self.var_type | |
| 348 | |
| 349 @staticmethod | |
| 350 def get_output_argument_prefix(): | |
| 351 return "" | |
| 352 | |
| 353 @staticmethod | |
| 354 def get_output_to_raw_expression(): | |
| 355 return "%s" | |
| 356 | |
| 357 def get_output_parameter_type(self): | |
| 358 return self.var_type + "&" | |
| 359 | |
| 360 def get_set_return_condition(self): | |
| 361 return self.set_condition | |
| 362 | |
| 363 class ByPointer: | |
| 364 def __init__(self, var_type): | |
| 365 self.var_type = var_type | |
| 366 | |
| 367 def get_return_var_type(self): | |
| 368 return self.var_type | |
| 369 | |
| 370 @staticmethod | |
| 371 def get_output_argument_prefix(): | |
| 372 return "&" | |
| 373 | |
| 374 @staticmethod | |
| 375 def get_output_to_raw_expression(): | |
| 376 return "%s" | |
| 377 | |
| 378 def get_output_parameter_type(self): | |
| 379 return self.var_type + "*" | |
| 380 | |
| 381 @staticmethod | |
| 382 def get_set_return_condition(): | |
| 383 return None | |
| 384 | |
| 385 class OptOutput: | |
| 386 def __init__(self, var_type): | |
| 387 self.var_type = var_type | |
| 388 | |
| 389 def get_return_var_type(self): | |
| 390 return "TypeBuilder::OptOutput<%s>" % self.var_type | |
| 391 | |
| 392 @staticmethod | |
| 393 def get_output_argument_prefix(): | |
| 394 return "&" | |
| 395 | |
| 396 @staticmethod | |
| 397 def get_output_to_raw_expression(): | |
| 398 return "%s.getValue()" | |
| 399 | |
| 400 def get_output_parameter_type(self): | |
| 401 return "TypeBuilder::OptOutput<%s>*" % self.var_type | |
| 402 | |
| 403 @staticmethod | |
| 404 def get_set_return_condition(): | |
| 405 return "%s.isAssigned()" | |
| 406 | |
| 407 | |
| 408 class TypeModel: | |
| 409 class RefPtrBased(object): | |
| 410 def __init__(self, class_name): | |
| 411 self.class_name = class_name | |
| 412 self.optional = False | |
| 413 | |
| 414 def get_optional(self): | |
| 415 result = TypeModel.RefPtrBased(self.class_name) | |
| 416 result.optional = True | |
| 417 return result | |
| 418 | |
| 419 def get_command_return_pass_model(self): | |
| 420 if self.optional: | |
| 421 set_condition = "%s" | |
| 422 else: | |
| 423 set_condition = None | |
| 424 return CommandReturnPassModel.ByReference("RefPtr<%s>" % self.class_ name, set_condition) | |
| 425 | |
| 426 def get_input_param_type_text(self): | |
| 427 return "PassRefPtr<%s>" % self.class_name | |
| 428 | |
| 429 @staticmethod | |
| 430 def get_event_setter_expression_pattern(): | |
| 431 return "%s" | |
| 432 | |
| 433 class Enum(object): | |
| 434 def __init__(self, base_type_name): | |
| 435 self.type_name = base_type_name + "::Enum" | |
| 436 | |
| 437 def get_optional(base_self): | |
| 438 class EnumOptional: | |
| 439 @classmethod | |
| 440 def get_optional(cls): | |
| 441 return cls | |
| 442 | |
| 443 @staticmethod | |
| 444 def get_command_return_pass_model(): | |
| 445 return CommandReturnPassModel.OptOutput(base_self.type_name) | |
| 446 | |
| 447 @staticmethod | |
| 448 def get_input_param_type_text(): | |
| 449 return base_self.type_name + "*" | |
| 450 | |
| 451 @staticmethod | |
| 452 def get_event_setter_expression_pattern(): | |
| 453 raise Exception("TODO") | |
| 454 return EnumOptional | |
| 455 | |
| 456 def get_command_return_pass_model(self): | |
| 457 return CommandReturnPassModel.ByPointer(self.type_name) | |
| 458 | |
| 459 def get_input_param_type_text(self): | |
| 460 return self.type_name | |
| 461 | |
| 462 @staticmethod | |
| 463 def get_event_setter_expression_pattern(): | |
| 464 return "%s" | |
| 465 | |
| 466 class ValueType(object): | |
| 467 def __init__(self, type_name, is_heavy): | |
| 468 self.type_name = type_name | |
| 469 self.is_heavy = is_heavy | |
| 470 | |
| 471 def get_optional(self): | |
| 472 return self.ValueOptional(self) | |
| 473 | |
| 474 def get_command_return_pass_model(self): | |
| 475 return CommandReturnPassModel.ByPointer(self.type_name) | |
| 476 | |
| 477 def get_input_param_type_text(self): | |
| 478 if self.is_heavy: | |
| 479 return "const %s&" % self.type_name | |
| 480 else: | |
| 481 return self.type_name | |
| 482 | |
| 483 def get_opt_output_type_(self): | |
| 484 return self.type_name | |
| 485 | |
| 486 @staticmethod | |
| 487 def get_event_setter_expression_pattern(): | |
| 488 return "%s" | |
| 489 | |
| 490 class ValueOptional: | |
| 491 def __init__(self, base): | |
| 492 self.base = base | |
| 493 | |
| 494 def get_optional(self): | |
| 495 return self | |
| 496 | |
| 497 def get_command_return_pass_model(self): | |
| 498 return CommandReturnPassModel.OptOutput(self.base.get_opt_output _type_()) | |
| 499 | |
| 500 def get_input_param_type_text(self): | |
| 501 return "const %s* const" % self.base.type_name | |
| 502 | |
| 503 @staticmethod | |
| 504 def get_event_setter_expression_pattern(): | |
| 505 return "*%s" | |
| 506 | |
| 507 @classmethod | |
| 508 def init_class(cls): | |
| 509 cls.Bool = cls.ValueType("bool", False) | |
| 510 cls.Int = cls.ValueType("int", False) | |
| 511 cls.Number = cls.ValueType("double", False) | |
| 512 cls.String = cls.ValueType("String", True,) | |
| 513 cls.Object = cls.RefPtrBased("JSONObject") | |
| 514 cls.Array = cls.RefPtrBased("JSONArray") | |
| 515 cls.Any = cls.RefPtrBased("JSONValue") | |
| 516 | |
| 517 TypeModel.init_class() | |
| 518 | |
| 519 | |
| 520 # Collection of JSONObject class methods that are likely to be overloaded in gen erated class. | |
| 521 # We must explicitly import all overloaded methods or they won't be available to user. | |
| 522 INSPECTOR_OBJECT_SETTER_NAMES = frozenset(["setValue", "setBoolean", "setNumber" , "setString", "setValue", "setObject", "setArray"]) | |
| 523 | |
| 524 | |
| 525 def fix_type_name(json_name): | |
| 526 if json_name in TYPE_NAME_FIX_MAP: | |
| 527 fixed = TYPE_NAME_FIX_MAP[json_name] | |
| 528 | |
| 529 class Result(object): | |
| 530 class_name = fixed | |
| 531 | |
| 532 @staticmethod | |
| 533 def output_comment(writer): | |
| 534 writer.newline("// Type originally was named '%s'.\n" % json_nam e) | |
| 535 else: | |
| 536 | |
| 537 class Result(object): | |
| 538 class_name = json_name | |
| 539 | |
| 540 @staticmethod | |
| 541 def output_comment(writer): | |
| 542 pass | |
| 543 | |
| 544 return Result | |
| 545 | |
| 546 | |
| 547 class Writer: | |
| 548 def __init__(self, output, indent): | |
| 549 self.output = output | |
| 550 self.indent = indent | |
| 551 | |
| 552 def newline(self, str): | |
| 553 if (self.indent): | |
| 554 self.output.append(self.indent) | |
| 555 self.output.append(str) | |
| 556 | |
| 557 def append(self, str): | |
| 558 self.output.append(str) | |
| 559 | |
| 560 def newline_multiline(self, str): | |
| 561 parts = str.split('\n') | |
| 562 self.newline(parts[0]) | |
| 563 for p in parts[1:]: | |
| 564 self.output.append('\n') | |
| 565 if p: | |
| 566 self.newline(p) | |
| 567 | |
| 568 def append_multiline(self, str): | |
| 569 parts = str.split('\n') | |
| 570 self.append(parts[0]) | |
| 571 for p in parts[1:]: | |
| 572 self.output.append('\n') | |
| 573 if p: | |
| 574 self.newline(p) | |
| 575 | |
| 576 def get_indent(self): | |
| 577 return self.indent | |
| 578 | |
| 579 def insert_writer(self, additional_indent): | |
| 580 new_output = [] | |
| 581 self.output.append(new_output) | |
| 582 return Writer(new_output, self.indent + additional_indent) | |
| 583 | |
| 584 | |
| 585 class EnumConstants: | |
| 586 map_ = {} | |
| 587 constants_ = [] | |
| 588 | |
| 589 @classmethod | |
| 590 def add_constant(cls, value): | |
| 591 if value in cls.map_: | |
| 592 return cls.map_[value] | |
| 593 else: | |
| 594 pos = len(cls.map_) | |
| 595 cls.map_[value] = pos | |
| 596 cls.constants_.append(value) | |
| 597 return pos | |
| 598 | |
| 599 @classmethod | |
| 600 def get_enum_constant_code(cls): | |
| 601 output = [] | |
| 602 for item in cls.constants_: | |
| 603 output.append(" \"" + item + "\"") | |
| 604 return ",\n".join(output) + "\n" | |
| 605 | |
| 606 | |
| 607 # Typebuilder code is generated in several passes: first typedefs, then other cl asses. | |
| 608 # Manual pass management is needed because we cannot have forward declarations f or typedefs. | |
| 609 class TypeBuilderPass: | |
| 610 TYPEDEF = "typedef" | |
| 611 MAIN = "main" | |
| 612 | |
| 613 | |
| 614 class TypeBindings: | |
| 615 @staticmethod | |
| 616 def create_named_type_declaration(json_typable, context_domain_name, type_da ta): | |
| 617 json_type = type_data.get_json_type() | |
| 618 | |
| 619 class Helper: | |
| 620 is_ad_hoc = False | |
| 621 full_name_prefix_for_use = "TypeBuilder::" + context_domain_name + " ::" | |
| 622 full_name_prefix_for_impl = "TypeBuilder::" + context_domain_name + "::" | |
| 623 | |
| 624 @staticmethod | |
| 625 def write_doc(writer): | |
| 626 if "description" in json_type: | |
| 627 writer.newline("/* ") | |
| 628 writer.append(json_type["description"]) | |
| 629 writer.append(" */\n") | |
| 630 | |
| 631 @staticmethod | |
| 632 def add_to_forward_listener(forward_listener): | |
| 633 forward_listener.add_type_data(type_data) | |
| 634 | |
| 635 | |
| 636 fixed_type_name = fix_type_name(json_type["id"]) | |
| 637 return TypeBindings.create_type_declaration_(json_typable, context_domai n_name, fixed_type_name, Helper) | |
| 638 | |
| 639 @staticmethod | |
| 640 def create_ad_hoc_type_declaration(json_typable, context_domain_name, ad_hoc _type_context): | |
| 641 class Helper: | |
| 642 is_ad_hoc = True | |
| 643 full_name_prefix_for_use = ad_hoc_type_context.container_relative_na me_prefix | |
| 644 full_name_prefix_for_impl = ad_hoc_type_context.container_full_name_ prefix | |
| 645 | |
| 646 @staticmethod | |
| 647 def write_doc(writer): | |
| 648 pass | |
| 649 | |
| 650 @staticmethod | |
| 651 def add_to_forward_listener(forward_listener): | |
| 652 pass | |
| 653 fixed_type_name = ad_hoc_type_context.get_type_name_fix() | |
| 654 return TypeBindings.create_type_declaration_(json_typable, context_domai n_name, fixed_type_name, Helper) | |
| 655 | |
| 656 @staticmethod | |
| 657 def create_type_declaration_(json_typable, context_domain_name, fixed_type_n ame, helper): | |
| 658 if json_typable["type"] == "string": | |
| 659 if "enum" in json_typable: | |
| 660 | |
| 661 class EnumBinding: | |
| 662 need_user_runtime_cast_ = False | |
| 663 need_internal_runtime_cast_ = False | |
| 664 | |
| 665 @classmethod | |
| 666 def resolve_inner(cls, resolve_context): | |
| 667 pass | |
| 668 | |
| 669 @classmethod | |
| 670 def request_user_runtime_cast(cls, request): | |
| 671 if request: | |
| 672 cls.need_user_runtime_cast_ = True | |
| 673 request.acknowledge() | |
| 674 | |
| 675 @classmethod | |
| 676 def request_internal_runtime_cast(cls): | |
| 677 cls.need_internal_runtime_cast_ = True | |
| 678 | |
| 679 @classmethod | |
| 680 def get_code_generator(enum_binding_cls): | |
| 681 | |
| 682 class CodeGenerator: | |
| 683 @staticmethod | |
| 684 def generate_type_builder(writer, generate_context): | |
| 685 enum = json_typable["enum"] | |
| 686 helper.write_doc(writer) | |
| 687 enum_name = fixed_type_name.class_name | |
| 688 fixed_type_name.output_comment(writer) | |
| 689 writer.newline("struct ") | |
| 690 writer.append(enum_name) | |
| 691 writer.append(" {\n") | |
| 692 writer.newline(" enum Enum {\n") | |
| 693 for enum_item in enum: | |
| 694 enum_pos = EnumConstants.add_constant(enum_i tem) | |
| 695 | |
| 696 item_c_name = enum_item.replace('-', '_') | |
| 697 item_c_name = Capitalizer.lower_camel_case_t o_upper(item_c_name) | |
| 698 if item_c_name in TYPE_NAME_FIX_MAP: | |
| 699 item_c_name = TYPE_NAME_FIX_MAP[item_c_n ame] | |
| 700 writer.newline(" ") | |
| 701 writer.append(item_c_name) | |
| 702 writer.append(" = ") | |
| 703 writer.append("%s" % enum_pos) | |
| 704 writer.append(",\n") | |
| 705 writer.newline(" };\n") | |
| 706 if enum_binding_cls.need_user_runtime_cast_: | |
| 707 raise Exception("Not yet implemented") | |
| 708 | |
| 709 if enum_binding_cls.need_internal_runtime_cast_: | |
| 710 writer.append("#if %s\n" % VALIDATOR_IFDEF_N AME) | |
| 711 writer.newline(" static void assertCorrec tValue(JSONValue* value);\n") | |
| 712 writer.append("#endif // %s\n" % VALIDATOR_ IFDEF_NAME) | |
| 713 | |
| 714 validator_writer = generate_context.validato r_writer | |
| 715 | |
| 716 validator_writer.newline("void %s%s::assertC orrectValue(JSONValue* value)\n" % (helper.full_name_prefix_for_impl, enum_name) ) | |
| 717 validator_writer.newline("{\n") | |
| 718 validator_writer.newline(" WTF::String s; \n") | |
| 719 validator_writer.newline(" bool cast_res = value->asString(&s);\n") | |
| 720 validator_writer.newline(" ASSERT(cast_re s);\n") | |
| 721 if len(enum) > 0: | |
| 722 condition_list = [] | |
| 723 for enum_item in enum: | |
| 724 enum_pos = EnumConstants.add_constan t(enum_item) | |
| 725 condition_list.append("s == \"%s\"" % enum_item) | |
| 726 validator_writer.newline(" ASSERT(%s) ;\n" % " || ".join(condition_list)) | |
| 727 validator_writer.newline("}\n") | |
| 728 | |
| 729 validator_writer.newline("\n\n") | |
| 730 | |
| 731 writer.newline("}; // struct ") | |
| 732 writer.append(enum_name) | |
| 733 writer.append("\n\n") | |
| 734 | |
| 735 @staticmethod | |
| 736 def register_use(forward_listener): | |
| 737 pass | |
| 738 | |
| 739 @staticmethod | |
| 740 def get_generate_pass_id(): | |
| 741 return TypeBuilderPass.MAIN | |
| 742 | |
| 743 return CodeGenerator | |
| 744 | |
| 745 @classmethod | |
| 746 def get_validator_call_text(cls): | |
| 747 return helper.full_name_prefix_for_use + fixed_type_name .class_name + "::assertCorrectValue" | |
| 748 | |
| 749 @classmethod | |
| 750 def get_array_item_c_type_text(cls): | |
| 751 return helper.full_name_prefix_for_use + fixed_type_name .class_name + "::Enum" | |
| 752 | |
| 753 @staticmethod | |
| 754 def get_setter_value_expression_pattern(): | |
| 755 return "TypeBuilder::getEnumConstantValue(%s)" | |
| 756 | |
| 757 @staticmethod | |
| 758 def reduce_to_raw_type(): | |
| 759 return RawTypes.String | |
| 760 | |
| 761 @staticmethod | |
| 762 def get_type_model(): | |
| 763 return TypeModel.Enum(helper.full_name_prefix_for_use + fixed_type_name.class_name) | |
| 764 | |
| 765 return EnumBinding | |
| 766 else: | |
| 767 if helper.is_ad_hoc: | |
| 768 | |
| 769 class PlainString: | |
| 770 @classmethod | |
| 771 def resolve_inner(cls, resolve_context): | |
| 772 pass | |
| 773 | |
| 774 @staticmethod | |
| 775 def request_user_runtime_cast(request): | |
| 776 raise Exception("Unsupported") | |
| 777 | |
| 778 @staticmethod | |
| 779 def request_internal_runtime_cast(): | |
| 780 pass | |
| 781 | |
| 782 @staticmethod | |
| 783 def get_code_generator(): | |
| 784 return None | |
| 785 | |
| 786 @classmethod | |
| 787 def get_validator_call_text(cls): | |
| 788 return RawTypes.String.get_raw_validator_call_text() | |
| 789 | |
| 790 @staticmethod | |
| 791 def reduce_to_raw_type(): | |
| 792 return RawTypes.String | |
| 793 | |
| 794 @staticmethod | |
| 795 def get_type_model(): | |
| 796 return TypeModel.String | |
| 797 | |
| 798 @staticmethod | |
| 799 def get_setter_value_expression_pattern(): | |
| 800 return None | |
| 801 | |
| 802 @classmethod | |
| 803 def get_array_item_c_type_text(cls): | |
| 804 return cls.reduce_to_raw_type().get_array_item_raw_c _type_text() | |
| 805 | |
| 806 return PlainString | |
| 807 | |
| 808 else: | |
| 809 | |
| 810 class TypedefString: | |
| 811 @classmethod | |
| 812 def resolve_inner(cls, resolve_context): | |
| 813 pass | |
| 814 | |
| 815 @staticmethod | |
| 816 def request_user_runtime_cast(request): | |
| 817 raise Exception("Unsupported") | |
| 818 | |
| 819 @staticmethod | |
| 820 def request_internal_runtime_cast(): | |
| 821 pass | |
| 822 | |
| 823 @staticmethod | |
| 824 def get_code_generator(): | |
| 825 class CodeGenerator: | |
| 826 @staticmethod | |
| 827 def generate_type_builder(writer, generate_conte xt): | |
| 828 helper.write_doc(writer) | |
| 829 fixed_type_name.output_comment(writer) | |
| 830 writer.newline("typedef String ") | |
| 831 writer.append(fixed_type_name.class_name) | |
| 832 writer.append(";\n\n") | |
| 833 | |
| 834 @staticmethod | |
| 835 def register_use(forward_listener): | |
| 836 pass | |
| 837 | |
| 838 @staticmethod | |
| 839 def get_generate_pass_id(): | |
| 840 return TypeBuilderPass.TYPEDEF | |
| 841 | |
| 842 return CodeGenerator | |
| 843 | |
| 844 @classmethod | |
| 845 def get_validator_call_text(cls): | |
| 846 return RawTypes.String.get_raw_validator_call_text() | |
| 847 | |
| 848 @staticmethod | |
| 849 def reduce_to_raw_type(): | |
| 850 return RawTypes.String | |
| 851 | |
| 852 @staticmethod | |
| 853 def get_type_model(): | |
| 854 return TypeModel.ValueType("%s%s" % (helper.full_nam e_prefix_for_use, fixed_type_name.class_name), True) | |
| 855 | |
| 856 @staticmethod | |
| 857 def get_setter_value_expression_pattern(): | |
| 858 return None | |
| 859 | |
| 860 @classmethod | |
| 861 def get_array_item_c_type_text(cls): | |
| 862 return "%s%s" % (helper.full_name_prefix_for_use, fi xed_type_name.class_name) | |
| 863 | |
| 864 return TypedefString | |
| 865 | |
| 866 elif json_typable["type"] == "object": | |
| 867 if "properties" in json_typable: | |
| 868 | |
| 869 class ClassBinding: | |
| 870 resolve_data_ = None | |
| 871 need_user_runtime_cast_ = False | |
| 872 need_internal_runtime_cast_ = False | |
| 873 | |
| 874 @classmethod | |
| 875 def resolve_inner(cls, resolve_context): | |
| 876 if cls.resolve_data_: | |
| 877 return | |
| 878 | |
| 879 properties = json_typable["properties"] | |
| 880 main = [] | |
| 881 optional = [] | |
| 882 | |
| 883 ad_hoc_type_list = [] | |
| 884 | |
| 885 for prop in properties: | |
| 886 prop_name = prop["name"] | |
| 887 ad_hoc_type_context = cls.AdHocTypeContextImpl(prop_ name, fixed_type_name.class_name, resolve_context, ad_hoc_type_list, helper.full _name_prefix_for_impl) | |
| 888 binding = resolve_param_type(prop, context_domain_na me, ad_hoc_type_context) | |
| 889 | |
| 890 code_generator = binding.get_code_generator() | |
| 891 if code_generator: | |
| 892 code_generator.register_use(resolve_context.forw ard_listener) | |
| 893 | |
| 894 class PropertyData: | |
| 895 param_type_binding = binding | |
| 896 p = prop | |
| 897 | |
| 898 if prop.get("optional"): | |
| 899 optional.append(PropertyData) | |
| 900 else: | |
| 901 main.append(PropertyData) | |
| 902 | |
| 903 class ResolveData: | |
| 904 main_properties = main | |
| 905 optional_properties = optional | |
| 906 ad_hoc_types = ad_hoc_type_list | |
| 907 | |
| 908 cls.resolve_data_ = ResolveData | |
| 909 | |
| 910 for ad_hoc in ad_hoc_type_list: | |
| 911 ad_hoc.resolve_inner(resolve_context) | |
| 912 | |
| 913 @classmethod | |
| 914 def request_user_runtime_cast(cls, request): | |
| 915 if not request: | |
| 916 return | |
| 917 cls.need_user_runtime_cast_ = True | |
| 918 request.acknowledge() | |
| 919 cls.request_internal_runtime_cast() | |
| 920 | |
| 921 @classmethod | |
| 922 def request_internal_runtime_cast(cls): | |
| 923 if cls.need_internal_runtime_cast_: | |
| 924 return | |
| 925 cls.need_internal_runtime_cast_ = True | |
| 926 for p in cls.resolve_data_.main_properties: | |
| 927 p.param_type_binding.request_internal_runtime_cast() | |
| 928 for p in cls.resolve_data_.optional_properties: | |
| 929 p.param_type_binding.request_internal_runtime_cast() | |
| 930 | |
| 931 @classmethod | |
| 932 def get_code_generator(class_binding_cls): | |
| 933 class CodeGenerator: | |
| 934 @classmethod | |
| 935 def generate_type_builder(cls, writer, generate_cont ext): | |
| 936 resolve_data = class_binding_cls.resolve_data_ | |
| 937 helper.write_doc(writer) | |
| 938 class_name = fixed_type_name.class_name | |
| 939 | |
| 940 fixed_type_name.output_comment(writer) | |
| 941 writer.newline("class PLATFORM_EXPORT %s : publi c JSONObjectBase {\n" % class_name) | |
| 942 writer.newline("public:\n") | |
| 943 ad_hoc_type_writer = writer.insert_writer(" " ) | |
| 944 | |
| 945 for ad_hoc_type in resolve_data.ad_hoc_types: | |
| 946 code_generator = ad_hoc_type.get_code_genera tor() | |
| 947 if code_generator: | |
| 948 code_generator.generate_type_builder(ad_ hoc_type_writer, generate_context) | |
| 949 | |
| 950 writer.newline_multiline( | |
| 951 """ enum { | |
| 952 NoFieldsSet = 0, | |
| 953 """) | |
| 954 | |
| 955 state_enum_items = [] | |
| 956 if len(resolve_data.main_properties) > 0: | |
| 957 pos = 0 | |
| 958 for prop_data in resolve_data.main_propertie s: | |
| 959 item_name = Capitalizer.lower_camel_case _to_upper(prop_data.p["name"]) + "Set" | |
| 960 state_enum_items.append(item_name) | |
| 961 writer.newline(" %s = 1 << %s,\n" % (item_name, pos)) | |
| 962 pos += 1 | |
| 963 all_fields_set_value = "(" + (" | ".join(sta te_enum_items)) + ")" | |
| 964 else: | |
| 965 all_fields_set_value = "0" | |
| 966 | |
| 967 writer.newline_multiline(CodeGeneratorStrings.cl ass_binding_builder_part_1 | |
| 968 % (all_fields_set_value , class_name, class_name)) | |
| 969 | |
| 970 pos = 0 | |
| 971 for prop_data in resolve_data.main_properties: | |
| 972 prop_name = prop_data.p["name"] | |
| 973 | |
| 974 param_type_binding = prop_data.param_type_bi nding | |
| 975 param_raw_type = param_type_binding.reduce_t o_raw_type() | |
| 976 | |
| 977 writer.newline_multiline(CodeGeneratorString s.class_binding_builder_part_2 | |
| 978 % (state_enum_items[pos], | |
| 979 Capitalizer.lower_camel_case_to_upper (prop_name), | |
| 980 param_type_binding.get_type_model().g et_input_param_type_text(), | |
| 981 state_enum_items[pos], prop_name, | |
| 982 param_raw_type.get_setter_name(), pro p_name, | |
| 983 format_setter_value_expression(param_ type_binding, "value"), | |
| 984 state_enum_items[pos])) | |
| 985 | |
| 986 pos += 1 | |
| 987 | |
| 988 writer.newline_multiline(CodeGeneratorStrings.cl ass_binding_builder_part_3 | |
| 989 % (class_name, class_na me, class_name, class_name, class_name, class_name)) | |
| 990 | |
| 991 writer.newline(" /*\n") | |
| 992 writer.newline(" * Synthetic constructor:\n" ) | |
| 993 writer.newline(" * RefPtr<%s> result = %s::c reate()" % (class_name, class_name)) | |
| 994 for prop_data in resolve_data.main_properties: | |
| 995 writer.append_multiline("\n * .set%s (...)" % Capitalizer.lower_camel_case_to_upper(prop_data.p["name"])) | |
| 996 writer.append_multiline(";\n */\n") | |
| 997 | |
| 998 writer.newline_multiline(CodeGeneratorStrings.cl ass_binding_builder_part_4) | |
| 999 | |
| 1000 writer.newline(" typedef TypeBuilder::StructI temTraits ItemTraits;\n") | |
| 1001 | |
| 1002 for prop_data in resolve_data.main_properties: | |
| 1003 prop_name = prop_data.p["name"] | |
| 1004 param_type_binding = prop_data.param_type_bi nding | |
| 1005 if isinstance(param_type_binding.get_type_mo del(), TypeModel.ValueType): | |
| 1006 writer.append_multiline("\n void %s" % prop_name) | |
| 1007 writer.append("(%s value)\n" % param_typ e_binding.get_type_model().get_command_return_pass_model().get_output_parameter_ type()) | |
| 1008 writer.newline(" {\n") | |
| 1009 writer.newline(" JSONObjectBase:: get%s(\"%s\", value);\n" | |
| 1010 % (param_type_binding.reduce_to_raw_ type().get_setter_name(), prop_data.p["name"])) | |
| 1011 writer.newline(" }\n") | |
| 1012 | |
| 1013 for prop_data in resolve_data.optional_propertie s: | |
| 1014 prop_name = prop_data.p["name"] | |
| 1015 param_type_binding = prop_data.param_type_bi nding | |
| 1016 setter_name = "set%s" % Capitalizer.lower_ca mel_case_to_upper(prop_name) | |
| 1017 | |
| 1018 writer.append_multiline("\n void %s" % se tter_name) | |
| 1019 writer.append("(%s value)\n" % param_type_bi nding.get_type_model().get_input_param_type_text()) | |
| 1020 writer.newline(" {\n") | |
| 1021 writer.newline(" this->set%s(\"%s\", %s);\n" | |
| 1022 % (param_type_binding.reduce_to_raw_type ().get_setter_name(), prop_data.p["name"], | |
| 1023 format_setter_value_expression(param_ type_binding, "value"))) | |
| 1024 writer.newline(" }\n") | |
| 1025 | |
| 1026 if setter_name in INSPECTOR_OBJECT_SETTER_NA MES: | |
| 1027 writer.newline(" using JSONObjectBase ::%s;\n\n" % setter_name) | |
| 1028 | |
| 1029 if class_binding_cls.need_user_runtime_cast_: | |
| 1030 writer.newline(" static PassRefPtr<%s> ru ntimeCast(PassRefPtr<JSONValue> value)\n" % class_name) | |
| 1031 writer.newline(" {\n") | |
| 1032 writer.newline(" RefPtr<JSONObject> o bject;\n") | |
| 1033 writer.newline(" bool castRes = value ->asObject(&object);\n") | |
| 1034 writer.newline(" ASSERT_UNUSED(castRe s, castRes);\n") | |
| 1035 writer.append("#if %s\n" % VALIDATOR_IFDEF_N AME) | |
| 1036 writer.newline(" assertCorrectValue(o bject.get());\n") | |
| 1037 writer.append("#endif // %s\n" % VALIDATOR_ IFDEF_NAME) | |
| 1038 writer.newline(" static_assert(sizeof (%s) == sizeof(JSONObjectBase), \"%s should be the same size as JSONObjectBase\" );\n" % (class_name, class_name)) | |
| 1039 writer.newline(" return static_cast<% s*>(static_cast<JSONObjectBase*>(object.get()));\n" % class_name) | |
| 1040 writer.newline(" }\n") | |
| 1041 writer.append("\n") | |
| 1042 | |
| 1043 if class_binding_cls.need_internal_runtime_cast_ : | |
| 1044 writer.append("#if %s\n" % VALIDATOR_IFDEF_N AME) | |
| 1045 writer.newline(" static void assertCorrec tValue(JSONValue* value);\n") | |
| 1046 writer.append("#endif // %s\n" % VALIDATOR_ IFDEF_NAME) | |
| 1047 | |
| 1048 validator_writer = generate_context.validato r_writer | |
| 1049 | |
| 1050 validator_writer.newline("void %s%s::assertC orrectValue(JSONValue* value)\n" % (helper.full_name_prefix_for_impl, class_name )) | |
| 1051 validator_writer.newline("{\n") | |
| 1052 validator_writer.newline(" RefPtr<JSONObj ect> object;\n") | |
| 1053 validator_writer.newline(" bool castRes = value->asObject(&object);\n") | |
| 1054 validator_writer.newline(" ASSERT_UNUSED( castRes, castRes);\n") | |
| 1055 for prop_data in resolve_data.main_propertie s: | |
| 1056 validator_writer.newline(" {\n") | |
| 1057 it_name = "%sPos" % prop_data.p["name"] | |
| 1058 validator_writer.newline(" JSONOb ject::iterator %s;\n" % it_name) | |
| 1059 validator_writer.newline(" %s = o bject->find(\"%s\");\n" % (it_name, prop_data.p["name"])) | |
| 1060 validator_writer.newline(" ASSERT (%s != object->end());\n" % it_name) | |
| 1061 validator_writer.newline(" %s(%s- >value.get());\n" % (prop_data.param_type_binding.get_validator_call_text(), it_ name)) | |
| 1062 validator_writer.newline(" }\n") | |
| 1063 | |
| 1064 validator_writer.newline(" int foundPrope rtiesCount = %s;\n" % len(resolve_data.main_properties)) | |
| 1065 | |
| 1066 for prop_data in resolve_data.optional_prope rties: | |
| 1067 validator_writer.newline(" {\n") | |
| 1068 it_name = "%sPos" % prop_data.p["name"] | |
| 1069 validator_writer.newline(" JSONOb ject::iterator %s;\n" % it_name) | |
| 1070 validator_writer.newline(" %s = o bject->find(\"%s\");\n" % (it_name, prop_data.p["name"])) | |
| 1071 validator_writer.newline(" if (%s != object->end()) {\n" % it_name) | |
| 1072 validator_writer.newline(" %s (%s->value.get());\n" % (prop_data.param_type_binding.get_validator_call_text(), it_name)) | |
| 1073 validator_writer.newline(" ++ foundPropertiesCount;\n") | |
| 1074 validator_writer.newline(" }\n") | |
| 1075 validator_writer.newline(" }\n") | |
| 1076 | |
| 1077 validator_writer.newline(" if (foundPrope rtiesCount != object->size()) {\n") | |
| 1078 validator_writer.newline(" FATAL(\"Unex pected properties in object: %s\\n\", object->toJSONString().ascii().data());\n" ) | |
| 1079 validator_writer.newline(" }\n") | |
| 1080 validator_writer.newline("}\n") | |
| 1081 | |
| 1082 validator_writer.newline("\n\n") | |
| 1083 | |
| 1084 writer.newline("};\n\n") | |
| 1085 | |
| 1086 @staticmethod | |
| 1087 def generate_forward_declaration(writer): | |
| 1088 class_name = fixed_type_name.class_name | |
| 1089 writer.newline("class ") | |
| 1090 writer.append(class_name) | |
| 1091 writer.append(";\n") | |
| 1092 | |
| 1093 @staticmethod | |
| 1094 def register_use(forward_listener): | |
| 1095 helper.add_to_forward_listener(forward_listener) | |
| 1096 | |
| 1097 @staticmethod | |
| 1098 def get_generate_pass_id(): | |
| 1099 return TypeBuilderPass.MAIN | |
| 1100 | |
| 1101 return CodeGenerator | |
| 1102 | |
| 1103 @staticmethod | |
| 1104 def get_validator_call_text(): | |
| 1105 return helper.full_name_prefix_for_use + fixed_type_name .class_name + "::assertCorrectValue" | |
| 1106 | |
| 1107 @classmethod | |
| 1108 def get_array_item_c_type_text(cls): | |
| 1109 return helper.full_name_prefix_for_use + fixed_type_name .class_name | |
| 1110 | |
| 1111 @staticmethod | |
| 1112 def get_setter_value_expression_pattern(): | |
| 1113 return "static_pointer_cast<JSONValue>(%s)" | |
| 1114 | |
| 1115 @staticmethod | |
| 1116 def reduce_to_raw_type(): | |
| 1117 return RawTypes.Object | |
| 1118 | |
| 1119 @staticmethod | |
| 1120 def get_type_model(): | |
| 1121 return TypeModel.RefPtrBased(helper.full_name_prefix_for _use + fixed_type_name.class_name) | |
| 1122 | |
| 1123 class AdHocTypeContextImpl: | |
| 1124 def __init__(self, property_name, class_name, resolve_co ntext, ad_hoc_type_list, parent_full_name_prefix): | |
| 1125 self.property_name = property_name | |
| 1126 self.class_name = class_name | |
| 1127 self.resolve_context = resolve_context | |
| 1128 self.ad_hoc_type_list = ad_hoc_type_list | |
| 1129 self.container_full_name_prefix = parent_full_name_p refix + class_name + "::" | |
| 1130 self.container_relative_name_prefix = "" | |
| 1131 | |
| 1132 def get_type_name_fix(self): | |
| 1133 class NameFix: | |
| 1134 class_name = Capitalizer.lower_camel_case_to_upp er(self.property_name) | |
| 1135 | |
| 1136 @staticmethod | |
| 1137 def output_comment(writer): | |
| 1138 writer.newline("// Named after property name '%s' while generating %s.\n" % (self.property_name, self.class_name)) | |
| 1139 | |
| 1140 return NameFix | |
| 1141 | |
| 1142 def add_type(self, binding): | |
| 1143 self.ad_hoc_type_list.append(binding) | |
| 1144 | |
| 1145 return ClassBinding | |
| 1146 else: | |
| 1147 | |
| 1148 class PlainObjectBinding: | |
| 1149 @classmethod | |
| 1150 def resolve_inner(cls, resolve_context): | |
| 1151 pass | |
| 1152 | |
| 1153 @staticmethod | |
| 1154 def request_user_runtime_cast(request): | |
| 1155 pass | |
| 1156 | |
| 1157 @staticmethod | |
| 1158 def request_internal_runtime_cast(): | |
| 1159 pass | |
| 1160 | |
| 1161 @staticmethod | |
| 1162 def get_code_generator(): | |
| 1163 pass | |
| 1164 | |
| 1165 @staticmethod | |
| 1166 def get_validator_call_text(): | |
| 1167 return "RuntimeCastHelper::assertType<JSONValue::TypeObj ect>" | |
| 1168 | |
| 1169 @classmethod | |
| 1170 def get_array_item_c_type_text(cls): | |
| 1171 return cls.reduce_to_raw_type().get_array_item_raw_c_typ e_text() | |
| 1172 | |
| 1173 @staticmethod | |
| 1174 def get_setter_value_expression_pattern(): | |
| 1175 return None | |
| 1176 | |
| 1177 @staticmethod | |
| 1178 def reduce_to_raw_type(): | |
| 1179 return RawTypes.Object | |
| 1180 | |
| 1181 @staticmethod | |
| 1182 def get_type_model(): | |
| 1183 return TypeModel.Object | |
| 1184 | |
| 1185 return PlainObjectBinding | |
| 1186 elif json_typable["type"] == "array": | |
| 1187 if "items" in json_typable: | |
| 1188 | |
| 1189 ad_hoc_types = [] | |
| 1190 | |
| 1191 class AdHocTypeContext: | |
| 1192 container_full_name_prefix = "<not yet defined>" | |
| 1193 container_relative_name_prefix = "" | |
| 1194 | |
| 1195 @staticmethod | |
| 1196 def get_type_name_fix(): | |
| 1197 return fixed_type_name | |
| 1198 | |
| 1199 @staticmethod | |
| 1200 def add_type(binding): | |
| 1201 ad_hoc_types.append(binding) | |
| 1202 | |
| 1203 item_binding = resolve_param_type(json_typable["items"], context _domain_name, AdHocTypeContext) | |
| 1204 | |
| 1205 class ArrayBinding: | |
| 1206 resolve_data_ = None | |
| 1207 need_internal_runtime_cast_ = False | |
| 1208 | |
| 1209 @classmethod | |
| 1210 def resolve_inner(cls, resolve_context): | |
| 1211 if cls.resolve_data_: | |
| 1212 return | |
| 1213 | |
| 1214 class ResolveData: | |
| 1215 item_type_binding = item_binding | |
| 1216 ad_hoc_type_list = ad_hoc_types | |
| 1217 | |
| 1218 cls.resolve_data_ = ResolveData | |
| 1219 | |
| 1220 for t in ad_hoc_types: | |
| 1221 t.resolve_inner(resolve_context) | |
| 1222 | |
| 1223 @classmethod | |
| 1224 def request_user_runtime_cast(cls, request): | |
| 1225 raise Exception("Not implemented yet") | |
| 1226 | |
| 1227 @classmethod | |
| 1228 def request_internal_runtime_cast(cls): | |
| 1229 if cls.need_internal_runtime_cast_: | |
| 1230 return | |
| 1231 cls.need_internal_runtime_cast_ = True | |
| 1232 cls.resolve_data_.item_type_binding.request_internal_run time_cast() | |
| 1233 | |
| 1234 @classmethod | |
| 1235 def get_code_generator(array_binding_cls): | |
| 1236 | |
| 1237 class CodeGenerator: | |
| 1238 @staticmethod | |
| 1239 def generate_type_builder(writer, generate_context): | |
| 1240 ad_hoc_type_writer = writer | |
| 1241 | |
| 1242 resolve_data = array_binding_cls.resolve_data_ | |
| 1243 | |
| 1244 for ad_hoc_type in resolve_data.ad_hoc_type_list : | |
| 1245 code_generator = ad_hoc_type.get_code_genera tor() | |
| 1246 if code_generator: | |
| 1247 code_generator.generate_type_builder(ad_ hoc_type_writer, generate_context) | |
| 1248 | |
| 1249 @staticmethod | |
| 1250 def generate_forward_declaration(writer): | |
| 1251 pass | |
| 1252 | |
| 1253 @staticmethod | |
| 1254 def register_use(forward_listener): | |
| 1255 item_code_generator = item_binding.get_code_gene rator() | |
| 1256 if item_code_generator: | |
| 1257 item_code_generator.register_use(forward_lis tener) | |
| 1258 | |
| 1259 @staticmethod | |
| 1260 def get_generate_pass_id(): | |
| 1261 return TypeBuilderPass.MAIN | |
| 1262 | |
| 1263 return CodeGenerator | |
| 1264 | |
| 1265 @classmethod | |
| 1266 def get_validator_call_text(cls): | |
| 1267 return cls.get_array_item_c_type_text() + "::assertCorre ctValue" | |
| 1268 | |
| 1269 @classmethod | |
| 1270 def get_array_item_c_type_text(cls): | |
| 1271 return "TypeBuilder::Array<%s>" % cls.resolve_data_.item _type_binding.get_array_item_c_type_text() | |
| 1272 | |
| 1273 @staticmethod | |
| 1274 def get_setter_value_expression_pattern(): | |
| 1275 return None | |
| 1276 | |
| 1277 @staticmethod | |
| 1278 def reduce_to_raw_type(): | |
| 1279 return RawTypes.Array | |
| 1280 | |
| 1281 @classmethod | |
| 1282 def get_type_model(cls): | |
| 1283 return TypeModel.RefPtrBased(cls.get_array_item_c_type_t ext()) | |
| 1284 | |
| 1285 return ArrayBinding | |
| 1286 else: | |
| 1287 # Fall-through to raw type. | |
| 1288 pass | |
| 1289 | |
| 1290 raw_type = RawTypes.get(json_typable["type"]) | |
| 1291 | |
| 1292 return RawTypeBinding(raw_type) | |
| 1293 | |
| 1294 | |
| 1295 class RawTypeBinding: | |
| 1296 def __init__(self, raw_type): | |
| 1297 self.raw_type_ = raw_type | |
| 1298 | |
| 1299 def resolve_inner(self, resolve_context): | |
| 1300 pass | |
| 1301 | |
| 1302 def request_user_runtime_cast(self, request): | |
| 1303 raise Exception("Unsupported") | |
| 1304 | |
| 1305 def request_internal_runtime_cast(self): | |
| 1306 pass | |
| 1307 | |
| 1308 def get_code_generator(self): | |
| 1309 return None | |
| 1310 | |
| 1311 def get_validator_call_text(self): | |
| 1312 return self.raw_type_.get_raw_validator_call_text() | |
| 1313 | |
| 1314 def get_array_item_c_type_text(self): | |
| 1315 return self.raw_type_.get_array_item_raw_c_type_text() | |
| 1316 | |
| 1317 def get_setter_value_expression_pattern(self): | |
| 1318 return None | |
| 1319 | |
| 1320 def reduce_to_raw_type(self): | |
| 1321 return self.raw_type_ | |
| 1322 | |
| 1323 def get_type_model(self): | |
| 1324 return self.raw_type_.get_raw_type_model() | |
| 1325 | |
| 1326 | |
| 1327 class TypeData(object): | |
| 1328 def __init__(self, json_type, json_domain, domain_data): | |
| 1329 self.json_type_ = json_type | |
| 1330 self.json_domain_ = json_domain | |
| 1331 self.domain_data_ = domain_data | |
| 1332 | |
| 1333 if "type" not in json_type: | |
| 1334 raise Exception("Unknown type") | |
| 1335 | |
| 1336 json_type_name = json_type["type"] | |
| 1337 raw_type = RawTypes.get(json_type_name) | |
| 1338 self.raw_type_ = raw_type | |
| 1339 self.binding_being_resolved_ = False | |
| 1340 self.binding_ = None | |
| 1341 | |
| 1342 def get_raw_type(self): | |
| 1343 return self.raw_type_ | |
| 1344 | |
| 1345 def get_binding(self): | |
| 1346 if not self.binding_: | |
| 1347 if self.binding_being_resolved_: | |
| 1348 raise Error("Type %s is already being resolved" % self.json_type _["type"]) | |
| 1349 # Resolve only lazily, because resolving one named type may require resolving some other named type. | |
| 1350 self.binding_being_resolved_ = True | |
| 1351 try: | |
| 1352 self.binding_ = TypeBindings.create_named_type_declaration(self. json_type_, self.json_domain_["domain"], self) | |
| 1353 finally: | |
| 1354 self.binding_being_resolved_ = False | |
| 1355 | |
| 1356 return self.binding_ | |
| 1357 | |
| 1358 def get_json_type(self): | |
| 1359 return self.json_type_ | |
| 1360 | |
| 1361 def get_name(self): | |
| 1362 return self.json_type_["id"] | |
| 1363 | |
| 1364 def get_domain_name(self): | |
| 1365 return self.json_domain_["domain"] | |
| 1366 | |
| 1367 | |
| 1368 class DomainData: | |
| 1369 def __init__(self, json_domain): | |
| 1370 self.json_domain = json_domain | |
| 1371 self.types_ = [] | |
| 1372 | |
| 1373 def add_type(self, type_data): | |
| 1374 self.types_.append(type_data) | |
| 1375 | |
| 1376 def name(self): | |
| 1377 return self.json_domain["domain"] | |
| 1378 | |
| 1379 def types(self): | |
| 1380 return self.types_ | |
| 1381 | |
| 1382 | |
| 1383 class TypeMap: | |
| 1384 def __init__(self, api): | |
| 1385 self.map_ = {} | |
| 1386 self.domains_ = [] | |
| 1387 for json_domain in api["domains"]: | |
| 1388 domain_name = json_domain["domain"] | |
| 1389 | |
| 1390 domain_map = {} | |
| 1391 self.map_[domain_name] = domain_map | |
| 1392 | |
| 1393 domain_data = DomainData(json_domain) | |
| 1394 self.domains_.append(domain_data) | |
| 1395 | |
| 1396 if "types" in json_domain: | |
| 1397 for json_type in json_domain["types"]: | |
| 1398 type_name = json_type["id"] | |
| 1399 type_data = TypeData(json_type, json_domain, domain_data) | |
| 1400 domain_map[type_name] = type_data | |
| 1401 domain_data.add_type(type_data) | |
| 1402 | |
| 1403 def domains(self): | |
| 1404 return self.domains_ | |
| 1405 | |
| 1406 def get(self, domain_name, type_name): | |
| 1407 return self.map_[domain_name][type_name] | |
| 1408 | |
| 1409 | |
| 1410 def resolve_param_type(json_parameter, scope_domain_name, ad_hoc_type_context): | |
| 1411 if "$ref" in json_parameter: | |
| 1412 json_ref = json_parameter["$ref"] | |
| 1413 type_data = get_ref_data(json_ref, scope_domain_name) | |
| 1414 return type_data.get_binding() | |
| 1415 elif "type" in json_parameter: | |
| 1416 result = TypeBindings.create_ad_hoc_type_declaration(json_parameter, sco pe_domain_name, ad_hoc_type_context) | |
| 1417 ad_hoc_type_context.add_type(result) | |
| 1418 return result | |
| 1419 else: | |
| 1420 raise Exception("Unknown type") | |
| 1421 | |
| 1422 def resolve_param_raw_type(json_parameter, scope_domain_name): | |
| 1423 if "$ref" in json_parameter: | |
| 1424 json_ref = json_parameter["$ref"] | |
| 1425 type_data = get_ref_data(json_ref, scope_domain_name) | |
| 1426 return type_data.get_raw_type() | |
| 1427 elif "type" in json_parameter: | |
| 1428 json_type = json_parameter["type"] | |
| 1429 return RawTypes.get(json_type) | |
| 1430 else: | |
| 1431 raise Exception("Unknown type") | |
| 1432 | |
| 1433 | |
| 1434 def get_ref_data(json_ref, scope_domain_name): | |
| 1435 dot_pos = json_ref.find(".") | |
| 1436 if dot_pos == -1: | |
| 1437 domain_name = scope_domain_name | |
| 1438 type_name = json_ref | |
| 1439 else: | |
| 1440 domain_name = json_ref[:dot_pos] | |
| 1441 type_name = json_ref[dot_pos + 1:] | |
| 1442 | |
| 1443 return type_map.get(domain_name, type_name) | |
| 1444 | |
| 1445 | |
| 1446 input_file = open(input_json_filename, "r") | 55 input_file = open(input_json_filename, "r") |
| 1447 json_string = input_file.read() | 56 json_string = input_file.read() |
| 1448 json_api = json.loads(json_string) | 57 json_api = json.loads(json_string) |
| 1449 | 58 |
| 1450 | 59 |
| 1451 class Templates: | 60 def to_title_case(name): |
| 1452 def get_this_script_path_(absolute_path): | 61 return name[:1].upper() + name[1:] |
| 1453 absolute_path = os.path.abspath(absolute_path) | 62 |
| 1454 components = [] | 63 |
| 1455 | 64 def dash_to_camelcase(word): |
| 1456 def fill_recursive(path_part, depth): | 65 return ''.join(to_title_case(x) or '-' for x in word.split('-')) |
| 1457 if depth <= 0 or path_part == '/': | 66 |
| 1458 return | 67 |
| 1459 fill_recursive(os.path.dirname(path_part), depth - 1) | 68 def initialize_jinja_env(cache_dir): |
| 1460 components.append(os.path.basename(path_part)) | 69 jinja_env = jinja2.Environment( |
| 1461 | 70 loader=jinja2.FileSystemLoader(templates_dir), |
| 1462 # Typical path is /Source/platform/inspector_protocol/CodeGenerator.py | 71 # Bytecode cache is not concurrency-safe unless pre-cached: |
| 1463 # Let's take 4 components from the real path then. | 72 # if pre-cached this is read-only, but writing creates a race condition. |
| 1464 fill_recursive(absolute_path, 4) | 73 bytecode_cache=jinja2.FileSystemBytecodeCache(cache_dir), |
| 1465 | 74 keep_trailing_newline=True, # newline-terminate generated files |
| 1466 return "/".join(components) | 75 lstrip_blocks=True, # so can indent control flow tags |
| 1467 | 76 trim_blocks=True) |
| 1468 file_header_ = ("// File is generated by %s\n\n" % get_this_script_path_(sys .argv[0]) + | 77 jinja_env.filters.update({"to_title_case": to_title_case, "dash_to_camelcase ": dash_to_camelcase}) |
| 1469 """// Copyright (c) 2011 The Chromium Authors. All rights reserved. | 78 jinja_env.add_extension('jinja2.ext.loopcontrols') |
| 1470 // Use of this source code is governed by a BSD-style license that can be | 79 return jinja_env |
| 1471 // found in the LICENSE file. | 80 |
| 1472 """) | |
| 1473 | |
| 1474 frontend_domain_class = string.Template(CodeGeneratorStrings.frontend_domain _class) | |
| 1475 backend_method = string.Template(CodeGeneratorStrings.backend_method) | |
| 1476 frontend_method = string.Template(CodeGeneratorStrings.frontend_method) | |
| 1477 callback_main_methods = string.Template(CodeGeneratorStrings.callback_main_m ethods) | |
| 1478 frontend_h = string.Template(file_header_ + CodeGeneratorStrings.frontend_h) | |
| 1479 backend_h = string.Template(file_header_ + CodeGeneratorStrings.backend_h) | |
| 1480 backend_cpp = string.Template(file_header_ + CodeGeneratorStrings.backend_cp p) | |
| 1481 frontend_cpp = string.Template(file_header_ + CodeGeneratorStrings.frontend_ cpp) | |
| 1482 typebuilder_h = string.Template(file_header_ + CodeGeneratorStrings.typebuil der_h) | |
| 1483 typebuilder_cpp = string.Template(file_header_ + CodeGeneratorStrings.typebu ilder_cpp) | |
| 1484 param_container_access_code = CodeGeneratorStrings.param_container_access_co de | |
| 1485 | |
| 1486 | |
| 1487 | |
| 1488 | |
| 1489 | |
| 1490 type_map = TypeMap(json_api) | |
| 1491 | |
| 1492 | |
| 1493 class NeedRuntimeCastRequest: | |
| 1494 def __init__(self): | |
| 1495 self.ack_ = None | |
| 1496 | |
| 1497 def acknowledge(self): | |
| 1498 self.ack_ = True | |
| 1499 | |
| 1500 def is_acknowledged(self): | |
| 1501 return self.ack_ | |
| 1502 | |
| 1503 | |
| 1504 def resolve_all_types(): | |
| 1505 runtime_cast_generate_requests = {} | |
| 1506 for type_name in TYPES_WITH_RUNTIME_CAST_SET: | |
| 1507 runtime_cast_generate_requests[type_name] = NeedRuntimeCastRequest() | |
| 1508 | |
| 1509 class ForwardListener: | |
| 1510 type_data_set = set() | |
| 1511 already_declared_set = set() | |
| 1512 | |
| 1513 @classmethod | |
| 1514 def add_type_data(cls, type_data): | |
| 1515 if type_data not in cls.already_declared_set: | |
| 1516 cls.type_data_set.add(type_data) | |
| 1517 | |
| 1518 class ResolveContext: | |
| 1519 forward_listener = ForwardListener | |
| 1520 | |
| 1521 for domain_data in type_map.domains(): | |
| 1522 for type_data in domain_data.types(): | |
| 1523 # Do not generate forwards for this type any longer. | |
| 1524 ForwardListener.already_declared_set.add(type_data) | |
| 1525 | |
| 1526 binding = type_data.get_binding() | |
| 1527 binding.resolve_inner(ResolveContext) | |
| 1528 | |
| 1529 for domain_data in type_map.domains(): | |
| 1530 for type_data in domain_data.types(): | |
| 1531 full_type_name = "%s.%s" % (type_data.get_domain_name(), type_data.g et_name()) | |
| 1532 request = runtime_cast_generate_requests.pop(full_type_name, None) | |
| 1533 binding = type_data.get_binding() | |
| 1534 if request: | |
| 1535 binding.request_user_runtime_cast(request) | |
| 1536 | |
| 1537 if request and not request.is_acknowledged(): | |
| 1538 raise Exception("Failed to generate runtimeCast in " + full_type _name) | |
| 1539 | |
| 1540 for full_type_name in runtime_cast_generate_requests: | |
| 1541 raise Exception("Failed to generate runtimeCast. Type " + full_type_name + " not found") | |
| 1542 | |
| 1543 return ForwardListener | |
| 1544 | |
| 1545 | |
| 1546 global_forward_listener = resolve_all_types() | |
| 1547 | |
| 1548 | |
| 1549 def get_annotated_type_text(raw_type, annotated_type): | |
| 1550 if annotated_type != raw_type: | |
| 1551 return "/*%s*/ %s" % (annotated_type, raw_type) | |
| 1552 else: | |
| 1553 return raw_type | |
| 1554 | |
| 1555 | |
| 1556 def format_setter_value_expression(param_type_binding, value_ref): | |
| 1557 pattern = param_type_binding.get_setter_value_expression_pattern() | |
| 1558 if pattern: | |
| 1559 return pattern % value_ref | |
| 1560 else: | |
| 1561 return value_ref | |
| 1562 | |
| 1563 class Generator: | |
| 1564 frontend_class_field_lines = [] | |
| 1565 frontend_domain_class_lines = [] | |
| 1566 | |
| 1567 method_name_enum_list = [] | |
| 1568 backend_method_declaration_list = [] | |
| 1569 backend_method_implementation_list = [] | |
| 1570 backend_method_name_declaration_list = [] | |
| 1571 backend_method_name_declaration_index_list = [] | |
| 1572 backend_method_name_declaration_current_index = 0 | |
| 1573 method_handler_list = [] | |
| 1574 frontend_method_list = [] | |
| 1575 | |
| 1576 backend_virtual_setters_list = [] | |
| 1577 backend_agent_interface_list = [] | |
| 1578 backend_setters_list = [] | |
| 1579 backend_constructor_init_list = [] | |
| 1580 backend_field_list = [] | |
| 1581 frontend_constructor_init_list = [] | |
| 1582 type_builder_fragments = [] | |
| 1583 type_builder_forwards = [] | |
| 1584 validator_impl_list = [] | |
| 1585 type_builder_impl_list = [] | |
| 1586 | |
| 1587 | |
| 1588 @staticmethod | |
| 1589 def go(): | |
| 1590 Generator.process_types(type_map) | |
| 1591 | |
| 1592 for json_domain in json_api["domains"]: | |
| 1593 domain_name = json_domain["domain"] | |
| 1594 domain_name_lower = domain_name.lower() | |
| 1595 | |
| 1596 agent_field_name = DomainNameFixes.get_fixed_data(domain_name) | |
| 1597 | |
| 1598 frontend_method_declaration_lines = [] | |
| 1599 | |
| 1600 if "events" in json_domain: | |
| 1601 for json_event in json_domain["events"]: | |
| 1602 Generator.process_event(json_event, domain_name, frontend_me thod_declaration_lines) | |
| 1603 | |
| 1604 Generator.frontend_class_field_lines.append(" %s m_%s;\n" % (doma in_name, domain_name_lower)) | |
| 1605 if Generator.frontend_constructor_init_list: | |
| 1606 Generator.frontend_constructor_init_list.append(" , ") | |
| 1607 Generator.frontend_constructor_init_list.append("m_%s(frontendChanne l)\n" % domain_name_lower) | |
| 1608 Generator.frontend_domain_class_lines.append(Templates.frontend_doma in_class.substitute(None, | |
| 1609 domainClassName=domain_name, | |
| 1610 domainFieldName=domain_name_lower, | |
| 1611 frontendDomainMethodDeclarations="".join(flatten_list(frontend_m ethod_declaration_lines)))) | |
| 1612 | |
| 1613 agent_interface_name = Capitalizer.lower_camel_case_to_upper(domain_ name) + "CommandHandler" | |
| 1614 Generator.backend_agent_interface_list.append(" class PLATFORM_EX PORT %s {\n" % agent_interface_name) | |
| 1615 Generator.backend_agent_interface_list.append(" public:\n") | |
| 1616 if "commands" in json_domain: | |
| 1617 for json_command in json_domain["commands"]: | |
| 1618 Generator.process_command(json_command, domain_name, agent_f ield_name, agent_interface_name) | |
| 1619 Generator.backend_agent_interface_list.append("\n protected:\n") | |
| 1620 Generator.backend_agent_interface_list.append(" virtual ~%s() { }\n" % agent_interface_name) | |
| 1621 Generator.backend_agent_interface_list.append(" };\n\n") | |
| 1622 | |
| 1623 Generator.backend_constructor_init_list.append(" , m_%s(0)" % agent_field_name) | |
| 1624 Generator.backend_virtual_setters_list.append(" virtual void regi sterAgent(%s* %s) = 0;" % (agent_interface_name, agent_field_name)) | |
| 1625 Generator.backend_setters_list.append(" virtual void registerAgen t(%s* %s) { ASSERT(!m_%s); m_%s = %s; }" % (agent_interface_name, agent_field_na me, agent_field_name, agent_field_name, agent_field_name)) | |
| 1626 Generator.backend_field_list.append(" %s* m_%s;" % (agent_interfa ce_name, agent_field_name)) | |
| 1627 | |
| 1628 @staticmethod | |
| 1629 def process_event(json_event, domain_name, frontend_method_declaration_lines ): | |
| 1630 if (("handlers" in json_event) and (not ("renderer" in json_event["handl ers"]))): | |
| 1631 return | |
| 1632 | |
| 1633 event_name = json_event["name"] | |
| 1634 | |
| 1635 ad_hoc_type_output = [] | |
| 1636 frontend_method_declaration_lines.append(ad_hoc_type_output) | |
| 1637 ad_hoc_type_writer = Writer(ad_hoc_type_output, " ") | |
| 1638 | |
| 1639 decl_parameter_list = [] | |
| 1640 | |
| 1641 json_parameters = json_event.get("parameters") | |
| 1642 Generator.generate_send_method(json_parameters, event_name, domain_name, ad_hoc_type_writer, | |
| 1643 decl_parameter_list, | |
| 1644 Generator.EventMethodStructTemplate, | |
| 1645 Generator.frontend_method_list, Templates .frontend_method, {"eventName": event_name}) | |
| 1646 | |
| 1647 frontend_method_declaration_lines.append( | |
| 1648 " void %s(%s);\n" % (event_name, ", ".join(decl_parameter_lis t))) | |
| 1649 | |
| 1650 class EventMethodStructTemplate: | |
| 1651 @staticmethod | |
| 1652 def append_prolog(line_list): | |
| 1653 line_list.append(" RefPtr<JSONObject> paramsObject = JSONObject:: create();\n") | |
| 1654 | |
| 1655 @staticmethod | |
| 1656 def append_epilog(line_list): | |
| 1657 line_list.append(" jsonMessage->setObject(\"params\", paramsObjec t);\n") | |
| 1658 | |
| 1659 container_name = "paramsObject" | |
| 1660 | |
| 1661 @staticmethod | |
| 1662 def process_command(json_command, domain_name, agent_field_name, agent_inter face_name): | |
| 1663 if (("handlers" in json_command) and (not ("renderer" in json_command["h andlers"]))): | |
| 1664 return | |
| 1665 | |
| 1666 json_command_name = json_command["name"] | |
| 1667 | |
| 1668 cmd_enum_name = "k%s_%sCmd" % (domain_name, json_command["name"]) | |
| 1669 | |
| 1670 Generator.method_name_enum_list.append(" %s," % cmd_enum_name) | |
| 1671 Generator.method_handler_list.append(" &DispatcherImpl::%s_%s ," % (domain_name, json_command_name)) | |
| 1672 Generator.backend_method_declaration_list.append(" void %s_%s(int ses sionId, int callId, JSONObject* requestMessageObject, JSONArray* protocolErrors) ;" % (domain_name, json_command_name)) | |
| 1673 | |
| 1674 backend_agent_interface_list = [] if "redirect" in json_command else Gen erator.backend_agent_interface_list | |
| 1675 | |
| 1676 ad_hoc_type_output = [] | |
| 1677 backend_agent_interface_list.append(ad_hoc_type_output) | |
| 1678 ad_hoc_type_writer = Writer(ad_hoc_type_output, " ") | |
| 1679 | |
| 1680 backend_agent_interface_list.append(" virtual void %s(ErrorString *" % json_command_name) | |
| 1681 | |
| 1682 method_in_code = "" | |
| 1683 method_out_code = "" | |
| 1684 agent_call_param_list = ["&error"] | |
| 1685 agent_call_params_declaration_list = [" ErrorString error;"] | |
| 1686 send_response_call_params_list = ["error"] | |
| 1687 request_message_param = "" | |
| 1688 normal_response_cook_text = "" | |
| 1689 | |
| 1690 if "parameters" in json_command: | |
| 1691 json_params = json_command["parameters"] | |
| 1692 request_message_param = " requestMessageObject" | |
| 1693 | |
| 1694 if json_params: | |
| 1695 method_in_code += Templates.param_container_access_code | |
| 1696 | |
| 1697 for json_parameter in json_params: | |
| 1698 json_param_name = json_parameter["name"] | |
| 1699 param_raw_type = resolve_param_raw_type(json_parameter, domain_n ame) | |
| 1700 | |
| 1701 getter_name = param_raw_type.get_getter_name() | |
| 1702 | |
| 1703 optional = json_parameter.get("optional") | |
| 1704 | |
| 1705 non_optional_type_model = param_raw_type.get_raw_type_model() | |
| 1706 | |
| 1707 if optional: | |
| 1708 code = (" bool %s_valueFound = false;\n" | |
| 1709 " %s in_%s = get%s(paramsContainerPtr, \"%s\", &% s_valueFound, protocolErrors);\n" % | |
| 1710 (json_param_name, non_optional_type_model.get_command _return_pass_model().get_return_var_type(), json_param_name, getter_name, json_p aram_name, json_param_name)) | |
| 1711 param = "%s_valueFound ? &in_%s : 0" % (json_param_name, jso n_param_name) | |
| 1712 # FIXME: pass optional refptr-values as PassRefPtr | |
| 1713 formal_param_type_pattern = "const %s*" | |
| 1714 else: | |
| 1715 code = (" %s in_%s = get%s(paramsContainerPtr, \"%s\", 0, protocolErrors);\n" % | |
| 1716 (non_optional_type_model.get_command_return_pass_mod el().get_return_var_type(), json_param_name, getter_name, json_param_name)) | |
| 1717 param = "in_%s" % json_param_name | |
| 1718 # FIXME: pass not-optional refptr-values as NonNullPassRefPt r | |
| 1719 if param_raw_type.is_heavy_value(): | |
| 1720 formal_param_type_pattern = "const %s&" | |
| 1721 else: | |
| 1722 formal_param_type_pattern = "%s" | |
| 1723 | |
| 1724 method_in_code += code | |
| 1725 agent_call_param_list.append(param) | |
| 1726 backend_agent_interface_list.append(", %s in_%s" % (formal_param _type_pattern % non_optional_type_model.get_command_return_pass_model().get_retu rn_var_type(), json_param_name)) | |
| 1727 | |
| 1728 if json_command.get("async") == True: | |
| 1729 callback_name = Capitalizer.lower_camel_case_to_upper(json_command_n ame) + "Callback" | |
| 1730 | |
| 1731 callback_output = [] | |
| 1732 callback_writer = Writer(callback_output, ad_hoc_type_writer.get_ind ent()) | |
| 1733 | |
| 1734 decl_parameter_list = [] | |
| 1735 Generator.generate_send_method(json_command.get("returns"), json_com mand_name, domain_name, ad_hoc_type_writer, | |
| 1736 decl_parameter_list, | |
| 1737 Generator.CallbackMethodStructTemplat e, | |
| 1738 Generator.backend_method_implementati on_list, Templates.callback_main_methods, | |
| 1739 {"callbackName": callback_name, "agen tName": agent_interface_name}) | |
| 1740 | |
| 1741 callback_writer.newline("class " + callback_name + " : public Callba ckBase {\n") | |
| 1742 callback_writer.newline("public:\n") | |
| 1743 callback_writer.newline(" " + callback_name + "(PassRefPtr<Dispat cherImpl>, int sessionId, int id);\n") | |
| 1744 callback_writer.newline(" PLATFORM_EXPORT void sendSuccess(" + ", ".join(decl_parameter_list) + ");\n") | |
| 1745 callback_writer.newline("};\n") | |
| 1746 | |
| 1747 ad_hoc_type_output.append(callback_output) | |
| 1748 | |
| 1749 method_out_code += " RefPtr<" + agent_interface_name + "::" + cal lback_name + "> callback = adoptRef(new " + agent_interface_name + "::" + callba ck_name + "(this, sessionId, callId));\n" | |
| 1750 agent_call_param_list.append("callback") | |
| 1751 normal_response_cook_text += " if (!error.length()) \n" | |
| 1752 normal_response_cook_text += " return;\n" | |
| 1753 normal_response_cook_text += " callback->disable();\n" | |
| 1754 backend_agent_interface_list.append(", PassRefPtr<%s> callback" % ca llback_name) | |
| 1755 else: | |
| 1756 if "returns" in json_command: | |
| 1757 method_out_code += "\n" | |
| 1758 agent_call_params_declaration_list.append(" RefPtr<JSONObject > result = JSONObject::create();") | |
| 1759 send_response_call_params_list.append("result") | |
| 1760 response_cook_list = [] | |
| 1761 for json_return in json_command["returns"]: | |
| 1762 | |
| 1763 json_return_name = json_return["name"] | |
| 1764 | |
| 1765 optional = bool(json_return.get("optional")) | |
| 1766 | |
| 1767 return_type_binding = Generator.resolve_param_type_and_gener ate_ad_hoc(json_return, json_command_name, domain_name, ad_hoc_type_writer, agen t_interface_name + "::") | |
| 1768 | |
| 1769 raw_type = return_type_binding.reduce_to_raw_type() | |
| 1770 setter_type = raw_type.get_setter_name() | |
| 1771 | |
| 1772 type_model = return_type_binding.get_type_model() | |
| 1773 if optional: | |
| 1774 type_model = type_model.get_optional() | |
| 1775 | |
| 1776 code = " %s out_%s;\n" % (type_model.get_command_return_p ass_model().get_return_var_type(), json_return_name) | |
| 1777 param = "%sout_%s" % (type_model.get_command_return_pass_mod el().get_output_argument_prefix(), json_return_name) | |
| 1778 var_name = "out_%s" % json_return_name | |
| 1779 setter_argument = type_model.get_command_return_pass_model() .get_output_to_raw_expression() % var_name | |
| 1780 if return_type_binding.get_setter_value_expression_pattern() : | |
| 1781 setter_argument = return_type_binding.get_setter_value_e xpression_pattern() % setter_argument | |
| 1782 | |
| 1783 cook = " result->set%s(\"%s\", %s);\n" % (setter_type , json_return_name, | |
| 1784 setter_ argument) | |
| 1785 | |
| 1786 set_condition_pattern = type_model.get_command_return_pass_m odel().get_set_return_condition() | |
| 1787 if set_condition_pattern: | |
| 1788 cook = (" if (%s)\n " % (set_condition_pattern % var_name)) + cook | |
| 1789 annotated_type = type_model.get_command_return_pass_model(). get_output_parameter_type() | |
| 1790 | |
| 1791 param_name = var_name | |
| 1792 if optional: | |
| 1793 param_name = "opt_" + param_name | |
| 1794 | |
| 1795 backend_agent_interface_list.append(", %s %s" % (annotated_t ype, param_name)) | |
| 1796 response_cook_list.append(cook) | |
| 1797 | |
| 1798 method_out_code += code | |
| 1799 agent_call_param_list.append(param) | |
| 1800 | |
| 1801 normal_response_cook_text += "".join(response_cook_list) | |
| 1802 | |
| 1803 if len(normal_response_cook_text) != 0: | |
| 1804 normal_response_cook_text = " if (!error.length()) {\n" + normal_response_cook_text + " }" | |
| 1805 | |
| 1806 # Redirect to another agent's implementation. | |
| 1807 agent_field = "m_" + agent_field_name | |
| 1808 if "redirect" in json_command: | |
| 1809 agent_field = "m_" + DomainNameFixes.get_fixed_data(json_command.get ("redirect")) | |
| 1810 | |
| 1811 Generator.backend_method_implementation_list.append(Templates.backend_me thod.substitute(None, | |
| 1812 domainName=domain_name, methodName=json_command_name, | |
| 1813 agentField=agent_field, | |
| 1814 methodCode="".join([method_in_code, method_out_code]), | |
| 1815 agentCallParamsDeclaration="\n".join(agent_call_params_declaration_l ist), | |
| 1816 agentCallParams=", ".join(agent_call_param_list), | |
| 1817 requestMessageObject=request_message_param, | |
| 1818 responseCook=normal_response_cook_text, | |
| 1819 sendResponseCallParams=", ".join(send_response_call_params_list), | |
| 1820 commandNameIndex=cmd_enum_name)) | |
| 1821 declaration_command_name = "%s.%s\\0" % (domain_name, json_command_name) | |
| 1822 Generator.backend_method_name_declaration_list.append(" \"%s\"" % dec laration_command_name) | |
| 1823 assert Generator.backend_method_name_declaration_current_index < 2 ** 16 , "Number too large for unsigned short." | |
| 1824 Generator.backend_method_name_declaration_index_list.append(" %d," % Generator.backend_method_name_declaration_current_index) | |
| 1825 Generator.backend_method_name_declaration_current_index += len(declarati on_command_name) - 1 | |
| 1826 | |
| 1827 backend_agent_interface_list.append(") = 0;\n") | |
| 1828 | |
| 1829 class CallbackMethodStructTemplate: | |
| 1830 @staticmethod | |
| 1831 def append_prolog(line_list): | |
| 1832 pass | |
| 1833 | |
| 1834 @staticmethod | |
| 1835 def append_epilog(line_list): | |
| 1836 pass | |
| 1837 | |
| 1838 container_name = "jsonMessage" | |
| 1839 | |
| 1840 # Generates common code for event sending and callback response data sending . | |
| 1841 @staticmethod | |
| 1842 def generate_send_method(parameters, event_name, domain_name, ad_hoc_type_wr iter, decl_parameter_list, | |
| 1843 method_struct_template, | |
| 1844 generator_method_list, method_template, template_pa rams): | |
| 1845 method_line_list = [] | |
| 1846 if parameters: | |
| 1847 method_struct_template.append_prolog(method_line_list) | |
| 1848 for json_parameter in parameters: | |
| 1849 parameter_name = json_parameter["name"] | |
| 1850 | |
| 1851 param_type_binding = Generator.resolve_param_type_and_generate_a d_hoc(json_parameter, event_name, domain_name, ad_hoc_type_writer, "") | |
| 1852 | |
| 1853 raw_type = param_type_binding.reduce_to_raw_type() | |
| 1854 raw_type_binding = RawTypeBinding(raw_type) | |
| 1855 | |
| 1856 optional = bool(json_parameter.get("optional")) | |
| 1857 | |
| 1858 setter_type = raw_type.get_setter_name() | |
| 1859 | |
| 1860 type_model = param_type_binding.get_type_model() | |
| 1861 raw_type_model = raw_type_binding.get_type_model() | |
| 1862 if optional: | |
| 1863 type_model = type_model.get_optional() | |
| 1864 raw_type_model = raw_type_model.get_optional() | |
| 1865 | |
| 1866 annotated_type = type_model.get_input_param_type_text() | |
| 1867 mode_type_binding = param_type_binding | |
| 1868 | |
| 1869 decl_parameter_list.append("%s %s" % (annotated_type, parameter_ name)) | |
| 1870 | |
| 1871 setter_argument = raw_type_model.get_event_setter_expression_pat tern() % parameter_name | |
| 1872 if mode_type_binding.get_setter_value_expression_pattern(): | |
| 1873 setter_argument = mode_type_binding.get_setter_value_express ion_pattern() % setter_argument | |
| 1874 | |
| 1875 setter_code = " %s->set%s(\"%s\", %s);\n" % (method_struct_te mplate.container_name, setter_type, parameter_name, setter_argument) | |
| 1876 if optional: | |
| 1877 setter_code = (" if (%s)\n " % parameter_name) + sette r_code | |
| 1878 method_line_list.append(setter_code) | |
| 1879 | |
| 1880 method_struct_template.append_epilog(method_line_list) | |
| 1881 | |
| 1882 generator_method_list.append(method_template.substitute(None, | |
| 1883 domainName=domain_name, | |
| 1884 parameters=", ".join(decl_parameter_list), | |
| 1885 code="".join(method_line_list), **template_params)) | |
| 1886 | |
| 1887 @classmethod | |
| 1888 def resolve_param_type_and_generate_ad_hoc(cls, json_param, method_name, dom ain_name, ad_hoc_type_writer, container_relative_name_prefix_param): | |
| 1889 param_name = json_param["name"] | |
| 1890 return cls.resolve_type_and_generate_ad_hoc(json_param, param_name, meth od_name, domain_name, ad_hoc_type_writer, container_relative_name_prefix_param) | |
| 1891 | |
| 1892 @staticmethod | |
| 1893 def resolve_type_and_generate_ad_hoc(typable_element, element_name, method_n ame, domain_name, ad_hoc_type_writer, container_relative_name_prefix_param): | |
| 1894 ad_hoc_type_list = [] | |
| 1895 | |
| 1896 class AdHocTypeContext: | |
| 1897 container_full_name_prefix = "<not yet defined>" | |
| 1898 container_relative_name_prefix = container_relative_name_prefix_para m | |
| 1899 | |
| 1900 @staticmethod | |
| 1901 def get_type_name_fix(): | |
| 1902 class NameFix: | |
| 1903 class_name = Capitalizer.lower_camel_case_to_upper(element_n ame) | |
| 1904 | |
| 1905 @staticmethod | |
| 1906 def output_comment(writer): | |
| 1907 writer.newline("// Named after parameter '%s' while gene rating command/event %s.\n" % (element_name, method_name)) | |
| 1908 | |
| 1909 return NameFix | |
| 1910 | |
| 1911 @staticmethod | |
| 1912 def add_type(binding): | |
| 1913 ad_hoc_type_list.append(binding) | |
| 1914 | |
| 1915 type_binding = resolve_param_type(typable_element, domain_name, AdHocTyp eContext) | |
| 1916 | |
| 1917 class InterfaceForwardListener: | |
| 1918 @staticmethod | |
| 1919 def add_type_data(type_data): | |
| 1920 pass | |
| 1921 | |
| 1922 class InterfaceResolveContext: | |
| 1923 forward_listener = InterfaceForwardListener | |
| 1924 | |
| 1925 for type in ad_hoc_type_list: | |
| 1926 type.resolve_inner(InterfaceResolveContext) | |
| 1927 | |
| 1928 class InterfaceGenerateContext: | |
| 1929 validator_writer = "not supported in InterfaceGenerateContext" | |
| 1930 cpp_writer = validator_writer | |
| 1931 | |
| 1932 for type in ad_hoc_type_list: | |
| 1933 generator = type.get_code_generator() | |
| 1934 if generator: | |
| 1935 generator.generate_type_builder(ad_hoc_type_writer, InterfaceGen erateContext) | |
| 1936 | |
| 1937 return type_binding | |
| 1938 | |
| 1939 @staticmethod | |
| 1940 def process_types(type_map): | |
| 1941 output = Generator.type_builder_fragments | |
| 1942 | |
| 1943 class GenerateContext: | |
| 1944 validator_writer = Writer(Generator.validator_impl_list, "") | |
| 1945 cpp_writer = Writer(Generator.type_builder_impl_list, "") | |
| 1946 | |
| 1947 def generate_all_domains_code(out, type_data_callback): | |
| 1948 writer = Writer(out, "") | |
| 1949 for domain_data in type_map.domains(): | |
| 1950 namespace_declared = [] | |
| 1951 | |
| 1952 def namespace_lazy_generator(): | |
| 1953 if not namespace_declared: | |
| 1954 writer.newline("namespace ") | |
| 1955 writer.append(domain_data.name()) | |
| 1956 writer.append(" {\n") | |
| 1957 # What is a better way to change value from outer scope? | |
| 1958 namespace_declared.append(True) | |
| 1959 return writer | |
| 1960 | |
| 1961 for type_data in domain_data.types(): | |
| 1962 type_data_callback(type_data, namespace_lazy_generator) | |
| 1963 | |
| 1964 if namespace_declared: | |
| 1965 writer.append("} // ") | |
| 1966 writer.append(domain_data.name()) | |
| 1967 writer.append("\n\n") | |
| 1968 | |
| 1969 def create_type_builder_caller(generate_pass_id): | |
| 1970 def call_type_builder(type_data, writer_getter): | |
| 1971 code_generator = type_data.get_binding().get_code_generator() | |
| 1972 if code_generator and generate_pass_id == code_generator.get_gen erate_pass_id(): | |
| 1973 writer = writer_getter() | |
| 1974 | |
| 1975 code_generator.generate_type_builder(writer, GenerateContext ) | |
| 1976 return call_type_builder | |
| 1977 | |
| 1978 generate_all_domains_code(output, create_type_builder_caller(TypeBuilder Pass.MAIN)) | |
| 1979 | |
| 1980 Generator.type_builder_forwards.append("// Forward declarations.\n") | |
| 1981 | |
| 1982 def generate_forward_callback(type_data, writer_getter): | |
| 1983 if type_data in global_forward_listener.type_data_set: | |
| 1984 binding = type_data.get_binding() | |
| 1985 binding.get_code_generator().generate_forward_declaration(writer _getter()) | |
| 1986 generate_all_domains_code(Generator.type_builder_forwards, generate_forw ard_callback) | |
| 1987 | |
| 1988 Generator.type_builder_forwards.append("// End of forward declarations.\ n\n") | |
| 1989 | |
| 1990 Generator.type_builder_forwards.append("// Typedefs.\n") | |
| 1991 | |
| 1992 generate_all_domains_code(Generator.type_builder_forwards, create_type_b uilder_caller(TypeBuilderPass.TYPEDEF)) | |
| 1993 | |
| 1994 Generator.type_builder_forwards.append("// End of typedefs.\n\n") | |
| 1995 | |
| 1996 | |
| 1997 def flatten_list(input): | |
| 1998 res = [] | |
| 1999 | |
| 2000 def fill_recursive(l): | |
| 2001 for item in l: | |
| 2002 if isinstance(item, list): | |
| 2003 fill_recursive(item) | |
| 2004 else: | |
| 2005 res.append(item) | |
| 2006 fill_recursive(input) | |
| 2007 return res | |
| 2008 | 81 |
| 2009 def output_file(file_name): | 82 def output_file(file_name): |
| 2010 return open(file_name, "w") | 83 return open(file_name, "w") |
| 2011 | 84 |
| 2012 | 85 |
| 2013 Generator.go() | 86 def patch_full_qualified_refs(): |
| 2014 | 87 def patch_full_qualified_refs_in_domain(json, domain_name): |
| 2015 backend_h_file = output_file(output_dirname + "/Dispatcher.h") | 88 if isinstance(json, list): |
| 2016 backend_cpp_file = output_file(output_dirname + "/Dispatcher.cpp") | 89 for item in json: |
| 2017 | 90 patch_full_qualified_refs_in_domain(item, domain_name) |
| 2018 frontend_h_file = output_file(output_dirname + "/Frontend.h") | 91 |
| 2019 frontend_cpp_file = output_file(output_dirname + "/Frontend.cpp") | 92 if not isinstance(json, dict): |
| 2020 | 93 return |
| 2021 typebuilder_h_file = output_file(output_dirname + "/TypeBuilder.h") | 94 for key in json: |
| 2022 typebuilder_cpp_file = output_file(output_dirname + "/TypeBuilder.cpp") | 95 if key != "$ref": |
| 2023 | 96 patch_full_qualified_refs_in_domain(json[key], domain_name) |
| 2024 | 97 continue |
| 2025 backend_h_file.write(Templates.backend_h.substitute(None, | 98 if json["$ref"].find(".") == -1: |
| 2026 virtualSetters="\n".join(Generator.backend_virtual_setters_list), | 99 json["$ref"] = domain_name + "." + json["$ref"] |
| 2027 agentInterfaces="".join(flatten_list(Generator.backend_agent_interface_list) ), | 100 |
| 2028 methodNamesEnumContent="\n".join(Generator.method_name_enum_list))) | 101 for domain in json_api["domains"]: |
| 2029 | 102 patch_full_qualified_refs_in_domain(domain, domain["domain"]) |
| 2030 backend_cpp_file.write(Templates.backend_cpp.substitute(None, | 103 |
| 2031 constructorInit="\n".join(Generator.backend_constructor_init_list), | 104 |
| 2032 setters="\n".join(Generator.backend_setters_list), | 105 def create_user_type_definition(domain_name, type): |
| 2033 fieldDeclarations="\n".join(Generator.backend_field_list), | 106 return { |
| 2034 methodNameDeclarations="\n".join(Generator.backend_method_name_declaration_l ist), | 107 "return_type": "PassOwnPtr<protocol::TypeBuilder::%s::%s>" % (domain_nam e, type["id"]), |
| 2035 methodNameDeclarationsIndex="\n".join(Generator.backend_method_name_declarat ion_index_list), | 108 "pass_type": "PassOwnPtr<protocol::TypeBuilder::%s::%s>" % (domain_name, type["id"]), |
| 2036 methods="\n".join(Generator.backend_method_implementation_list), | 109 "to_pass_type": "%s.release()", |
| 2037 methodDeclarations="\n".join(Generator.backend_method_declaration_list), | 110 "type": "OwnPtr<protocol::TypeBuilder::%s::%s>" % (domain_name, type["id "]), |
| 2038 messageHandlers="\n".join(Generator.method_handler_list))) | 111 "raw_type": "protocol::TypeBuilder::%s::%s" % (domain_name, type["id"]), |
| 2039 | 112 "create_type": "adoptPtr(new protocol::TypeBuilder::%s::%s())" % (domain _name, type["id"]), |
| 2040 frontend_h_file.write(Templates.frontend_h.substitute(None, | 113 "optional_type": "OwnPtr<protocol::TypeBuilder::%s::%s>" % (domain_name, type["id"]), |
| 2041 fieldDeclarations="".join(Generator.frontend_class_field_lines), | 114 "optional_pass_type": "PassOwnPtr<protocol::TypeBuilder::%s::%s>" % (dom ain_name, type["id"]), |
| 2042 domainClassList="".join(Generator.frontend_domain_class_lines))) | 115 "from_optional_out": "%s.release()", |
| 2043 | 116 "json_getter": "FromValue<protocol::TypeBuilder::%s::%s>::convert(getObj ect(%%s))" % (domain_name, type["id"]), |
| 2044 frontend_cpp_file.write(Templates.frontend_cpp.substitute(None, | 117 "nullable": True, |
| 2045 constructorInit="".join(Generator.frontend_constructor_init_list), | 118 } |
| 2046 methods="\n".join(Generator.frontend_method_list))) | 119 |
| 2047 | 120 |
| 2048 typebuilder_h_file.write(Templates.typebuilder_h.substitute(None, | 121 def create_object_type_definition(): |
| 2049 typeBuilders="".join(flatten_list(Generator.type_builder_fragments)), | 122 return { |
| 2050 forwards="".join(Generator.type_builder_forwards), | 123 "return_type": "PassRefPtr<JSONObject>", |
| 2051 validatorIfdefName=VALIDATOR_IFDEF_NAME)) | 124 "pass_type": "PassRefPtr<JSONObject>", |
| 2052 | 125 "to_pass_type": "%s.release()", |
| 2053 typebuilder_cpp_file.write(Templates.typebuilder_cpp.substitute(None, | 126 "type": "RefPtr<JSONObject>", |
| 2054 enumConstantValues=EnumConstants.get_enum_constant_code(), | 127 "raw_type": "RefPtr<JSONObject>", |
| 2055 implCode="".join(flatten_list(Generator.type_builder_impl_list)), | 128 "optional_type": "RefPtr<JSONObject>", |
| 2056 validatorCode="".join(flatten_list(Generator.validator_impl_list)), | 129 "optional_pass_type": "PassRefPtr<JSONObject>", |
| 2057 validatorIfdefName=VALIDATOR_IFDEF_NAME)) | 130 "from_optional_out": "%s.release()", |
| 2058 | 131 "json_getter": "getObject(%s)", |
| 2059 backend_h_file.close() | 132 "nullable": True, |
| 2060 backend_cpp_file.close() | 133 } |
| 2061 | 134 |
| 2062 frontend_h_file.close() | 135 |
| 2063 frontend_cpp_file.close() | 136 def create_any_type_definition(): |
| 2064 | 137 return { |
| 2065 typebuilder_h_file.close() | 138 "return_type": "PassRefPtr<JSONValue>", |
| 2066 typebuilder_cpp_file.close() | 139 "pass_type": "PassRefPtr<JSONValue>", |
| 140 "to_pass_type": "%s.release()", | |
| 141 "type": "RefPtr<JSONValue>", | |
| 142 "raw_type": "RefPtr<JSONValue>", | |
| 143 "optional_type": "RefPtr<JSONValue>", | |
| 144 "optional_pass_type": "PassRefPtr<JSONValue>", | |
| 145 "from_optional_out": "%s.release()", | |
| 146 "json_getter": "getValue(%s)", | |
| 147 "nullable": True, | |
| 148 } | |
| 149 | |
| 150 | |
| 151 def create_primitive_type_definition(type): | |
| 152 if type == "string": | |
| 153 return { | |
| 154 "return_type": "String", | |
| 155 "pass_type": "const String&", | |
| 156 "to_pass_type": "%s", | |
| 157 "type": "String", | |
| 158 "raw_type": "String", | |
| 159 "optional_type": "protocol::TypeBuilder::OptionalValue<String>", | |
| 160 "optional_pass_type": "const protocol::TypeBuilder::OptionalValue<St ring>&", | |
| 161 "from_optional_out": "%s.get()", | |
| 162 "json_getter": "getString(%s)", | |
| 163 "nullable": False, | |
| 164 } | |
| 165 | |
| 166 typedefs = { | |
| 167 "number": "double", | |
| 168 "integer": "int", | |
| 169 "boolean": "bool" | |
| 170 } | |
| 171 return { | |
| 172 "return_type": typedefs[type], | |
| 173 "pass_type": typedefs[type], | |
| 174 "to_pass_type": "%s", | |
| 175 "type": typedefs[type], | |
| 176 "raw_type": typedefs[type], | |
| 177 "optional_type": "protocol::TypeBuilder::OptionalValue<" + typedefs[type ] + ">", | |
| 178 "optional_pass_type": "const protocol::TypeBuilder::OptionalValue<" + ty pedefs[type] + ">&", | |
| 179 "from_optional_out": "%s.get()", | |
| 180 "json_getter": "get" + to_title_case(type) + "(%s)", | |
| 181 "nullable": False, | |
| 182 } | |
| 183 | |
| 184 type_definitions = {} | |
| 185 type_definitions["string"] = create_primitive_type_definition("string") | |
| 186 type_definitions["number"] = create_primitive_type_definition("number") | |
| 187 type_definitions["integer"] = create_primitive_type_definition("integer") | |
| 188 type_definitions["boolean"] = create_primitive_type_definition("boolean") | |
| 189 type_definitions["object"] = create_object_type_definition() | |
| 190 type_definitions["any"] = create_any_type_definition() | |
| 191 | |
| 192 | |
| 193 def wrap_array_definition(type): | |
| 194 return { | |
| 195 "return_type": "PassOwnPtr<protocol::TypeBuilder::Array<%s>>" % type["ra w_type"], | |
| 196 "pass_type": "PassOwnPtr<protocol::TypeBuilder::Array<%s>>" % type["raw_ type"], | |
| 197 "to_pass_type": "%s.release()", | |
| 198 "type": "OwnPtr<protocol::TypeBuilder::Array<%s>>" % type["raw_type"], | |
| 199 "raw_type": "protocol::TypeBuilder::Array<%s>" % type["raw_type"], | |
| 200 "create_type": "adoptPtr(new <protocol::TypeBuilder::Array<%s>)" % type[ "raw_type"], | |
|
dgozman
2016/02/22 23:57:36
typo: new <protocol
| |
| 201 "out_type": "protocol::TypeBuilder::Array<%s>&" % type["raw_type"], | |
| 202 "optional_type": "OwnPtr<protocol::TypeBuilder::Array<%s>>" % type["raw_ type"], | |
| 203 "optional_pass_type": "PassOwnPtr<protocol::TypeBuilder::Array<%s>>" % t ype["raw_type"], | |
| 204 "from_optional_out": "%s.release()", | |
| 205 "json_getter": "FromValue<protocol::TypeBuilder::Array<%s>>::convert(get Array(%%s))" % type["raw_type"], | |
| 206 "nullable": True, | |
| 207 } | |
| 208 | |
| 209 | |
| 210 def create_type_definitions(): | |
| 211 for domain in json_api["domains"]: | |
| 212 if not ("types" in domain): | |
| 213 continue | |
| 214 for type in domain["types"]: | |
| 215 if type["type"] == "object": | |
| 216 type_definitions[domain["domain"] + "." + type["id"]] = create_u ser_type_definition(domain["domain"], type) | |
| 217 elif type["type"] == "array": | |
| 218 items_type = type["items"]["type"] | |
|
dgozman
2016/02/22 23:57:36
What about $ref? Should be easy.
| |
| 219 type_definitions[domain["domain"] + "." + type["id"]] = wrap_arr ay_definition(type_definitions[items_type]) | |
| 220 else: | |
| 221 type_definitions[domain["domain"] + "." + type["id"]] = create_p rimitive_type_definition(type["type"]) | |
| 222 | |
| 223 patch_full_qualified_refs() | |
| 224 create_type_definitions() | |
| 225 | |
| 226 | |
| 227 def type_definition(name): | |
| 228 return type_definitions[name] | |
| 229 | |
| 230 | |
| 231 def resolve_type(property): | |
| 232 if "$ref" in property: | |
| 233 return type_definitions[property["$ref"]] | |
| 234 if property["type"] == "array": | |
| 235 return wrap_array_definition(resolve_type(property["items"])) | |
| 236 return type_definitions[property["type"]] | |
| 237 | |
| 238 | |
| 239 def join_arrays(dict, keys): | |
| 240 result = [] | |
| 241 for key in keys: | |
| 242 if key in dict: | |
| 243 result += dict[key] | |
| 244 return result | |
| 245 | |
| 246 | |
| 247 def generate(class_name): | |
| 248 template_context = { | |
| 249 "class_name": class_name, | |
| 250 "api": json_api, | |
| 251 "join_arrays": join_arrays, | |
| 252 "resolve_type": resolve_type, | |
| 253 "type_definition": type_definition | |
| 254 } | |
| 255 h_template = jinja_env.get_template("/%s_template.h" % class_name) | |
| 256 cpp_template = jinja_env.get_template("/%s_template.cpp" % class_name) | |
| 257 h_file = output_file(output_dirname + "/" + class_name + ".h") | |
| 258 cpp_file = output_file(output_dirname + "/" + class_name + ".cpp") | |
| 259 h_file.write(h_template.render(template_context)) | |
| 260 cpp_file.write(cpp_template.render(template_context)) | |
| 261 h_file.close() | |
| 262 cpp_file.close() | |
| 263 | |
| 264 | |
| 265 jinja_env = initialize_jinja_env(output_dirname) | |
| 266 generate("Dispatcher") | |
| 267 generate("Frontend") | |
| 268 generate("TypeBuilder") | |
| OLD | NEW |