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