Changeset 101249 in webkit
- Timestamp:
- Nov 28, 2011 4:30:54 AM (12 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r101247 r101249 1 2011-11-28 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 Pavel Feldman. 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-11-28 Simon Hausmann <simon.hausmann@nokia.com> 2 15 -
trunk/Source/WebCore/inspector/CodeGeneratorInspector.py
r101236 r101249 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 … … 189 236 elif json_type == "number": 190 237 return RawTypes.Number 238 elif json_type == "any": 239 return RawTypes.Any 191 240 else: 192 241 raise Exception("Unknown type: %s" % json_type) … … 204 253 @classmethod 205 254 def get_c_param_type(cls, param_type, optional): 206 if param_type == ParamType.EVENT :255 if param_type == ParamType.EVENT or param_type == ParamType.TYPE_BUILDER_OUTPUT: 207 256 return cls._ref_c_type 208 257 else: … … 299 348 @classmethod 300 349 def get_c_param_type(cls, param_type, optional): 301 if param_type == ParamType.EVENT :350 if param_type == ParamType.EVENT or param_type == ParamType.TYPE_BUILDER_OUTPUT: 302 351 return cls._ref_c_type 303 352 else: … … 324 373 _plain_c_type = CParamType("RefPtr<InspectorObject>") 325 374 _ref_c_type = CParamType("PassRefPtr<InspectorObject>") 375 376 class Any(BaseType): 377 @classmethod 378 def get_c_param_type(cls, param_type, optional): 379 if param_type == ParamType.EVENT or param_type == ParamType.TYPE_BUILDER_OUTPUT: 380 return cls._ref_c_type 381 else: 382 return cls._plain_c_type 383 384 @staticmethod 385 def get_getter_name(): 386 return "Value" 387 388 get_setter_name = get_getter_name 389 390 @staticmethod 391 def get_c_initializer(): 392 return "InspectorValue::create()" 393 394 @staticmethod 395 def get_js_bind_type(): 396 raise Exception("Unsupported") 397 398 @staticmethod 399 def is_event_param_check_optional(): 400 return True 401 402 _plain_c_type = CParamType("RefPtr<InspectorValue>") 403 _ref_c_type = CParamType("PassRefPtr<InspectorValue>") 326 404 327 405 class Array(BaseType): … … 361 439 OUTPUT = "output" 362 440 EVENT = "event" 441 TYPE_BUILDER_OUTPUT = "typeBuilderOutput" 442 443 # Collection of InspectorObject class methods that are likely to be overloaded in generated class. 444 # We must explicitly import all overloaded methods or they won't be available to user. 445 INSPECTOR_OBJECT_SETTER_NAMES = frozenset(["setValue", "setBoolean", "setNumber", "setString", "setValue", "setObject", "setArray"]) 446 447 448 class TypeBindings: 449 @staticmethod 450 def create_for_named_type_declaration(json_type, context_domain_name): 451 if json_type["type"] == "string": 452 if "enum" in json_type: 453 454 class EnumBinding: 455 @staticmethod 456 def generate_type_builder(output, forward_listener): 457 enum = json_type["enum"] 458 # TODO: doc 459 output.append("namespace ") 460 output.append(json_type["id"]) 461 output.append(" {\n") 462 for enum_item in enum: 463 item_c_name = enum_item.replace('-', '_') 464 output.append("const char* const ") 465 output.append(Capitalizer.upper_camel_case_to_lower(item_c_name)) 466 output.append(" = \"") 467 output.append(enum_item) 468 output.append("\";\n") 469 output.append("} // namespace ") 470 output.append(json_type["id"]) 471 output.append("\n\n") 472 473 return EnumBinding 474 else: 475 476 class PlainString: 477 @staticmethod 478 def generate_type_builder(output, forward_listener): 479 if "description" in json_type: 480 output.append("/* ") 481 output.append(json_type["description"]) 482 output.append(" */\n") 483 output.append("typedef String ") 484 output.append(json_type["id"]) 485 output.append(";\n\n") 486 return PlainString 487 488 elif json_type["type"] == "object": 489 if "properties" in json_type: 490 491 class ClassBinding: 492 @staticmethod 493 def generate_type_builder(output, forward_listener): 494 # TODO: doc 495 output.append("class ") 496 class_name = json_type["id"] 497 output.append(class_name) 498 output.append(" : public InspectorObject {\n") 499 output.append("public:\n") 500 501 properties = json_type["properties"] 502 main_properties = [] 503 optional_properties = [] 504 for p in properties: 505 if "optional" in p and p["optional"]: 506 optional_properties.append(p) 507 else: 508 main_properties.append(p) 509 510 output.append( 511 """ enum { 512 NO_FIELDS_SET = 0, 513 """) 514 515 state_enum_items = [] 516 if len(main_properties) > 0: 517 pos = 0 518 for p in main_properties: 519 item_name = Capitalizer.camel_case_to_capitalized_with_underscores(p["name"]) + "_SET" 520 state_enum_items.append(item_name) 521 output.append(" %s = 1 << %s,\n" % (item_name, pos)) 522 pos += 1 523 all_fields_set_value = "(" + (" | ".join(state_enum_items)) + ")" 524 else: 525 all_fields_set_value = "0" 526 527 output.append( 528 """ ALL_FIELDS_SET = %s 529 }; 530 531 template<int STATE> 532 class Builder { 533 private: 534 RefPtr<InspectorObject> m_result; 535 536 template<int STEP> Builder<STATE | STEP>& castState() 537 { 538 return *reinterpret_cast<Builder<STATE | STEP>*>(this); 539 } 540 541 Builder(PassRefPtr<%s> ptr) 542 { 543 COMPILE_ASSERT(STATE == NO_FIELDS_SET, builder_created_in_non_init_state); 544 m_result = ptr; 545 } 546 friend class %s; 547 public: 548 """ % (all_fields_set_value, class_name, class_name)) 549 550 pos = 0 551 for prop in main_properties: 552 prop_name = prop["name"] 553 param_raw_type = resolve_param_raw_type(prop, context_domain_name) 554 output.append(""" 555 Builder<STATE | %s>& set%s(%s value) 556 { 557 COMPILE_ASSERT(!(STATE & %s), property_%s_already_set); 558 m_result->set%s("%s", value); 559 return castState<%s>(); 560 } 561 """ 562 % (state_enum_items[pos], 563 Capitalizer.lower_camel_case_to_upper(prop_name), 564 param_raw_type.get_c_param_type(ParamType.TYPE_BUILDER_OUTPUT, False).get_text(), 565 state_enum_items[pos], prop_name, 566 param_raw_type.get_setter_name(), prop_name, state_enum_items[pos])) 567 568 pos += 1 569 570 output.append(""" 571 operator RefPtr<%s>& () 572 { 573 COMPILE_ASSERT(STATE == ALL_FIELDS_SET, result_is_not_ready); 574 return *reinterpret_cast<RefPtr<%s>*>(&m_result); 575 } 576 577 operator PassRefPtr<%s> () 578 { 579 return RefPtr<%s>(*this); 580 } 581 }; 582 583 """ 584 % (class_name, class_name, class_name, class_name)) 585 586 output.append(" /*\n") 587 output.append(" * Synthetic constructor:\n") 588 output.append(" * RefPtr<%s> result = %s::create()" % (class_name, class_name)) 589 for prop in main_properties: 590 output.append("\n * .set%s(...)" % Capitalizer.lower_camel_case_to_upper(prop["name"])) 591 output.append(";\n */\n") 592 593 output.append( 594 """ static Builder<NO_FIELDS_SET> create() 595 { 596 return Builder<NO_FIELDS_SET>(adoptRef(new %s())); 597 } 598 """ % class_name) 599 600 for prop in optional_properties: 601 param_raw_type = resolve_param_raw_type(prop, context_domain_name) 602 setter_name = "set%s" % Capitalizer.lower_camel_case_to_upper(prop["name"]) 603 output.append("\n void %s" % setter_name) 604 output.append("(%s value)\n" % param_raw_type.get_c_param_type(ParamType.TYPE_BUILDER_OUTPUT, False).get_text()) 605 output.append(" {\n") 606 output.append(" this->set%s(\"%s\", value);\n" % (param_raw_type.get_setter_name(), prop["name"])) 607 output.append(" }\n") 608 609 if setter_name in INSPECTOR_OBJECT_SETTER_NAMES: 610 output.append(" using InspectorObject::%s;\n\n" % setter_name) 611 612 output.append("};\n\n") 613 return ClassBinding 614 else: 615 616 class PlainObjectBinding: 617 @staticmethod 618 def generate_type_builder(output, forward_listener): 619 # No-op 620 pass 621 return PlainObjectBinding 622 else: 623 raw_type = RawTypes.get(json_type["type"]) 624 625 class RawTypesBinding: 626 @staticmethod 627 def generate_type_builder(output, forward_listener): 628 # No-op 629 pass 630 return RawTypesBinding 363 631 364 632 365 633 class TypeData(object): 366 def __init__(self, json_type, json_domain ):634 def __init__(self, json_type, json_domain, domain_data): 367 635 self.json_type_ = json_type 368 636 self.json_domain_ = json_domain 369 370 if "type" in json_type: 371 json_type_name = json_type["type"] 372 raw_type = RawTypes.get(json_type_name) 373 else: 637 self.domain_data_ = domain_data 638 639 if "type" not in json_type: 374 640 raise Exception("Unknown type") 641 642 json_type_name = json_type["type"] 643 raw_type = RawTypes.get(json_type_name) 375 644 self.raw_type_ = raw_type 645 self.binding_ = TypeBindings.create_for_named_type_declaration(json_type, json_domain["domain"]) 376 646 377 647 def get_raw_type(self): 378 648 return self.raw_type_ 649 650 def get_binding(self): 651 return self.binding_ 652 653 654 class DomainData: 655 def __init__(self, json_domain): 656 self.json_domain = json_domain 657 self.types_ = [] 658 659 def add_type(self, type_data): 660 self.types_.append(type_data) 661 662 def name(self): 663 return self.json_domain["domain"] 664 665 def types(self): 666 return self.types_ 379 667 380 668 … … 382 670 def __init__(self, api): 383 671 self.map_ = {} 672 self.domains_ = [] 384 673 for json_domain in api["domains"]: 385 674 domain_name = json_domain["domain"] … … 387 676 domain_map = {} 388 677 self.map_[domain_name] = domain_map 678 679 domain_data = DomainData(json_domain) 680 self.domains_.append(domain_data) 389 681 390 682 if "types" in json_domain: 391 683 for json_type in json_domain["types"]: 392 684 type_name = json_type["id"] 393 type_data = TypeData(json_type, json_domain )685 type_data = TypeData(json_type, json_domain, domain_data) 394 686 domain_map[type_name] = type_data 687 domain_data.add_type(type_data) 688 689 def domains(self): 690 return self.domains_ 395 691 396 692 def get(self, domain_name, type_name): … … 428 724 429 725 class Templates: 726 def get_this_script_path_(absolute_path): 727 absolute_path = os.path.abspath(absolute_path) 728 components = [] 729 730 def fill_recursive(path_part, depth): 731 if depth <= 0 or path_part == '/': 732 return 733 fill_recursive(os.path.dirname(path_part), depth - 1) 734 components.append(os.path.basename(path_part)) 735 736 # Typical path is /Source/WebCore/inspector/CodeGeneratorInspector.py 737 # Let's take 4 components from the real path then. 738 fill_recursive(absolute_path, 4) 739 740 return "/".join(components) 741 742 file_header_ = ("// File is generated by %s\n\n" % get_this_script_path_(sys.argv[0]) + 743 """// Copyright (c) 2011 The Chromium Authors. All rights reserved. 744 // Use of this source code is governed by a BSD-style license that can be 745 // found in the LICENSE file. 746 """) 747 748 749 430 750 frontend_domain_class = string.Template( 431 751 """ class $domainClassName { … … 469 789 """) 470 790 471 frontend_h = string.Template("""// Copyright (c) 2011 The Chromium Authors. All rights reserved. 472 // Use of this source code is governed by a BSD-style license that can be 473 // found in the LICENSE file. 474 #ifndef InspectorFrontend_h 791 frontend_h = string.Template(file_header_ + 792 """#ifndef InspectorFrontend_h 475 793 #define InspectorFrontend_h 476 794 795 #include "InspectorValues.h" 477 796 #include <PlatformString.h> 478 797 #include <wtf/PassRefPtr.h> … … 480 799 namespace WebCore { 481 800 482 class InspectorArray;483 801 class InspectorFrontendChannel; 484 class InspectorObject;485 802 486 803 typedef String ErrorString; 804 805 namespace TypeBuilder { 806 ${typeBuilders} 807 } // namespace TypeBuilder 487 808 488 809 class InspectorFrontend { … … 500 821 """) 501 822 502 backend_h = string.Template("""// Copyright (c) 2011 The Chromium Authors. All rights reserved. 503 // Use of this source code is governed by a BSD-style license that can be 504 // found in the LICENSE file. 505 #ifndef InspectorBackendDispatcher_h 823 backend_h = string.Template(file_header_ + 824 """#ifndef InspectorBackendDispatcher_h 506 825 #define InspectorBackendDispatcher_h 507 826 … … 572 891 """) 573 892 574 backend_cpp = string.Template("""// Copyright (c) 2011 The Chromium Authors. All rights reserved. 575 // Use of this source code is governed by a BSD-style license that can be 576 // found in the LICENSE file. 577 893 backend_cpp = string.Template(file_header_ + 894 """ 578 895 579 896 #include "config.h" … … 903 1220 """) 904 1221 905 frontend_cpp = string.Template("""// Copyright (c) 2011 The Chromium Authors. All rights reserved. 906 // Use of this source code is governed by a BSD-style license that can be 907 // found in the LICENSE file. 908 1222 frontend_cpp = string.Template(file_header_ + 1223 """ 909 1224 910 1225 #include "config.h" … … 935 1250 """) 936 1251 937 backend_js = string.Template("""// Copyright (c) 2011 The Chromium Authors. All rights reserved. 938 // Use of this source code is governed by a BSD-style license that can be 939 // found in the LICENSE file. 940 1252 backend_js = string.Template(file_header_ + 1253 """ 941 1254 942 1255 InspectorBackendStub = function() … … 1213 1526 frontend_constructor_init_list = [] 1214 1527 frontend_capabilities_constants_list = [] 1528 type_builder_fragments = [] 1215 1529 1216 1530 @staticmethod 1217 1531 def go(): 1532 Generator.process_types(type_map) 1533 1218 1534 for json_domain in json_api["domains"]: 1219 1535 domain_name = json_domain["domain"] … … 1410 1726 Generator.backend_js_initializer_list.append(" this._registerDelegate('{\"method\": \"%s.%s\"%s, \"id\": 0}');\n" % (domain_name, json_command_name, js_parameters_text)) 1411 1727 1728 @staticmethod 1729 def process_types(type_map): 1730 output = Generator.type_builder_fragments 1731 1732 class ForwardListener: 1733 pass 1734 1735 for domain_data in type_map.domains(): 1736 output.append("namespace ") 1737 output.append(domain_data.name()) 1738 output.append(" {\n") 1739 for type_data in domain_data.types(): 1740 type_data.get_binding().generate_type_builder(output, ForwardListener) 1741 1742 output.append("} // ") 1743 output.append(domain_data.name()) 1744 output.append("\n") 1745 1412 1746 Generator.go() 1413 1747 … … 1423 1757 frontend_h_file.write(Templates.frontend_h.substitute(None, 1424 1758 fieldDeclarations=join(Generator.frontend_class_field_lines, ""), 1425 domainClassList=join(Generator.frontend_domain_class_lines, ""))) 1759 domainClassList=join(Generator.frontend_domain_class_lines, ""), 1760 typeBuilders=join(Generator.type_builder_fragments, ""))) 1426 1761 1427 1762 backend_h_file.write(Templates.backend_h.substitute(None, -
trunk/Source/WebCore/inspector/InspectorValues.h
r99683 r101249 207 207 const_iterator end() const { return m_data.end(); } 208 208 209 pr ivate:209 protected: 210 210 InspectorObject(); 211 212 private: 211 213 Dictionary m_data; 212 214 Vector<String> m_order;
Note: See TracChangeset
for help on using the changeset viewer.