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