Changeset 102440 in webkit
- Timestamp:
- Dec 9, 2011 12:33:02 AM (12 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r102435 r102440 1 2011-12-09 Peter Rybin <peter.rybin@gmail.com> 2 3 Web Inspector: [protocol] generate C++ classes for protocol JSON named types 4 https://bugs.webkit.org/show_bug.cgi?id=72835 5 6 Reviewed by NOBODY. 7 8 Extends python generator functionality. 9 Makes constructor in InspectorObject public. 10 11 * inspector/CodeGeneratorInspector.py: 12 * inspector/InspectorValues.h: 13 1 14 2011-12-08 Viatcheslav Ostapenko <ostapenko.viatcheslav@nokia.com> 2 15 -
trunk/Source/WebCore/inspector/CodeGeneratorInspector.py
r102005 r102440 105 105 class Capitalizer: 106 106 @staticmethod 107 def lower_camel_case_to_upper(str): 108 if len(str) > 0 and str[0].islower(): 109 str = str[0].upper() + str[1:] 110 return str 111 112 @staticmethod 107 113 def upper_camel_case_to_lower(str): 108 114 pos = 0 … … 121 127 return str 122 128 129 @staticmethod 130 def camel_case_to_capitalized_with_underscores(str): 131 if len(str) == 0: 132 return str 133 output = Capitalizer.split_camel_case_(str) 134 return "_".join(output).upper() 135 136 @staticmethod 137 def split_camel_case_(str): 138 output = [] 139 pos_being = 0 140 pos = 1 141 has_oneletter = False 142 while pos < len(str): 143 if str[pos].isupper(): 144 output.append(str[pos_being:pos].upper()) 145 if pos - pos_being == 1: 146 has_oneletter = True 147 pos_being = pos 148 pos += 1 149 output.append(str[pos_being:]) 150 if has_oneletter: 151 array_pos = 0 152 while array_pos < len(output) - 1: 153 if len(output[array_pos]) == 1: 154 array_pos_end = array_pos + 1 155 while array_pos_end < len(output) and len(output[array_pos_end]) == 1: 156 array_pos_end += 1 157 if array_pos_end - array_pos > 1: 158 possible_abbreviation = "".join(output[array_pos:array_pos_end]) 159 if possible_abbreviation.upper() in Capitalizer.ABBREVIATION: 160 output[array_pos:array_pos_end] = [possible_abbreviation] 161 else: 162 array_pos = array_pos_end - 1 163 array_pos += 1 164 return output 165 123 166 ABBREVIATION = frozenset(["XHR", "DOM", "CSS"]) 124 167 … … 187 230 elif json_type == "number": 188 231 return RawTypes.Number 232 elif json_type == "any": 233 return RawTypes.Any 189 234 else: 190 235 raise Exception("Unknown type: %s" % json_type) … … 202 247 @classmethod 203 248 def get_c_param_type(cls, param_type, optional): 204 if param_type == ParamType.EVENT :249 if param_type == ParamType.EVENT or param_type == ParamType.TYPE_BUILDER_OUTPUT: 205 250 return cls._ref_c_type 206 251 else: … … 297 342 @classmethod 298 343 def get_c_param_type(cls, param_type, optional): 299 if param_type == ParamType.EVENT :344 if param_type == ParamType.EVENT or param_type == ParamType.TYPE_BUILDER_OUTPUT: 300 345 return cls._ref_c_type 301 346 else: … … 322 367 _plain_c_type = CParamType("RefPtr<InspectorObject>") 323 368 _ref_c_type = CParamType("PassRefPtr<InspectorObject>") 369 370 class Any(BaseType): 371 @classmethod 372 def get_c_param_type(cls, param_type, optional): 373 if param_type == ParamType.EVENT or param_type == ParamType.TYPE_BUILDER_OUTPUT: 374 return cls._ref_c_type 375 else: 376 return cls._plain_c_type 377 378 @staticmethod 379 def get_getter_name(): 380 return "Value" 381 382 get_setter_name = get_getter_name 383 384 @staticmethod 385 def get_c_initializer(): 386 return "InspectorValue::create()" 387 388 @staticmethod 389 def get_js_bind_type(): 390 raise Exception("Unsupported") 391 392 @staticmethod 393 def is_event_param_check_optional(): 394 return True 395 396 _plain_c_type = CParamType("RefPtr<InspectorValue>") 397 _ref_c_type = CParamType("PassRefPtr<InspectorValue>") 324 398 325 399 class Array(BaseType): … … 359 433 OUTPUT = "output" 360 434 EVENT = "event" 435 TYPE_BUILDER_OUTPUT = "typeBuilderOutput" 436 437 # Collection of InspectorObject class methods that are likely to be overloaded in generated class. 438 # We must explicitly import all overloaded methods or they won't be available to user. 439 INSPECTOR_OBJECT_SETTER_NAMES = frozenset(["setValue", "setBoolean", "setNumber", "setString", "setValue", "setObject", "setArray"]) 440 441 442 class TypeBindings: 443 @staticmethod 444 def create_for_named_type_declaration(json_type, context_domain_name): 445 if json_type["type"] == "string": 446 if "enum" in json_type: 447 448 class EnumBinding: 449 @staticmethod 450 def generate_type_builder(output, forward_listener): 451 enum = json_type["enum"] 452 # TODO: doc 453 output.append("namespace ") 454 output.append(json_type["id"]) 455 output.append(" {\n") 456 for enum_item in enum: 457 item_c_name = enum_item.replace('-', '_') 458 output.append("const char* const ") 459 output.append(Capitalizer.upper_camel_case_to_lower(item_c_name)) 460 output.append(" = \"") 461 output.append(enum_item) 462 output.append("\";\n") 463 output.append("} // namespace ") 464 output.append(json_type["id"]) 465 output.append("\n\n") 466 467 return EnumBinding 468 else: 469 470 class PlainString: 471 @staticmethod 472 def generate_type_builder(output, forward_listener): 473 if "description" in json_type: 474 output.append("/* ") 475 output.append(json_type["description"]) 476 output.append(" */\n") 477 output.append("typedef String ") 478 output.append(json_type["id"]) 479 output.append(";\n\n") 480 return PlainString 481 482 elif json_type["type"] == "object": 483 if "properties" in json_type: 484 485 class ClassBinding: 486 @staticmethod 487 def generate_type_builder(output, forward_listener): 488 # TODO: doc 489 output.append("class ") 490 class_name = json_type["id"] 491 output.append(class_name) 492 output.append(" : public InspectorObject {\n") 493 output.append("public:\n") 494 495 properties = json_type["properties"] 496 main_properties = [] 497 optional_properties = [] 498 for p in properties: 499 if "optional" in p and p["optional"]: 500 optional_properties.append(p) 501 else: 502 main_properties.append(p) 503 504 output.append( 505 """ enum { 506 NO_FIELDS_SET = 0, 507 """) 508 509 state_enum_items = [] 510 if len(main_properties) > 0: 511 pos = 0 512 for p in main_properties: 513 item_name = Capitalizer.camel_case_to_capitalized_with_underscores(p["name"]) + "_SET" 514 state_enum_items.append(item_name) 515 output.append(" %s = 1 << %s,\n" % (item_name, pos)) 516 pos += 1 517 all_fields_set_value = "(" + (" | ".join(state_enum_items)) + ")" 518 else: 519 all_fields_set_value = "0" 520 521 output.append( 522 """ ALL_FIELDS_SET = %s 523 }; 524 525 template<int STATE> 526 class Builder { 527 private: 528 RefPtr<InspectorObject> m_result; 529 530 template<int STEP> Builder<STATE | STEP>& castState() 531 { 532 return *reinterpret_cast<Builder<STATE | STEP>*>(this); 533 } 534 535 Builder(PassRefPtr<%s> ptr) 536 { 537 COMPILE_ASSERT(STATE == NO_FIELDS_SET, builder_created_in_non_init_state); 538 m_result = ptr; 539 } 540 friend class %s; 541 public: 542 """ % (all_fields_set_value, class_name, class_name)) 543 544 pos = 0 545 for prop in main_properties: 546 prop_name = prop["name"] 547 param_raw_type = resolve_param_raw_type(prop, context_domain_name) 548 output.append(""" 549 Builder<STATE | %s>& set%s(%s value) 550 { 551 COMPILE_ASSERT(!(STATE & %s), property_%s_already_set); 552 m_result->set%s("%s", value); 553 return castState<%s>(); 554 } 555 """ 556 % (state_enum_items[pos], 557 Capitalizer.lower_camel_case_to_upper(prop_name), 558 param_raw_type.get_c_param_type(ParamType.TYPE_BUILDER_OUTPUT, False).get_text(), 559 state_enum_items[pos], prop_name, 560 param_raw_type.get_setter_name(), prop_name, state_enum_items[pos])) 561 562 pos += 1 563 564 output.append(""" 565 operator RefPtr<%s>& () 566 { 567 COMPILE_ASSERT(STATE == ALL_FIELDS_SET, result_is_not_ready); 568 return *reinterpret_cast<RefPtr<%s>*>(&m_result); 569 } 570 571 operator PassRefPtr<%s> () 572 { 573 return RefPtr<%s>(*this); 574 } 575 }; 576 577 """ 578 % (class_name, class_name, class_name, class_name)) 579 580 output.append(" /*\n") 581 output.append(" * Synthetic constructor:\n") 582 output.append(" * RefPtr<%s> result = %s::create()" % (class_name, class_name)) 583 for prop in main_properties: 584 output.append("\n * .set%s(...)" % Capitalizer.lower_camel_case_to_upper(prop["name"])) 585 output.append(";\n */\n") 586 587 output.append( 588 """ static Builder<NO_FIELDS_SET> create() 589 { 590 return Builder<NO_FIELDS_SET>(adoptRef(new %s())); 591 } 592 """ % class_name) 593 594 for prop in optional_properties: 595 param_raw_type = resolve_param_raw_type(prop, context_domain_name) 596 setter_name = "set%s" % Capitalizer.lower_camel_case_to_upper(prop["name"]) 597 output.append("\n void %s" % setter_name) 598 output.append("(%s value)\n" % param_raw_type.get_c_param_type(ParamType.TYPE_BUILDER_OUTPUT, False).get_text()) 599 output.append(" {\n") 600 output.append(" this->set%s(\"%s\", value);\n" % (param_raw_type.get_setter_name(), prop["name"])) 601 output.append(" }\n") 602 603 if setter_name in INSPECTOR_OBJECT_SETTER_NAMES: 604 output.append(" using InspectorObject::%s;\n\n" % setter_name) 605 606 output.append("};\n\n") 607 return ClassBinding 608 else: 609 610 class PlainObjectBinding: 611 @staticmethod 612 def generate_type_builder(output, forward_listener): 613 # No-op 614 pass 615 return PlainObjectBinding 616 else: 617 raw_type = RawTypes.get(json_type["type"]) 618 619 class RawTypesBinding: 620 @staticmethod 621 def generate_type_builder(output, forward_listener): 622 # No-op 623 pass 624 return RawTypesBinding 361 625 362 626 363 627 class TypeData(object): 364 def __init__(self, json_type, json_domain ):628 def __init__(self, json_type, json_domain, domain_data): 365 629 self.json_type_ = json_type 366 630 self.json_domain_ = json_domain 367 368 if "type" in json_type: 369 json_type_name = json_type["type"] 370 raw_type = RawTypes.get(json_type_name) 371 else: 631 self.domain_data_ = domain_data 632 633 if "type" not in json_type: 372 634 raise Exception("Unknown type") 635 636 json_type_name = json_type["type"] 637 raw_type = RawTypes.get(json_type_name) 373 638 self.raw_type_ = raw_type 639 self.binding_ = TypeBindings.create_for_named_type_declaration(json_type, json_domain["domain"]) 374 640 375 641 def get_raw_type(self): 376 642 return self.raw_type_ 643 644 def get_binding(self): 645 return self.binding_ 646 647 648 class DomainData: 649 def __init__(self, json_domain): 650 self.json_domain = json_domain 651 self.types_ = [] 652 653 def add_type(self, type_data): 654 self.types_.append(type_data) 655 656 def name(self): 657 return self.json_domain["domain"] 658 659 def types(self): 660 return self.types_ 377 661 378 662 … … 380 664 def __init__(self, api): 381 665 self.map_ = {} 666 self.domains_ = [] 382 667 for json_domain in api["domains"]: 383 668 domain_name = json_domain["domain"] … … 385 670 domain_map = {} 386 671 self.map_[domain_name] = domain_map 672 673 domain_data = DomainData(json_domain) 674 self.domains_.append(domain_data) 387 675 388 676 if "types" in json_domain: 389 677 for json_type in json_domain["types"]: 390 678 type_name = json_type["id"] 391 type_data = TypeData(json_type, json_domain )679 type_data = TypeData(json_type, json_domain, domain_data) 392 680 domain_map[type_name] = type_data 681 domain_data.add_type(type_data) 682 683 def domains(self): 684 return self.domains_ 393 685 394 686 def get(self, domain_name, type_name): … … 426 718 427 719 class Templates: 720 def get_this_script_path_(absolute_path): 721 absolute_path = os.path.abspath(absolute_path) 722 components = [] 723 724 def fill_recursive(path_part, depth): 725 if depth <= 0 or path_part == '/': 726 return 727 fill_recursive(os.path.dirname(path_part), depth - 1) 728 components.append(os.path.basename(path_part)) 729 730 # Typical path is /Source/WebCore/inspector/CodeGeneratorInspector.py 731 # Let's take 4 components from the real path then. 732 fill_recursive(absolute_path, 4) 733 734 return "/".join(components) 735 736 file_header_ = ("// File is generated by %s\n\n" % get_this_script_path_(sys.argv[0]) + 737 """// Copyright (c) 2011 The Chromium Authors. All rights reserved. 738 // Use of this source code is governed by a BSD-style license that can be 739 // found in the LICENSE file. 740 """) 741 742 743 428 744 frontend_domain_class = string.Template( 429 745 """ class $domainClassName { … … 467 783 """) 468 784 469 frontend_h = string.Template("""// Copyright (c) 2011 The Chromium Authors. All rights reserved. 470 // Use of this source code is governed by a BSD-style license that can be 471 // found in the LICENSE file. 472 #ifndef InspectorFrontend_h 785 frontend_h = string.Template(file_header_ + 786 """#ifndef InspectorFrontend_h 473 787 #define InspectorFrontend_h 474 788 789 #include "InspectorValues.h" 475 790 #include <PlatformString.h> 476 791 #include <wtf/PassRefPtr.h> … … 478 793 namespace WebCore { 479 794 795 class InspectorFrontendChannel; 796 797 // Both InspectorObject and InspectorArray may or may not be declared at this point as defined by ENABLED_INSPECTOR. 798 // Double-check we have them at least as forward declaration. 480 799 class InspectorArray; 481 class InspectorFrontendChannel;482 800 class InspectorObject; 483 801 484 802 typedef String ErrorString; 803 804 #if ENABLE(INSPECTOR) 805 806 namespace TypeBuilder { 807 ${typeBuilders} 808 } // namespace TypeBuilder 809 810 #endif // ENABLE(INSPECTOR) 485 811 486 812 class InspectorFrontend { … … 498 824 """) 499 825 500 backend_h = string.Template("""// Copyright (c) 2011 The Chromium Authors. All rights reserved. 501 // Use of this source code is governed by a BSD-style license that can be 502 // found in the LICENSE file. 503 #ifndef InspectorBackendDispatcher_h 826 backend_h = string.Template(file_header_ + 827 """#ifndef InspectorBackendDispatcher_h 504 828 #define InspectorBackendDispatcher_h 505 829 … … 571 895 """) 572 896 573 backend_cpp = string.Template("""// Copyright (c) 2011 The Chromium Authors. All rights reserved. 574 // Use of this source code is governed by a BSD-style license that can be 575 // found in the LICENSE file. 576 897 backend_cpp = string.Template(file_header_ + 898 """ 577 899 578 900 #include "config.h" … … 902 1224 """) 903 1225 904 frontend_cpp = string.Template("""// Copyright (c) 2011 The Chromium Authors. All rights reserved. 905 // Use of this source code is governed by a BSD-style license that can be 906 // found in the LICENSE file. 907 1226 frontend_cpp = string.Template(file_header_ + 1227 """ 908 1228 909 1229 #include "config.h" … … 932 1252 """) 933 1253 934 backend_js = string.Template("""// Copyright (c) 2011 The Chromium Authors. All rights reserved. 935 // Use of this source code is governed by a BSD-style license that can be 936 // found in the LICENSE file. 1254 backend_js = string.Template(file_header_ + 1255 """ 937 1256 938 1257 $delegates … … 970 1289 backend_include_list = [] 971 1290 frontend_constructor_init_list = [] 1291 type_builder_fragments = [] 972 1292 973 1293 @staticmethod 974 1294 def go(): 1295 Generator.process_types(type_map) 1296 975 1297 for json_domain in json_api["domains"]: 976 1298 domain_name = json_domain["domain"] … … 1156 1478 Generator.backend_js_initializer_list.append("InspectorBackend.registerCommand(\"%s.%s\", [%s], %s);\n" % (domain_name, json_command_name, js_parameters_text, js_reply_list)) 1157 1479 1480 @staticmethod 1481 def process_types(type_map): 1482 output = Generator.type_builder_fragments 1483 1484 class ForwardListener: 1485 pass 1486 1487 for domain_data in type_map.domains(): 1488 output.append("namespace ") 1489 output.append(domain_data.name()) 1490 output.append(" {\n") 1491 for type_data in domain_data.types(): 1492 type_data.get_binding().generate_type_builder(output, ForwardListener) 1493 1494 output.append("} // ") 1495 output.append(domain_data.name()) 1496 output.append("\n") 1497 1158 1498 Generator.go() 1159 1499 … … 1169 1509 frontend_h_file.write(Templates.frontend_h.substitute(None, 1170 1510 fieldDeclarations=join(Generator.frontend_class_field_lines, ""), 1171 domainClassList=join(Generator.frontend_domain_class_lines, ""))) 1511 domainClassList=join(Generator.frontend_domain_class_lines, ""), 1512 typeBuilders=join(Generator.type_builder_fragments, ""))) 1172 1513 1173 1514 backend_h_file.write(Templates.backend_h.substitute(None, -
trunk/Source/WebCore/inspector/InspectorValues.h
r102005 r102440 206 206 const_iterator end() const { return m_data.end(); } 207 207 208 pr ivate:208 protected: 209 209 InspectorObject(); 210 211 private: 210 212 Dictionary m_data; 211 213 Vector<String> m_order;
Note: See TracChangeset
for help on using the changeset viewer.