Changeset 102004 in webkit
- Timestamp:
- Dec 5, 2011 8:56:01 AM (12 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r102003 r102004 1 2011-12-05 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 Yury Semikhatsky. 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-05 Pavel Podivilov <podivilov@chromium.org> 2 15 -
trunk/Source/WebCore/inspector/CodeGeneratorInspector.py
r101756 r102004 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 pos = 0 135 while pos < len(output): 136 output[pos] = output[pos].upper() 137 pos += 1 138 return "_".join(output) 139 140 @staticmethod 141 def split_camel_case_(str): 142 output = [] 143 pos_being = 0 144 pos = 1 145 has_oneletter = False 146 while pos < len(str): 147 if str[pos].isupper(): 148 output.append(str[pos_being:pos].upper()) 149 if pos - pos_being == 1: 150 has_oneletter = True 151 pos_being = pos 152 pos += 1 153 output.append(str[pos_being:]) 154 if has_oneletter: 155 array_pos = 0 156 while array_pos < len(output) - 1: 157 if len(output[array_pos]) == 1: 158 array_pos_end = array_pos + 1 159 while array_pos_end < len(output) and len(output[array_pos_end]) == 1: 160 array_pos_end += 1 161 if array_pos_end - array_pos > 1: 162 possible_abbreviation = "".join(output[array_pos:array_pos_end]) 163 if possible_abbreviation.upper() in Capitalizer.ABBREVIATION: 164 output[array_pos:array_pos_end] = [possible_abbreviation] 165 else: 166 array_pos = array_pos_end - 1 167 array_pos += 1 168 return output 169 123 170 ABBREVIATION = frozenset(["XHR", "DOM", "CSS"]) 124 171 … … 187 234 elif json_type == "number": 188 235 return RawTypes.Number 236 elif json_type == "any": 237 return RawTypes.Any 189 238 else: 190 239 raise Exception("Unknown type: %s" % json_type) … … 202 251 @classmethod 203 252 def get_c_param_type(cls, param_type, optional): 204 if param_type == ParamType.EVENT :253 if param_type == ParamType.EVENT or param_type == ParamType.TYPE_BUILDER_OUTPUT: 205 254 return cls._ref_c_type 206 255 else: … … 297 346 @classmethod 298 347 def get_c_param_type(cls, param_type, optional): 299 if param_type == ParamType.EVENT :348 if param_type == ParamType.EVENT or param_type == ParamType.TYPE_BUILDER_OUTPUT: 300 349 return cls._ref_c_type 301 350 else: … … 322 371 _plain_c_type = CParamType("RefPtr<InspectorObject>") 323 372 _ref_c_type = CParamType("PassRefPtr<InspectorObject>") 373 374 class Any(BaseType): 375 @classmethod 376 def get_c_param_type(cls, param_type, optional): 377 if param_type == ParamType.EVENT or param_type == ParamType.TYPE_BUILDER_OUTPUT: 378 return cls._ref_c_type 379 else: 380 return cls._plain_c_type 381 382 @staticmethod 383 def get_getter_name(): 384 return "Value" 385 386 get_setter_name = get_getter_name 387 388 @staticmethod 389 def get_c_initializer(): 390 return "InspectorValue::create()" 391 392 @staticmethod 393 def get_js_bind_type(): 394 raise Exception("Unsupported") 395 396 @staticmethod 397 def is_event_param_check_optional(): 398 return True 399 400 _plain_c_type = CParamType("RefPtr<InspectorValue>") 401 _ref_c_type = CParamType("PassRefPtr<InspectorValue>") 324 402 325 403 class Array(BaseType): … … 359 437 OUTPUT = "output" 360 438 EVENT = "event" 439 TYPE_BUILDER_OUTPUT = "typeBuilderOutput" 440 441 # Collection of InspectorObject class methods that are likely to be overloaded in generated class. 442 # We must explicitly import all overloaded methods or they won't be available to user. 443 INSPECTOR_OBJECT_SETTER_NAMES = frozenset(["setValue", "setBoolean", "setNumber", "setString", "setValue", "setObject", "setArray"]) 444 445 446 class TypeBindings: 447 @staticmethod 448 def create_for_named_type_declaration(json_type, context_domain_name): 449 if json_type["type"] == "string": 450 if "enum" in json_type: 451 452 class EnumBinding: 453 @staticmethod 454 def generate_type_builder(output, forward_listener): 455 enum = json_type["enum"] 456 # TODO: doc 457 output.append("namespace ") 458 output.append(json_type["id"]) 459 output.append(" {\n") 460 for enum_item in enum: 461 item_c_name = enum_item.replace('-', '_') 462 output.append("const char* const ") 463 output.append(Capitalizer.upper_camel_case_to_lower(item_c_name)) 464 output.append(" = \"") 465 output.append(enum_item) 466 output.append("\";\n") 467 output.append("} // namespace ") 468 output.append(json_type["id"]) 469 output.append("\n\n") 470 471 return EnumBinding 472 else: 473 474 class PlainString: 475 @staticmethod 476 def generate_type_builder(output, forward_listener): 477 if "description" in json_type: 478 output.append("/* ") 479 output.append(json_type["description"]) 480 output.append(" */\n") 481 output.append("typedef String ") 482 output.append(json_type["id"]) 483 output.append(";\n\n") 484 return PlainString 485 486 elif json_type["type"] == "object": 487 if "properties" in json_type: 488 489 class ClassBinding: 490 @staticmethod 491 def generate_type_builder(output, forward_listener): 492 # TODO: doc 493 output.append("class ") 494 class_name = json_type["id"] 495 output.append(class_name) 496 output.append(" : public InspectorObject {\n") 497 output.append("public:\n") 498 499 properties = json_type["properties"] 500 main_properties = [] 501 optional_properties = [] 502 for p in properties: 503 if "optional" in p and p["optional"]: 504 optional_properties.append(p) 505 else: 506 main_properties.append(p) 507 508 output.append( 509 """ enum { 510 NO_FIELDS_SET = 0, 511 """) 512 513 state_enum_items = [] 514 if len(main_properties) > 0: 515 pos = 0 516 for p in main_properties: 517 item_name = Capitalizer.camel_case_to_capitalized_with_underscores(p["name"]) + "_SET" 518 state_enum_items.append(item_name) 519 output.append(" %s = 1 << %s,\n" % (item_name, pos)) 520 pos += 1 521 all_fields_set_value = "(" + (" | ".join(state_enum_items)) + ")" 522 else: 523 all_fields_set_value = "0" 524 525 output.append( 526 """ ALL_FIELDS_SET = %s 527 }; 528 529 template<int STATE> 530 class Builder { 531 private: 532 RefPtr<InspectorObject> m_result; 533 534 template<int STEP> Builder<STATE | STEP>& castState() 535 { 536 return *reinterpret_cast<Builder<STATE | STEP>*>(this); 537 } 538 539 Builder(PassRefPtr<%s> ptr) 540 { 541 COMPILE_ASSERT(STATE == NO_FIELDS_SET, builder_created_in_non_init_state); 542 m_result = ptr; 543 } 544 friend class %s; 545 public: 546 """ % (all_fields_set_value, class_name, class_name)) 547 548 pos = 0 549 for prop in main_properties: 550 prop_name = prop["name"] 551 param_raw_type = resolve_param_raw_type(prop, context_domain_name) 552 output.append(""" 553 Builder<STATE | %s>& set%s(%s value) 554 { 555 COMPILE_ASSERT(!(STATE & %s), property_%s_already_set); 556 m_result->set%s("%s", value); 557 return castState<%s>(); 558 } 559 """ 560 % (state_enum_items[pos], 561 Capitalizer.lower_camel_case_to_upper(prop_name), 562 param_raw_type.get_c_param_type(ParamType.TYPE_BUILDER_OUTPUT, False).get_text(), 563 state_enum_items[pos], prop_name, 564 param_raw_type.get_setter_name(), prop_name, state_enum_items[pos])) 565 566 pos += 1 567 568 output.append(""" 569 operator RefPtr<%s>& () 570 { 571 COMPILE_ASSERT(STATE == ALL_FIELDS_SET, result_is_not_ready); 572 return *reinterpret_cast<RefPtr<%s>*>(&m_result); 573 } 574 575 operator PassRefPtr<%s> () 576 { 577 return RefPtr<%s>(*this); 578 } 579 }; 580 581 """ 582 % (class_name, class_name, class_name, class_name)) 583 584 output.append(" /*\n") 585 output.append(" * Synthetic constructor:\n") 586 output.append(" * RefPtr<%s> result = %s::create()" % (class_name, class_name)) 587 for prop in main_properties: 588 output.append("\n * .set%s(...)" % Capitalizer.lower_camel_case_to_upper(prop["name"])) 589 output.append(";\n */\n") 590 591 output.append( 592 """ static Builder<NO_FIELDS_SET> create() 593 { 594 return Builder<NO_FIELDS_SET>(adoptRef(new %s())); 595 } 596 """ % class_name) 597 598 for prop in optional_properties: 599 param_raw_type = resolve_param_raw_type(prop, context_domain_name) 600 setter_name = "set%s" % Capitalizer.lower_camel_case_to_upper(prop["name"]) 601 output.append("\n void %s" % setter_name) 602 output.append("(%s value)\n" % param_raw_type.get_c_param_type(ParamType.TYPE_BUILDER_OUTPUT, False).get_text()) 603 output.append(" {\n") 604 output.append(" this->set%s(\"%s\", value);\n" % (param_raw_type.get_setter_name(), prop["name"])) 605 output.append(" }\n") 606 607 if setter_name in INSPECTOR_OBJECT_SETTER_NAMES: 608 output.append(" using InspectorObject::%s;\n\n" % setter_name) 609 610 output.append("};\n\n") 611 return ClassBinding 612 else: 613 614 class PlainObjectBinding: 615 @staticmethod 616 def generate_type_builder(output, forward_listener): 617 # No-op 618 pass 619 return PlainObjectBinding 620 else: 621 raw_type = RawTypes.get(json_type["type"]) 622 623 class RawTypesBinding: 624 @staticmethod 625 def generate_type_builder(output, forward_listener): 626 # No-op 627 pass 628 return RawTypesBinding 361 629 362 630 363 631 class TypeData(object): 364 def __init__(self, json_type, json_domain ):632 def __init__(self, json_type, json_domain, domain_data): 365 633 self.json_type_ = json_type 366 634 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: 635 self.domain_data_ = domain_data 636 637 if "type" not in json_type: 372 638 raise Exception("Unknown type") 639 640 json_type_name = json_type["type"] 641 raw_type = RawTypes.get(json_type_name) 373 642 self.raw_type_ = raw_type 643 self.binding_ = TypeBindings.create_for_named_type_declaration(json_type, json_domain["domain"]) 374 644 375 645 def get_raw_type(self): 376 646 return self.raw_type_ 647 648 def get_binding(self): 649 return self.binding_ 650 651 652 class DomainData: 653 def __init__(self, json_domain): 654 self.json_domain = json_domain 655 self.types_ = [] 656 657 def add_type(self, type_data): 658 self.types_.append(type_data) 659 660 def name(self): 661 return self.json_domain["domain"] 662 663 def types(self): 664 return self.types_ 377 665 378 666 … … 380 668 def __init__(self, api): 381 669 self.map_ = {} 670 self.domains_ = [] 382 671 for json_domain in api["domains"]: 383 672 domain_name = json_domain["domain"] … … 385 674 domain_map = {} 386 675 self.map_[domain_name] = domain_map 676 677 domain_data = DomainData(json_domain) 678 self.domains_.append(domain_data) 387 679 388 680 if "types" in json_domain: 389 681 for json_type in json_domain["types"]: 390 682 type_name = json_type["id"] 391 type_data = TypeData(json_type, json_domain )683 type_data = TypeData(json_type, json_domain, domain_data) 392 684 domain_map[type_name] = type_data 685 domain_data.add_type(type_data) 686 687 def domains(self): 688 return self.domains_ 393 689 394 690 def get(self, domain_name, type_name): … … 426 722 427 723 class Templates: 724 def get_this_script_path_(absolute_path): 725 absolute_path = os.path.abspath(absolute_path) 726 components = [] 727 728 def fill_recursive(path_part, depth): 729 if depth <= 0 or path_part == '/': 730 return 731 fill_recursive(os.path.dirname(path_part), depth - 1) 732 components.append(os.path.basename(path_part)) 733 734 # Typical path is /Source/WebCore/inspector/CodeGeneratorInspector.py 735 # Let's take 4 components from the real path then. 736 fill_recursive(absolute_path, 4) 737 738 return "/".join(components) 739 740 file_header_ = ("// File is generated by %s\n\n" % get_this_script_path_(sys.argv[0]) + 741 """// Copyright (c) 2011 The Chromium Authors. All rights reserved. 742 // Use of this source code is governed by a BSD-style license that can be 743 // found in the LICENSE file. 744 """) 745 746 747 428 748 frontend_domain_class = string.Template( 429 749 """ class $domainClassName { … … 467 787 """) 468 788 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 789 frontend_h = string.Template(file_header_ + 790 """#ifndef InspectorFrontend_h 473 791 #define InspectorFrontend_h 474 792 793 #include "InspectorValues.h" 475 794 #include <PlatformString.h> 476 795 #include <wtf/PassRefPtr.h> … … 478 797 namespace WebCore { 479 798 480 class InspectorArray;481 799 class InspectorFrontendChannel; 482 class InspectorObject;483 800 484 801 typedef String ErrorString; 802 803 namespace TypeBuilder { 804 ${typeBuilders} 805 } // namespace TypeBuilder 485 806 486 807 class InspectorFrontend { … … 498 819 """) 499 820 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 821 backend_h = string.Template(file_header_ + 822 """#ifndef InspectorBackendDispatcher_h 504 823 #define InspectorBackendDispatcher_h 505 824 … … 571 890 """) 572 891 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 892 backend_cpp = string.Template(file_header_ + 893 """ 577 894 578 895 #include "config.h" … … 902 1219 """) 903 1220 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 1221 frontend_cpp = string.Template(file_header_ + 1222 """ 908 1223 909 1224 #include "config.h" … … 932 1247 """) 933 1248 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. 1249 backend_js = string.Template(file_header_ + 1250 """ 937 1251 938 1252 $delegates … … 970 1284 backend_include_list = [] 971 1285 frontend_constructor_init_list = [] 1286 type_builder_fragments = [] 972 1287 973 1288 @staticmethod 974 1289 def go(): 1290 Generator.process_types(type_map) 1291 975 1292 for json_domain in json_api["domains"]: 976 1293 domain_name = json_domain["domain"] … … 1156 1473 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 1474 1475 @staticmethod 1476 def process_types(type_map): 1477 output = Generator.type_builder_fragments 1478 1479 class ForwardListener: 1480 pass 1481 1482 for domain_data in type_map.domains(): 1483 output.append("namespace ") 1484 output.append(domain_data.name()) 1485 output.append(" {\n") 1486 for type_data in domain_data.types(): 1487 type_data.get_binding().generate_type_builder(output, ForwardListener) 1488 1489 output.append("} // ") 1490 output.append(domain_data.name()) 1491 output.append("\n") 1492 1158 1493 Generator.go() 1159 1494 … … 1169 1504 frontend_h_file.write(Templates.frontend_h.substitute(None, 1170 1505 fieldDeclarations=join(Generator.frontend_class_field_lines, ""), 1171 domainClassList=join(Generator.frontend_domain_class_lines, ""))) 1506 domainClassList=join(Generator.frontend_domain_class_lines, ""), 1507 typeBuilders=join(Generator.type_builder_fragments, ""))) 1172 1508 1173 1509 backend_h_file.write(Templates.backend_h.substitute(None, -
trunk/Source/WebCore/inspector/InspectorValues.h
r101367 r102004 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.