2 # Copyright (c) 2011 Google Inc. All rights reserved.
3 # Copyright (c) 2012 Intel Corporation. All rights reserved.
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions are
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
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.
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.
39 import simplejson as json
41 import CodeGeneratorInspectorStrings
43 # Manually-filled map of type name replacements.
45 "RGBA": "Rgba", # RGBA is reported to be conflicting with a define name in Windows CE.
50 TYPES_WITH_RUNTIME_CAST_SET = frozenset(["Runtime.RemoteObject", "Runtime.PropertyDescriptor", "Runtime.InternalPropertyDescriptor",
51 "Debugger.FunctionDetails", "Debugger.CollectionEntry", "Debugger.CallFrame", "Debugger.Location",
52 "Canvas.TraceLog", "Canvas.ResourceState"])
54 TYPES_WITH_OPEN_FIELD_LIST_SET = frozenset([
55 # InspectorStyleSheet not only creates this property but wants to read it and modify it.
57 # InspectorResourceAgent needs to update mime-type.
60 cmdline_parser = optparse.OptionParser()
61 cmdline_parser.add_option("--output_dir")
64 arg_options, arg_values = cmdline_parser.parse_args()
65 if (len(arg_values) != 1):
66 raise Exception("Exactly one plain argument expected (found %s)" % len(arg_values))
67 input_json_filename = arg_values[0]
68 output_dirname = arg_options.output_dir
69 if not output_dirname:
70 raise Exception("Output directory must be specified")
72 # Work with python 2 and 3 http://docs.python.org/py3k/howto/pyporting.html
73 exc = sys.exc_info()[1]
74 sys.stderr.write("Failed to parse command-line arguments: %s\n\n" % exc)
75 sys.stderr.write("Usage: <script> --output_dir <output_dir> protocol.json\n")
79 # FIXME: move this methods under Capitalizer class below and remove duplications.
80 def dash_to_camelcase(word):
81 return ''.join(x.capitalize() or '-' for x in word.split('-'))
84 def fix_camel_case(name):
85 refined = re.sub(r'-(\w)', lambda pat: pat.group(1).upper(), name)
86 refined = to_title_case(refined)
87 return re.sub(r'(?i)HTML|XML|WML|API', lambda pat: pat.group(0).upper(), refined)
90 def to_title_case(name):
91 return name[:1].upper() + name[1:]
96 def lower_camel_case_to_upper(str):
97 if len(str) > 0 and str[0].islower():
98 str = str[0].upper() + str[1:]
102 def upper_camel_case_to_lower(str):
104 while pos < len(str) and str[pos].isupper():
109 return str[0].lower() + str[1:]
112 possible_abbreviation = str[0:pos]
113 if possible_abbreviation not in Capitalizer.ABBREVIATION:
114 raise Exception("Unknown abbreviation %s" % possible_abbreviation)
115 str = possible_abbreviation.lower() + str[pos:]
118 ABBREVIATION = frozenset(["XHR", "DOM", "CSS"])
120 VALIDATOR_IFDEF_NAME = "ENABLE(ASSERT)"
123 class DomainNameFixes:
125 def get_fixed_data(domain_name):
126 return Capitalizer.upper_camel_case_to_lower(domain_name) + "Agent"
128 class RawTypes(object):
131 if json_type == "boolean":
133 elif json_type == "string":
134 return RawTypes.String
135 elif json_type == "array":
136 return RawTypes.Array
137 elif json_type == "object":
138 return RawTypes.Object
139 elif json_type == "integer":
141 elif json_type == "number":
142 return RawTypes.Number
143 elif json_type == "any":
146 raise Exception("Unknown type: %s" % json_type)
148 class BaseType(object):
150 def get_raw_validator_call_text(cls):
151 return "RuntimeCastHelper::assertType<JSONValue::Type%s>" % cls.get_getter_name()
154 def get_getter_name():
155 raise Exception("Unsupported")
157 class String(BaseType):
159 def get_getter_name():
162 get_setter_name = get_getter_name
165 def get_constructor_pattern():
166 return "InspectorString::create(%s)"
169 def is_heavy_value():
173 def get_array_item_raw_c_type_text():
177 def get_raw_type_model():
178 return TypeModel.String
182 def get_getter_name():
186 def get_setter_name():
190 def get_constructor_pattern():
191 return "InspectorBasicValue::create(%s)"
194 def get_raw_validator_call_text(cls):
195 return "RuntimeCastHelper::assertInt"
198 def is_heavy_value():
202 def get_array_item_raw_c_type_text():
206 def get_raw_type_model():
209 class Number(BaseType):
211 def get_getter_name():
215 def get_setter_name():
219 def get_constructor_pattern():
220 return "InspectorBasicValue::create(%s)"
223 def get_raw_validator_call_text():
224 return "RuntimeCastHelper::assertType<JSONValue::TypeNumber>"
227 def is_heavy_value():
231 def get_array_item_raw_c_type_text():
235 def get_raw_type_model():
236 return TypeModel.Number
238 class Bool(BaseType):
240 def get_getter_name():
243 get_setter_name = get_getter_name
246 def get_constructor_pattern():
247 return "InspectorBasicValue::create(%s)"
250 def is_heavy_value():
254 def get_array_item_raw_c_type_text():
258 def get_raw_type_model():
259 return TypeModel.Bool
261 class Object(BaseType):
263 def get_getter_name():
267 def get_setter_name():
271 def get_constructor_pattern():
275 def get_output_argument_prefix():
279 def is_heavy_value():
283 def get_array_item_raw_c_type_text():
287 def get_raw_type_model():
288 return TypeModel.Object
292 def get_getter_name():
295 get_setter_name = get_getter_name
298 def get_constructor_pattern():
299 raise Exception("Unsupported")
302 def get_raw_validator_call_text():
303 return "RuntimeCastHelper::assertAny"
306 def is_heavy_value():
310 def get_array_item_raw_c_type_text():
314 def get_raw_type_model():
317 class Array(BaseType):
319 def get_getter_name():
323 def get_setter_name():
327 def get_constructor_pattern():
331 def get_output_argument_prefix():
335 def is_heavy_value():
339 def get_array_item_raw_c_type_text():
343 def get_raw_type_model():
344 return TypeModel.Array
347 def replace_right_shift(input_str):
348 return input_str.replace(">>", "> >")
351 class CommandReturnPassModel:
353 def __init__(self, var_type, set_condition):
354 self.var_type = var_type
355 self.set_condition = set_condition
357 def get_return_var_type(self):
361 def get_output_argument_prefix():
365 def get_output_to_raw_expression():
368 def get_output_parameter_type(self):
369 return self.var_type + "&"
371 def get_set_return_condition(self):
372 return self.set_condition
375 def __init__(self, var_type):
376 self.var_type = var_type
378 def get_return_var_type(self):
382 def get_output_argument_prefix():
386 def get_output_to_raw_expression():
389 def get_output_parameter_type(self):
390 return self.var_type + "*"
393 def get_set_return_condition():
397 def __init__(self, var_type):
398 self.var_type = var_type
400 def get_return_var_type(self):
401 return "TypeBuilder::OptOutput<%s>" % self.var_type
404 def get_output_argument_prefix():
408 def get_output_to_raw_expression():
409 return "%s.getValue()"
411 def get_output_parameter_type(self):
412 return "TypeBuilder::OptOutput<%s>*" % self.var_type
415 def get_set_return_condition():
416 return "%s.isAssigned()"
420 class RefPtrBased(object):
421 def __init__(self, class_name):
422 self.class_name = class_name
423 self.optional = False
425 def get_optional(self):
426 result = TypeModel.RefPtrBased(self.class_name)
427 result.optional = True
430 def get_command_return_pass_model(self):
435 return CommandReturnPassModel.ByReference(replace_right_shift("RefPtr<%s>" % self.class_name), set_condition)
437 def get_input_param_type_text(self):
438 return replace_right_shift("PassRefPtr<%s>" % self.class_name)
441 def get_event_setter_expression_pattern():
445 def __init__(self, base_type_name):
446 self.type_name = base_type_name + "::Enum"
448 def get_optional(base_self):
451 def get_optional(cls):
455 def get_command_return_pass_model():
456 return CommandReturnPassModel.OptOutput(base_self.type_name)
459 def get_input_param_type_text():
460 return base_self.type_name + "*"
463 def get_event_setter_expression_pattern():
464 raise Exception("TODO")
467 def get_command_return_pass_model(self):
468 return CommandReturnPassModel.ByPointer(self.type_name)
470 def get_input_param_type_text(self):
471 return self.type_name
474 def get_event_setter_expression_pattern():
477 class ValueType(object):
478 def __init__(self, type_name, is_heavy):
479 self.type_name = type_name
480 self.is_heavy = is_heavy
482 def get_optional(self):
483 return self.ValueOptional(self)
485 def get_command_return_pass_model(self):
486 return CommandReturnPassModel.ByPointer(self.type_name)
488 def get_input_param_type_text(self):
490 return "const %s&" % self.type_name
492 return self.type_name
494 def get_opt_output_type_(self):
495 return self.type_name
498 def get_event_setter_expression_pattern():
502 def __init__(self, base):
505 def get_optional(self):
508 def get_command_return_pass_model(self):
509 return CommandReturnPassModel.OptOutput(self.base.get_opt_output_type_())
511 def get_input_param_type_text(self):
512 return "const %s* const" % self.base.type_name
515 def get_event_setter_expression_pattern():
520 cls.Bool = cls.ValueType("bool", False)
521 cls.Int = cls.ValueType("int", False)
522 cls.Number = cls.ValueType("double", False)
523 cls.String = cls.ValueType("String", True,)
524 cls.Object = cls.RefPtrBased("JSONObject")
525 cls.Array = cls.RefPtrBased("JSONArray")
526 cls.Any = cls.RefPtrBased("JSONValue")
528 TypeModel.init_class()
531 # Collection of JSONObject class methods that are likely to be overloaded in generated class.
532 # We must explicitly import all overloaded methods or they won't be available to user.
533 INSPECTOR_OBJECT_SETTER_NAMES = frozenset(["setValue", "setBoolean", "setNumber", "setString", "setValue", "setObject", "setArray"])
536 def fix_type_name(json_name):
537 if json_name in TYPE_NAME_FIX_MAP:
538 fixed = TYPE_NAME_FIX_MAP[json_name]
540 class Result(object):
544 def output_comment(writer):
545 writer.newline("// Type originally was named '%s'.\n" % json_name)
548 class Result(object):
549 class_name = json_name
552 def output_comment(writer):
559 def __init__(self, output, indent):
563 def newline(self, str):
565 self.output.append(self.indent)
566 self.output.append(str)
568 def append(self, str):
569 self.output.append(str)
571 def newline_multiline(self, str):
572 parts = str.split('\n')
573 self.newline(parts[0])
575 self.output.append('\n')
579 def append_multiline(self, str):
580 parts = str.split('\n')
581 self.append(parts[0])
583 self.output.append('\n')
587 def get_indent(self):
590 def insert_writer(self, additional_indent):
592 self.output.append(new_output)
593 return Writer(new_output, self.indent + additional_indent)
601 def add_constant(cls, value):
602 if value in cls.map_:
603 return cls.map_[value]
606 cls.map_[value] = pos
607 cls.constants_.append(value)
611 def get_enum_constant_code(cls):
613 for item in cls.constants_:
614 output.append(" \"" + item + "\"")
615 return ",\n".join(output) + "\n"
618 # Typebuilder code is generated in several passes: first typedefs, then other classes.
619 # Manual pass management is needed because we cannot have forward declarations for typedefs.
620 class TypeBuilderPass:
627 def create_named_type_declaration(json_typable, context_domain_name, type_data):
628 json_type = type_data.get_json_type()
632 full_name_prefix_for_use = "TypeBuilder::" + context_domain_name + "::"
633 full_name_prefix_for_impl = "TypeBuilder::" + context_domain_name + "::"
636 def write_doc(writer):
637 if "description" in json_type:
638 writer.newline("/* ")
639 writer.append(json_type["description"])
640 writer.append(" */\n")
643 def add_to_forward_listener(forward_listener):
644 forward_listener.add_type_data(type_data)
647 fixed_type_name = fix_type_name(json_type["id"])
648 return TypeBindings.create_type_declaration_(json_typable, context_domain_name, fixed_type_name, Helper)
651 def create_ad_hoc_type_declaration(json_typable, context_domain_name, ad_hoc_type_context):
654 full_name_prefix_for_use = ad_hoc_type_context.container_relative_name_prefix
655 full_name_prefix_for_impl = ad_hoc_type_context.container_full_name_prefix
658 def write_doc(writer):
662 def add_to_forward_listener(forward_listener):
664 fixed_type_name = ad_hoc_type_context.get_type_name_fix()
665 return TypeBindings.create_type_declaration_(json_typable, context_domain_name, fixed_type_name, Helper)
668 def create_type_declaration_(json_typable, context_domain_name, fixed_type_name, helper):
669 if json_typable["type"] == "string":
670 if "enum" in json_typable:
673 need_user_runtime_cast_ = False
674 need_internal_runtime_cast_ = False
677 def resolve_inner(cls, resolve_context):
681 def request_user_runtime_cast(cls, request):
683 cls.need_user_runtime_cast_ = True
684 request.acknowledge()
687 def request_internal_runtime_cast(cls):
688 cls.need_internal_runtime_cast_ = True
691 def get_code_generator(enum_binding_cls):
695 def generate_type_builder(writer, generate_context):
696 enum = json_typable["enum"]
697 helper.write_doc(writer)
698 enum_name = fixed_type_name.class_name
699 fixed_type_name.output_comment(writer)
700 writer.newline("struct ")
701 writer.append(enum_name)
702 writer.append(" {\n")
703 writer.newline(" enum Enum {\n")
704 for enum_item in enum:
705 enum_pos = EnumConstants.add_constant(enum_item)
707 item_c_name = enum_item.replace('-', '_')
708 item_c_name = Capitalizer.lower_camel_case_to_upper(item_c_name)
709 if item_c_name in TYPE_NAME_FIX_MAP:
710 item_c_name = TYPE_NAME_FIX_MAP[item_c_name]
712 writer.append(item_c_name)
714 writer.append("%s" % enum_pos)
716 writer.newline(" };\n")
717 if enum_binding_cls.need_user_runtime_cast_:
718 raise Exception("Not yet implemented")
720 if enum_binding_cls.need_internal_runtime_cast_:
721 writer.append("#if %s\n" % VALIDATOR_IFDEF_NAME)
722 writer.newline(" static void assertCorrectValue(JSONValue* value);\n")
723 writer.append("#endif // %s\n" % VALIDATOR_IFDEF_NAME)
725 validator_writer = generate_context.validator_writer
727 validator_writer.newline("void %s%s::assertCorrectValue(JSONValue* value)\n" % (helper.full_name_prefix_for_impl, enum_name))
728 validator_writer.newline("{\n")
729 validator_writer.newline(" WTF::String s;\n")
730 validator_writer.newline(" bool cast_res = value->asString(&s);\n")
731 validator_writer.newline(" ASSERT(cast_res);\n")
734 for enum_item in enum:
735 enum_pos = EnumConstants.add_constant(enum_item)
736 condition_list.append("s == \"%s\"" % enum_item)
737 validator_writer.newline(" ASSERT(%s);\n" % " || ".join(condition_list))
738 validator_writer.newline("}\n")
740 validator_writer.newline("\n\n")
742 writer.newline("}; // struct ")
743 writer.append(enum_name)
744 writer.append("\n\n")
747 def register_use(forward_listener):
751 def get_generate_pass_id():
752 return TypeBuilderPass.MAIN
757 def get_validator_call_text(cls):
758 return helper.full_name_prefix_for_use + fixed_type_name.class_name + "::assertCorrectValue"
761 def get_array_item_c_type_text(cls):
762 return helper.full_name_prefix_for_use + fixed_type_name.class_name + "::Enum"
765 def get_setter_value_expression_pattern():
766 return "TypeBuilder::getEnumConstantValue(%s)"
769 def reduce_to_raw_type():
770 return RawTypes.String
773 def get_type_model():
774 return TypeModel.Enum(helper.full_name_prefix_for_use + fixed_type_name.class_name)
782 def resolve_inner(cls, resolve_context):
786 def request_user_runtime_cast(request):
787 raise Exception("Unsupported")
790 def request_internal_runtime_cast():
794 def get_code_generator():
798 def get_validator_call_text(cls):
799 return RawTypes.String.get_raw_validator_call_text()
802 def reduce_to_raw_type():
803 return RawTypes.String
806 def get_type_model():
807 return TypeModel.String
810 def get_setter_value_expression_pattern():
814 def get_array_item_c_type_text(cls):
815 return cls.reduce_to_raw_type().get_array_item_raw_c_type_text()
823 def resolve_inner(cls, resolve_context):
827 def request_user_runtime_cast(request):
828 raise Exception("Unsupported")
831 def request_internal_runtime_cast():
835 def get_code_generator():
838 def generate_type_builder(writer, generate_context):
839 helper.write_doc(writer)
840 fixed_type_name.output_comment(writer)
841 writer.newline("typedef String ")
842 writer.append(fixed_type_name.class_name)
843 writer.append(";\n\n")
846 def register_use(forward_listener):
850 def get_generate_pass_id():
851 return TypeBuilderPass.TYPEDEF
856 def get_validator_call_text(cls):
857 return RawTypes.String.get_raw_validator_call_text()
860 def reduce_to_raw_type():
861 return RawTypes.String
864 def get_type_model():
865 return TypeModel.ValueType("%s%s" % (helper.full_name_prefix_for_use, fixed_type_name.class_name), True)
868 def get_setter_value_expression_pattern():
872 def get_array_item_c_type_text(cls):
873 return "%s%s" % (helper.full_name_prefix_for_use, fixed_type_name.class_name)
877 elif json_typable["type"] == "object":
878 if "properties" in json_typable:
882 need_user_runtime_cast_ = False
883 need_internal_runtime_cast_ = False
886 def resolve_inner(cls, resolve_context):
887 if cls.resolve_data_:
890 properties = json_typable["properties"]
894 ad_hoc_type_list = []
896 for prop in properties:
897 prop_name = prop["name"]
898 ad_hoc_type_context = cls.AdHocTypeContextImpl(prop_name, fixed_type_name.class_name, resolve_context, ad_hoc_type_list, helper.full_name_prefix_for_impl)
899 binding = resolve_param_type(prop, context_domain_name, ad_hoc_type_context)
901 code_generator = binding.get_code_generator()
903 code_generator.register_use(resolve_context.forward_listener)
906 param_type_binding = binding
909 if prop.get("optional"):
910 optional.append(PropertyData)
912 main.append(PropertyData)
915 main_properties = main
916 optional_properties = optional
917 ad_hoc_types = ad_hoc_type_list
919 cls.resolve_data_ = ResolveData
921 for ad_hoc in ad_hoc_type_list:
922 ad_hoc.resolve_inner(resolve_context)
925 def request_user_runtime_cast(cls, request):
928 cls.need_user_runtime_cast_ = True
929 request.acknowledge()
930 cls.request_internal_runtime_cast()
933 def request_internal_runtime_cast(cls):
934 if cls.need_internal_runtime_cast_:
936 cls.need_internal_runtime_cast_ = True
937 for p in cls.resolve_data_.main_properties:
938 p.param_type_binding.request_internal_runtime_cast()
939 for p in cls.resolve_data_.optional_properties:
940 p.param_type_binding.request_internal_runtime_cast()
943 def get_code_generator(class_binding_cls):
946 def generate_type_builder(cls, writer, generate_context):
947 resolve_data = class_binding_cls.resolve_data_
948 helper.write_doc(writer)
949 class_name = fixed_type_name.class_name
951 is_open_type = (context_domain_name + "." + class_name) in TYPES_WITH_OPEN_FIELD_LIST_SET
953 fixed_type_name.output_comment(writer)
954 writer.newline("class ")
955 writer.append(class_name)
956 writer.append(" : public ")
958 writer.append("JSONObject")
960 writer.append("JSONObjectBase")
961 writer.append(" {\n")
962 writer.newline("public:\n")
963 ad_hoc_type_writer = writer.insert_writer(" ")
965 for ad_hoc_type in resolve_data.ad_hoc_types:
966 code_generator = ad_hoc_type.get_code_generator()
968 code_generator.generate_type_builder(ad_hoc_type_writer, generate_context)
970 writer.newline_multiline(
975 state_enum_items = []
976 if len(resolve_data.main_properties) > 0:
978 for prop_data in resolve_data.main_properties:
979 item_name = Capitalizer.lower_camel_case_to_upper(prop_data.p["name"]) + "Set"
980 state_enum_items.append(item_name)
981 writer.newline(" %s = 1 << %s,\n" % (item_name, pos))
983 all_fields_set_value = "(" + (" | ".join(state_enum_items)) + ")"
985 all_fields_set_value = "0"
987 writer.newline_multiline(CodeGeneratorInspectorStrings.class_binding_builder_part_1
988 % (all_fields_set_value, class_name, class_name))
991 for prop_data in resolve_data.main_properties:
992 prop_name = prop_data.p["name"]
994 param_type_binding = prop_data.param_type_binding
995 param_raw_type = param_type_binding.reduce_to_raw_type()
997 writer.newline_multiline(CodeGeneratorInspectorStrings.class_binding_builder_part_2
998 % (state_enum_items[pos],
999 Capitalizer.lower_camel_case_to_upper(prop_name),
1000 param_type_binding.get_type_model().get_input_param_type_text(),
1001 state_enum_items[pos], prop_name,
1002 param_raw_type.get_setter_name(), prop_name,
1003 format_setter_value_expression(param_type_binding, "value"),
1004 state_enum_items[pos]))
1008 writer.newline_multiline(CodeGeneratorInspectorStrings.class_binding_builder_part_3
1009 % (class_name, class_name, class_name, class_name, class_name))
1011 writer.newline(" /*\n")
1012 writer.newline(" * Synthetic constructor:\n")
1013 writer.newline(" * RefPtr<%s> result = %s::create()" % (class_name, class_name))
1014 for prop_data in resolve_data.main_properties:
1015 writer.append_multiline("\n * .set%s(...)" % Capitalizer.lower_camel_case_to_upper(prop_data.p["name"]))
1016 writer.append_multiline(";\n */\n")
1018 writer.newline_multiline(CodeGeneratorInspectorStrings.class_binding_builder_part_4)
1020 writer.newline(" typedef TypeBuilder::StructItemTraits ItemTraits;\n")
1022 for prop_data in resolve_data.main_properties:
1023 prop_name = prop_data.p["name"]
1024 param_type_binding = prop_data.param_type_binding
1025 if isinstance(param_type_binding.get_type_model(), TypeModel.ValueType):
1026 writer.append_multiline("\n void %s" % prop_name)
1027 writer.append("(%s value)\n" % param_type_binding.get_type_model().get_command_return_pass_model().get_output_parameter_type())
1028 writer.newline(" {\n")
1029 writer.newline(" JSONObjectBase::get%s(\"%s\", value);\n"
1030 % (param_type_binding.reduce_to_raw_type().get_setter_name(), prop_data.p["name"]))
1031 writer.newline(" }\n")
1033 for prop_data in resolve_data.optional_properties:
1034 prop_name = prop_data.p["name"]
1035 param_type_binding = prop_data.param_type_binding
1036 setter_name = "set%s" % Capitalizer.lower_camel_case_to_upper(prop_name)
1038 writer.append_multiline("\n void %s" % setter_name)
1039 writer.append("(%s value)\n" % param_type_binding.get_type_model().get_input_param_type_text())
1040 writer.newline(" {\n")
1041 writer.newline(" this->set%s(\"%s\", %s);\n"
1042 % (param_type_binding.reduce_to_raw_type().get_setter_name(), prop_data.p["name"],
1043 format_setter_value_expression(param_type_binding, "value")))
1044 writer.newline(" }\n")
1046 if setter_name in INSPECTOR_OBJECT_SETTER_NAMES:
1047 writer.newline(" using JSONObjectBase::%s;\n\n" % setter_name)
1049 if class_binding_cls.need_user_runtime_cast_:
1050 writer.newline(" static PassRefPtr<%s> runtimeCast(PassRefPtr<JSONValue> value)\n" % class_name)
1051 writer.newline(" {\n")
1052 writer.newline(" RefPtr<JSONObject> object;\n")
1053 writer.newline(" bool castRes = value->asObject(&object);\n")
1054 writer.newline(" ASSERT_UNUSED(castRes, castRes);\n")
1055 writer.append("#if %s\n" % VALIDATOR_IFDEF_NAME)
1056 writer.newline(" assertCorrectValue(object.get());\n")
1057 writer.append("#endif // %s\n" % VALIDATOR_IFDEF_NAME)
1058 writer.newline(" COMPILE_ASSERT(sizeof(%s) == sizeof(JSONObjectBase), type_cast_problem);\n" % class_name)
1059 writer.newline(" return static_cast<%s*>(static_cast<JSONObjectBase*>(object.get()));\n" % class_name)
1060 writer.newline(" }\n")
1063 if class_binding_cls.need_internal_runtime_cast_:
1064 writer.append("#if %s\n" % VALIDATOR_IFDEF_NAME)
1065 writer.newline(" static void assertCorrectValue(JSONValue* value);\n")
1066 writer.append("#endif // %s\n" % VALIDATOR_IFDEF_NAME)
1068 closed_field_set = (context_domain_name + "." + class_name) not in TYPES_WITH_OPEN_FIELD_LIST_SET
1070 validator_writer = generate_context.validator_writer
1072 validator_writer.newline("void %s%s::assertCorrectValue(JSONValue* value)\n" % (helper.full_name_prefix_for_impl, class_name))
1073 validator_writer.newline("{\n")
1074 validator_writer.newline(" RefPtr<JSONObject> object;\n")
1075 validator_writer.newline(" bool castRes = value->asObject(&object);\n")
1076 validator_writer.newline(" ASSERT_UNUSED(castRes, castRes);\n")
1077 for prop_data in resolve_data.main_properties:
1078 validator_writer.newline(" {\n")
1079 it_name = "%sPos" % prop_data.p["name"]
1080 validator_writer.newline(" JSONObject::iterator %s;\n" % it_name)
1081 validator_writer.newline(" %s = object->find(\"%s\");\n" % (it_name, prop_data.p["name"]))
1082 validator_writer.newline(" ASSERT(%s != object->end());\n" % it_name)
1083 validator_writer.newline(" %s(%s->value.get());\n" % (prop_data.param_type_binding.get_validator_call_text(), it_name))
1084 validator_writer.newline(" }\n")
1086 if closed_field_set:
1087 validator_writer.newline(" int foundPropertiesCount = %s;\n" % len(resolve_data.main_properties))
1089 for prop_data in resolve_data.optional_properties:
1090 validator_writer.newline(" {\n")
1091 it_name = "%sPos" % prop_data.p["name"]
1092 validator_writer.newline(" JSONObject::iterator %s;\n" % it_name)
1093 validator_writer.newline(" %s = object->find(\"%s\");\n" % (it_name, prop_data.p["name"]))
1094 validator_writer.newline(" if (%s != object->end()) {\n" % it_name)
1095 validator_writer.newline(" %s(%s->value.get());\n" % (prop_data.param_type_binding.get_validator_call_text(), it_name))
1096 if closed_field_set:
1097 validator_writer.newline(" ++foundPropertiesCount;\n")
1098 validator_writer.newline(" }\n")
1099 validator_writer.newline(" }\n")
1101 if closed_field_set:
1102 validator_writer.newline(" if (foundPropertiesCount != object->size()) {\n")
1103 validator_writer.newline(" FATAL(\"Unexpected properties in object: %s\\n\", object->toJSONString().ascii().data());\n")
1104 validator_writer.newline(" }\n")
1105 validator_writer.newline("}\n")
1107 validator_writer.newline("\n\n")
1110 cpp_writer = generate_context.cpp_writer
1112 writer.newline(" // Property names for type generated as open.\n")
1113 for prop_data in resolve_data.main_properties + resolve_data.optional_properties:
1114 prop_name = prop_data.p["name"]
1115 prop_field_name = Capitalizer.lower_camel_case_to_upper(prop_name)
1116 writer.newline(" static const char %s[];\n" % (prop_field_name))
1117 cpp_writer.newline("const char %s%s::%s[] = \"%s\";\n" % (helper.full_name_prefix_for_impl, class_name, prop_field_name, prop_name))
1120 writer.newline("};\n\n")
1123 def generate_forward_declaration(writer):
1124 class_name = fixed_type_name.class_name
1125 writer.newline("class ")
1126 writer.append(class_name)
1127 writer.append(";\n")
1130 def register_use(forward_listener):
1131 helper.add_to_forward_listener(forward_listener)
1134 def get_generate_pass_id():
1135 return TypeBuilderPass.MAIN
1137 return CodeGenerator
1140 def get_validator_call_text():
1141 return helper.full_name_prefix_for_use + fixed_type_name.class_name + "::assertCorrectValue"
1144 def get_array_item_c_type_text(cls):
1145 return helper.full_name_prefix_for_use + fixed_type_name.class_name
1148 def get_setter_value_expression_pattern():
1152 def reduce_to_raw_type():
1153 return RawTypes.Object
1156 def get_type_model():
1157 return TypeModel.RefPtrBased(helper.full_name_prefix_for_use + fixed_type_name.class_name)
1159 class AdHocTypeContextImpl:
1160 def __init__(self, property_name, class_name, resolve_context, ad_hoc_type_list, parent_full_name_prefix):
1161 self.property_name = property_name
1162 self.class_name = class_name
1163 self.resolve_context = resolve_context
1164 self.ad_hoc_type_list = ad_hoc_type_list
1165 self.container_full_name_prefix = parent_full_name_prefix + class_name + "::"
1166 self.container_relative_name_prefix = ""
1168 def get_type_name_fix(self):
1170 class_name = Capitalizer.lower_camel_case_to_upper(self.property_name)
1173 def output_comment(writer):
1174 writer.newline("// Named after property name '%s' while generating %s.\n" % (self.property_name, self.class_name))
1178 def add_type(self, binding):
1179 self.ad_hoc_type_list.append(binding)
1184 class PlainObjectBinding:
1186 def resolve_inner(cls, resolve_context):
1190 def request_user_runtime_cast(request):
1194 def request_internal_runtime_cast():
1198 def get_code_generator():
1202 def get_validator_call_text():
1203 return "RuntimeCastHelper::assertType<JSONValue::TypeObject>"
1206 def get_array_item_c_type_text(cls):
1207 return cls.reduce_to_raw_type().get_array_item_raw_c_type_text()
1210 def get_setter_value_expression_pattern():
1214 def reduce_to_raw_type():
1215 return RawTypes.Object
1218 def get_type_model():
1219 return TypeModel.Object
1221 return PlainObjectBinding
1222 elif json_typable["type"] == "array":
1223 if "items" in json_typable:
1227 class AdHocTypeContext:
1228 container_full_name_prefix = "<not yet defined>"
1229 container_relative_name_prefix = ""
1232 def get_type_name_fix():
1233 return fixed_type_name
1236 def add_type(binding):
1237 ad_hoc_types.append(binding)
1239 item_binding = resolve_param_type(json_typable["items"], context_domain_name, AdHocTypeContext)
1242 resolve_data_ = None
1243 need_internal_runtime_cast_ = False
1246 def resolve_inner(cls, resolve_context):
1247 if cls.resolve_data_:
1251 item_type_binding = item_binding
1252 ad_hoc_type_list = ad_hoc_types
1254 cls.resolve_data_ = ResolveData
1256 for t in ad_hoc_types:
1257 t.resolve_inner(resolve_context)
1260 def request_user_runtime_cast(cls, request):
1261 raise Exception("Not implemented yet")
1264 def request_internal_runtime_cast(cls):
1265 if cls.need_internal_runtime_cast_:
1267 cls.need_internal_runtime_cast_ = True
1268 cls.resolve_data_.item_type_binding.request_internal_runtime_cast()
1271 def get_code_generator(array_binding_cls):
1273 class CodeGenerator:
1275 def generate_type_builder(writer, generate_context):
1276 ad_hoc_type_writer = writer
1278 resolve_data = array_binding_cls.resolve_data_
1280 for ad_hoc_type in resolve_data.ad_hoc_type_list:
1281 code_generator = ad_hoc_type.get_code_generator()
1283 code_generator.generate_type_builder(ad_hoc_type_writer, generate_context)
1286 def generate_forward_declaration(writer):
1290 def register_use(forward_listener):
1291 item_code_generator = item_binding.get_code_generator()
1292 if item_code_generator:
1293 item_code_generator.register_use(forward_listener)
1296 def get_generate_pass_id():
1297 return TypeBuilderPass.MAIN
1299 return CodeGenerator
1302 def get_validator_call_text(cls):
1303 return cls.get_array_item_c_type_text() + "::assertCorrectValue"
1306 def get_array_item_c_type_text(cls):
1307 return replace_right_shift("TypeBuilder::Array<%s>" % cls.resolve_data_.item_type_binding.get_array_item_c_type_text())
1310 def get_setter_value_expression_pattern():
1314 def reduce_to_raw_type():
1315 return RawTypes.Array
1318 def get_type_model(cls):
1319 return TypeModel.RefPtrBased(cls.get_array_item_c_type_text())
1323 # Fall-through to raw type.
1326 raw_type = RawTypes.get(json_typable["type"])
1328 return RawTypeBinding(raw_type)
1331 class RawTypeBinding:
1332 def __init__(self, raw_type):
1333 self.raw_type_ = raw_type
1335 def resolve_inner(self, resolve_context):
1338 def request_user_runtime_cast(self, request):
1339 raise Exception("Unsupported")
1341 def request_internal_runtime_cast(self):
1344 def get_code_generator(self):
1347 def get_validator_call_text(self):
1348 return self.raw_type_.get_raw_validator_call_text()
1350 def get_array_item_c_type_text(self):
1351 return self.raw_type_.get_array_item_raw_c_type_text()
1353 def get_setter_value_expression_pattern(self):
1356 def reduce_to_raw_type(self):
1357 return self.raw_type_
1359 def get_type_model(self):
1360 return self.raw_type_.get_raw_type_model()
1363 class TypeData(object):
1364 def __init__(self, json_type, json_domain, domain_data):
1365 self.json_type_ = json_type
1366 self.json_domain_ = json_domain
1367 self.domain_data_ = domain_data
1369 if "type" not in json_type:
1370 raise Exception("Unknown type")
1372 json_type_name = json_type["type"]
1373 raw_type = RawTypes.get(json_type_name)
1374 self.raw_type_ = raw_type
1375 self.binding_being_resolved_ = False
1376 self.binding_ = None
1378 def get_raw_type(self):
1379 return self.raw_type_
1381 def get_binding(self):
1382 if not self.binding_:
1383 if self.binding_being_resolved_:
1384 raise Error("Type %s is already being resolved" % self.json_type_["type"])
1385 # Resolve only lazily, because resolving one named type may require resolving some other named type.
1386 self.binding_being_resolved_ = True
1388 self.binding_ = TypeBindings.create_named_type_declaration(self.json_type_, self.json_domain_["domain"], self)
1390 self.binding_being_resolved_ = False
1392 return self.binding_
1394 def get_json_type(self):
1395 return self.json_type_
1398 return self.json_type_["id"]
1400 def get_domain_name(self):
1401 return self.json_domain_["domain"]
1405 def __init__(self, json_domain):
1406 self.json_domain = json_domain
1409 def add_type(self, type_data):
1410 self.types_.append(type_data)
1413 return self.json_domain["domain"]
1420 def __init__(self, api):
1423 for json_domain in api["domains"]:
1424 domain_name = json_domain["domain"]
1427 self.map_[domain_name] = domain_map
1429 domain_data = DomainData(json_domain)
1430 self.domains_.append(domain_data)
1432 if "types" in json_domain:
1433 for json_type in json_domain["types"]:
1434 type_name = json_type["id"]
1435 type_data = TypeData(json_type, json_domain, domain_data)
1436 domain_map[type_name] = type_data
1437 domain_data.add_type(type_data)
1440 return self.domains_
1442 def get(self, domain_name, type_name):
1443 return self.map_[domain_name][type_name]
1446 def resolve_param_type(json_parameter, scope_domain_name, ad_hoc_type_context):
1447 if "$ref" in json_parameter:
1448 json_ref = json_parameter["$ref"]
1449 type_data = get_ref_data(json_ref, scope_domain_name)
1450 return type_data.get_binding()
1451 elif "type" in json_parameter:
1452 result = TypeBindings.create_ad_hoc_type_declaration(json_parameter, scope_domain_name, ad_hoc_type_context)
1453 ad_hoc_type_context.add_type(result)
1456 raise Exception("Unknown type")
1458 def resolve_param_raw_type(json_parameter, scope_domain_name):
1459 if "$ref" in json_parameter:
1460 json_ref = json_parameter["$ref"]
1461 type_data = get_ref_data(json_ref, scope_domain_name)
1462 return type_data.get_raw_type()
1463 elif "type" in json_parameter:
1464 json_type = json_parameter["type"]
1465 return RawTypes.get(json_type)
1467 raise Exception("Unknown type")
1470 def get_ref_data(json_ref, scope_domain_name):
1471 dot_pos = json_ref.find(".")
1473 domain_name = scope_domain_name
1474 type_name = json_ref
1476 domain_name = json_ref[:dot_pos]
1477 type_name = json_ref[dot_pos + 1:]
1479 return type_map.get(domain_name, type_name)
1482 input_file = open(input_json_filename, "r")
1483 json_string = input_file.read()
1484 json_api = json.loads(json_string)
1488 def get_this_script_path_(absolute_path):
1489 absolute_path = os.path.abspath(absolute_path)
1492 def fill_recursive(path_part, depth):
1493 if depth <= 0 or path_part == '/':
1495 fill_recursive(os.path.dirname(path_part), depth - 1)
1496 components.append(os.path.basename(path_part))
1498 # Typical path is /Source/WebCore/inspector/CodeGeneratorInspector.py
1499 # Let's take 4 components from the real path then.
1500 fill_recursive(absolute_path, 4)
1502 return "/".join(components)
1504 file_header_ = ("// File is generated by %s\n\n" % get_this_script_path_(sys.argv[0]) +
1505 """// Copyright (c) 2011 The Chromium Authors. All rights reserved.
1506 // Use of this source code is governed by a BSD-style license that can be
1507 // found in the LICENSE file.
1510 frontend_domain_class = string.Template(CodeGeneratorInspectorStrings.frontend_domain_class)
1511 backend_method = string.Template(CodeGeneratorInspectorStrings.backend_method)
1512 frontend_method = string.Template(CodeGeneratorInspectorStrings.frontend_method)
1513 callback_main_methods = string.Template(CodeGeneratorInspectorStrings.callback_main_methods)
1514 callback_failure_method = string.Template(CodeGeneratorInspectorStrings.callback_failure_method)
1515 frontend_h = string.Template(file_header_ + CodeGeneratorInspectorStrings.frontend_h)
1516 backend_h = string.Template(file_header_ + CodeGeneratorInspectorStrings.backend_h)
1517 backend_cpp = string.Template(file_header_ + CodeGeneratorInspectorStrings.backend_cpp)
1518 frontend_cpp = string.Template(file_header_ + CodeGeneratorInspectorStrings.frontend_cpp)
1519 typebuilder_h = string.Template(file_header_ + CodeGeneratorInspectorStrings.typebuilder_h)
1520 typebuilder_cpp = string.Template(file_header_ + CodeGeneratorInspectorStrings.typebuilder_cpp)
1521 param_container_access_code = CodeGeneratorInspectorStrings.param_container_access_code
1527 type_map = TypeMap(json_api)
1530 class NeedRuntimeCastRequest:
1534 def acknowledge(self):
1537 def is_acknowledged(self):
1541 def resolve_all_types():
1542 runtime_cast_generate_requests = {}
1543 for type_name in TYPES_WITH_RUNTIME_CAST_SET:
1544 runtime_cast_generate_requests[type_name] = NeedRuntimeCastRequest()
1546 class ForwardListener:
1547 type_data_set = set()
1548 already_declared_set = set()
1551 def add_type_data(cls, type_data):
1552 if type_data not in cls.already_declared_set:
1553 cls.type_data_set.add(type_data)
1555 class ResolveContext:
1556 forward_listener = ForwardListener
1558 for domain_data in type_map.domains():
1559 for type_data in domain_data.types():
1560 # Do not generate forwards for this type any longer.
1561 ForwardListener.already_declared_set.add(type_data)
1563 binding = type_data.get_binding()
1564 binding.resolve_inner(ResolveContext)
1566 for domain_data in type_map.domains():
1567 for type_data in domain_data.types():
1568 full_type_name = "%s.%s" % (type_data.get_domain_name(), type_data.get_name())
1569 request = runtime_cast_generate_requests.pop(full_type_name, None)
1570 binding = type_data.get_binding()
1572 binding.request_user_runtime_cast(request)
1574 if request and not request.is_acknowledged():
1575 raise Exception("Failed to generate runtimeCast in " + full_type_name)
1577 for full_type_name in runtime_cast_generate_requests:
1578 raise Exception("Failed to generate runtimeCast. Type " + full_type_name + " not found")
1580 return ForwardListener
1583 global_forward_listener = resolve_all_types()
1586 def get_annotated_type_text(raw_type, annotated_type):
1587 if annotated_type != raw_type:
1588 return "/*%s*/ %s" % (annotated_type, raw_type)
1593 def format_setter_value_expression(param_type_binding, value_ref):
1594 pattern = param_type_binding.get_setter_value_expression_pattern()
1596 return pattern % value_ref
1601 frontend_class_field_lines = []
1602 frontend_domain_class_lines = []
1604 method_name_enum_list = []
1605 backend_method_declaration_list = []
1606 backend_method_implementation_list = []
1607 backend_method_name_declaration_list = []
1608 backend_method_name_declaration_index_list = []
1609 backend_method_name_declaration_current_index = 0
1610 method_handler_list = []
1611 frontend_method_list = []
1613 backend_virtual_setters_list = []
1614 backend_agent_interface_list = []
1615 backend_setters_list = []
1616 backend_constructor_init_list = []
1617 backend_field_list = []
1618 frontend_constructor_init_list = []
1619 type_builder_fragments = []
1620 type_builder_forwards = []
1621 validator_impl_list = []
1622 type_builder_impl_list = []
1627 Generator.process_types(type_map)
1629 for json_domain in json_api["domains"]:
1630 domain_name = json_domain["domain"]
1631 domain_name_lower = domain_name.lower()
1633 agent_field_name = DomainNameFixes.get_fixed_data(domain_name)
1635 frontend_method_declaration_lines = []
1637 if "events" in json_domain:
1638 for json_event in json_domain["events"]:
1639 Generator.process_event(json_event, domain_name, frontend_method_declaration_lines)
1641 Generator.frontend_class_field_lines.append(" %s m_%s;\n" % (domain_name, domain_name_lower))
1642 if Generator.frontend_constructor_init_list:
1643 Generator.frontend_constructor_init_list.append(" , ")
1644 Generator.frontend_constructor_init_list.append("m_%s(inspectorFrontendChannel)\n" % domain_name_lower)
1645 Generator.frontend_domain_class_lines.append(Templates.frontend_domain_class.substitute(None,
1646 domainClassName=domain_name,
1647 domainFieldName=domain_name_lower,
1648 frontendDomainMethodDeclarations="".join(flatten_list(frontend_method_declaration_lines))))
1650 agent_interface_name = Capitalizer.lower_camel_case_to_upper(domain_name) + "CommandHandler"
1651 Generator.backend_agent_interface_list.append(" class %s {\n" % agent_interface_name)
1652 Generator.backend_agent_interface_list.append(" public:\n")
1653 if "commands" in json_domain:
1654 for json_command in json_domain["commands"]:
1655 Generator.process_command(json_command, domain_name, agent_field_name, agent_interface_name)
1656 Generator.backend_agent_interface_list.append("\n protected:\n")
1657 Generator.backend_agent_interface_list.append(" virtual ~%s() { }\n" % agent_interface_name)
1658 Generator.backend_agent_interface_list.append(" };\n\n")
1660 Generator.backend_constructor_init_list.append(" , m_%s(0)" % agent_field_name)
1661 Generator.backend_virtual_setters_list.append(" virtual void registerAgent(%s* %s) = 0;" % (agent_interface_name, agent_field_name))
1662 Generator.backend_setters_list.append(" virtual void registerAgent(%s* %s) { ASSERT(!m_%s); m_%s = %s; }" % (agent_interface_name, agent_field_name, agent_field_name, agent_field_name, agent_field_name))
1663 Generator.backend_field_list.append(" %s* m_%s;" % (agent_interface_name, agent_field_name))
1666 def process_event(json_event, domain_name, frontend_method_declaration_lines):
1667 if (("handlers" in json_event) and (not ("renderer" in json_event["handlers"]))):
1670 event_name = json_event["name"]
1672 ad_hoc_type_output = []
1673 frontend_method_declaration_lines.append(ad_hoc_type_output)
1674 ad_hoc_type_writer = Writer(ad_hoc_type_output, " ")
1676 decl_parameter_list = []
1678 json_parameters = json_event.get("parameters")
1679 Generator.generate_send_method(json_parameters, event_name, domain_name, ad_hoc_type_writer,
1680 decl_parameter_list,
1681 Generator.EventMethodStructTemplate,
1682 Generator.frontend_method_list, Templates.frontend_method, {"eventName": event_name})
1684 frontend_method_declaration_lines.append(
1685 " void %s(%s);\n" % (event_name, ", ".join(decl_parameter_list)))
1687 class EventMethodStructTemplate:
1689 def append_prolog(line_list):
1690 line_list.append(" RefPtr<JSONObject> paramsObject = JSONObject::create();\n")
1693 def append_epilog(line_list):
1694 line_list.append(" jsonMessage->setObject(\"params\", paramsObject);\n")
1696 container_name = "paramsObject"
1699 def process_command(json_command, domain_name, agent_field_name, agent_interface_name):
1700 if (("handlers" in json_command) and (not ("renderer" in json_command["handlers"]))):
1703 json_command_name = json_command["name"]
1705 cmd_enum_name = "k%s_%sCmd" % (domain_name, json_command["name"])
1707 Generator.method_name_enum_list.append(" %s," % cmd_enum_name)
1708 Generator.method_handler_list.append(" &InspectorBackendDispatcherImpl::%s_%s," % (domain_name, json_command_name))
1709 Generator.backend_method_declaration_list.append(" void %s_%s(long callId, JSONObject* requestMessageObject, JSONArray* protocolErrors);" % (domain_name, json_command_name))
1711 backend_agent_interface_list = [] if "redirect" in json_command else Generator.backend_agent_interface_list
1713 ad_hoc_type_output = []
1714 backend_agent_interface_list.append(ad_hoc_type_output)
1715 ad_hoc_type_writer = Writer(ad_hoc_type_output, " ")
1717 backend_agent_interface_list.append(" virtual void %s(ErrorString*" % json_command_name)
1720 method_out_code = ""
1721 agent_call_param_list = ["&error"]
1722 agent_call_params_declaration_list = [" ErrorString error;"]
1723 send_response_call_params_list = ["error"]
1724 request_message_param = ""
1725 normal_response_cook_text = ""
1726 error_type_binding = None
1727 if "error" in json_command:
1728 json_error = json_command["error"]
1729 error_type_binding = Generator.resolve_type_and_generate_ad_hoc(json_error, json_command_name + "Error", json_command_name, domain_name, ad_hoc_type_writer, agent_interface_name + "::")
1730 error_type_model = error_type_binding.get_type_model().get_optional()
1731 error_annotated_type = error_type_model.get_command_return_pass_model().get_output_parameter_type()
1732 agent_call_param_list.append("%serrorData" % error_type_model.get_command_return_pass_model().get_output_argument_prefix())
1733 backend_agent_interface_list.append(", %s errorData" % error_annotated_type)
1734 method_in_code += " %s errorData;\n" % error_type_model.get_command_return_pass_model().get_return_var_type()
1735 send_response_call_params_list.append("errorData")
1737 if "parameters" in json_command:
1738 json_params = json_command["parameters"]
1739 request_message_param = " requestMessageObject"
1742 method_in_code += Templates.param_container_access_code
1744 for json_parameter in json_params:
1745 json_param_name = json_parameter["name"]
1746 param_raw_type = resolve_param_raw_type(json_parameter, domain_name)
1748 getter_name = param_raw_type.get_getter_name()
1750 optional = json_parameter.get("optional")
1752 non_optional_type_model = param_raw_type.get_raw_type_model()
1755 code = (" bool %s_valueFound = false;\n"
1756 " %s in_%s = get%s(paramsContainerPtr, \"%s\", &%s_valueFound, protocolErrors);\n" %
1757 (json_param_name, non_optional_type_model.get_command_return_pass_model().get_return_var_type(), json_param_name, getter_name, json_param_name, json_param_name))
1758 param = "%s_valueFound ? &in_%s : 0" % (json_param_name, json_param_name)
1759 # FIXME: pass optional refptr-values as PassRefPtr
1760 formal_param_type_pattern = "const %s*"
1762 code = (" %s in_%s = get%s(paramsContainerPtr, \"%s\", 0, protocolErrors);\n" %
1763 (non_optional_type_model.get_command_return_pass_model().get_return_var_type(), json_param_name, getter_name, json_param_name))
1764 param = "in_%s" % json_param_name
1765 # FIXME: pass not-optional refptr-values as NonNullPassRefPtr
1766 if param_raw_type.is_heavy_value():
1767 formal_param_type_pattern = "const %s&"
1769 formal_param_type_pattern = "%s"
1771 method_in_code += code
1772 agent_call_param_list.append(param)
1773 backend_agent_interface_list.append(", %s in_%s" % (formal_param_type_pattern % non_optional_type_model.get_command_return_pass_model().get_return_var_type(), json_param_name))
1775 if json_command.get("async") == True:
1776 callback_name = Capitalizer.lower_camel_case_to_upper(json_command_name) + "Callback"
1778 callback_output = []
1779 callback_writer = Writer(callback_output, ad_hoc_type_writer.get_indent())
1781 decl_parameter_list = []
1782 Generator.generate_send_method(json_command.get("returns"), json_command_name, domain_name, ad_hoc_type_writer,
1783 decl_parameter_list,
1784 Generator.CallbackMethodStructTemplate,
1785 Generator.backend_method_implementation_list, Templates.callback_main_methods,
1786 {"callbackName": callback_name, "agentName": agent_interface_name})
1788 callback_writer.newline("class " + callback_name + " : public CallbackBase {\n")
1789 callback_writer.newline("public:\n")
1790 callback_writer.newline(" " + callback_name + "(PassRefPtrWillBeRawPtr<InspectorBackendDispatcherImpl>, int id);\n")
1791 callback_writer.newline(" void sendSuccess(" + ", ".join(decl_parameter_list) + ");\n")
1792 error_part_writer = callback_writer.insert_writer("")
1793 callback_writer.newline("};\n")
1795 if error_type_binding:
1796 annotated_type = error_type_model.get_input_param_type_text()
1797 error_part_writer.newline(" void sendFailure(const ErrorString&, %s);\n" % annotated_type)
1798 error_part_writer.newline(" using CallbackBase::sendFailure;\n")
1800 assigment_value = error_type_model.get_event_setter_expression_pattern() % "errorData"
1801 assigment_value = error_type_binding.reduce_to_raw_type().get_constructor_pattern() % assigment_value
1803 Generator.backend_method_implementation_list.append(Templates.callback_failure_method.substitute(None,
1804 agentName=agent_interface_name,
1805 callbackName=callback_name,
1806 parameter=annotated_type + " errorData",
1807 argument=assigment_value))
1809 ad_hoc_type_output.append(callback_output)
1811 method_out_code += " RefPtrWillBeRawPtr<" + agent_interface_name + "::" + callback_name + "> callback = adoptRefWillBeNoop(new " + agent_interface_name + "::" + callback_name + "(this, callId));\n"
1812 agent_call_param_list.append("callback")
1813 normal_response_cook_text += " if (!error.length()) \n"
1814 normal_response_cook_text += " return;\n"
1815 normal_response_cook_text += " callback->disable();\n"
1816 backend_agent_interface_list.append(", PassRefPtrWillBeRawPtr<%s> callback" % callback_name)
1818 if "returns" in json_command:
1819 method_out_code += "\n"
1820 agent_call_params_declaration_list.append(" RefPtr<JSONObject> result = JSONObject::create();")
1821 send_response_call_params_list.append("result")
1822 response_cook_list = []
1823 for json_return in json_command["returns"]:
1825 json_return_name = json_return["name"]
1827 optional = bool(json_return.get("optional"))
1829 return_type_binding = Generator.resolve_param_type_and_generate_ad_hoc(json_return, json_command_name, domain_name, ad_hoc_type_writer, agent_interface_name + "::")
1831 raw_type = return_type_binding.reduce_to_raw_type()
1832 setter_type = raw_type.get_setter_name()
1834 type_model = return_type_binding.get_type_model()
1836 type_model = type_model.get_optional()
1838 code = " %s out_%s;\n" % (type_model.get_command_return_pass_model().get_return_var_type(), json_return_name)
1839 param = "%sout_%s" % (type_model.get_command_return_pass_model().get_output_argument_prefix(), json_return_name)
1840 var_name = "out_%s" % json_return_name
1841 setter_argument = type_model.get_command_return_pass_model().get_output_to_raw_expression() % var_name
1842 if return_type_binding.get_setter_value_expression_pattern():
1843 setter_argument = return_type_binding.get_setter_value_expression_pattern() % setter_argument
1845 cook = " result->set%s(\"%s\", %s);\n" % (setter_type, json_return_name,
1848 set_condition_pattern = type_model.get_command_return_pass_model().get_set_return_condition()
1849 if set_condition_pattern:
1850 cook = (" if (%s)\n " % (set_condition_pattern % var_name)) + cook
1851 annotated_type = type_model.get_command_return_pass_model().get_output_parameter_type()
1853 param_name = var_name
1855 param_name = "opt_" + param_name
1857 backend_agent_interface_list.append(", %s %s" % (annotated_type, param_name))
1858 response_cook_list.append(cook)
1860 method_out_code += code
1861 agent_call_param_list.append(param)
1863 normal_response_cook_text += "".join(response_cook_list)
1865 if len(normal_response_cook_text) != 0:
1866 normal_response_cook_text = " if (!error.length()) {\n" + normal_response_cook_text + " }"
1868 # Redirect to another agent's implementation.
1869 agent_field = "m_" + agent_field_name
1870 if "redirect" in json_command:
1871 agent_field = "m_" + DomainNameFixes.get_fixed_data(json_command.get("redirect"))
1873 Generator.backend_method_implementation_list.append(Templates.backend_method.substitute(None,
1874 domainName=domain_name, methodName=json_command_name,
1875 agentField=agent_field,
1876 methodCode="".join([method_in_code, method_out_code]),
1877 agentCallParamsDeclaration="\n".join(agent_call_params_declaration_list),
1878 agentCallParams=", ".join(agent_call_param_list),
1879 requestMessageObject=request_message_param,
1880 responseCook=normal_response_cook_text,
1881 sendResponseCallParams=", ".join(send_response_call_params_list),
1882 commandNameIndex=cmd_enum_name))
1883 declaration_command_name = "%s.%s\\0" % (domain_name, json_command_name)
1884 Generator.backend_method_name_declaration_list.append(" \"%s\"" % declaration_command_name)
1885 Generator.backend_method_name_declaration_index_list.append(" %d," % Generator.backend_method_name_declaration_current_index)
1886 Generator.backend_method_name_declaration_current_index += len(declaration_command_name) - 1
1888 backend_agent_interface_list.append(") = 0;\n")
1890 class CallbackMethodStructTemplate:
1892 def append_prolog(line_list):
1896 def append_epilog(line_list):
1899 container_name = "jsonMessage"
1901 # Generates common code for event sending and callback response data sending.
1903 def generate_send_method(parameters, event_name, domain_name, ad_hoc_type_writer, decl_parameter_list,
1904 method_struct_template,
1905 generator_method_list, method_template, template_params):
1906 method_line_list = []
1908 method_struct_template.append_prolog(method_line_list)
1909 for json_parameter in parameters:
1910 parameter_name = json_parameter["name"]
1912 param_type_binding = Generator.resolve_param_type_and_generate_ad_hoc(json_parameter, event_name, domain_name, ad_hoc_type_writer, "")
1914 raw_type = param_type_binding.reduce_to_raw_type()
1915 raw_type_binding = RawTypeBinding(raw_type)
1917 optional = bool(json_parameter.get("optional"))
1919 setter_type = raw_type.get_setter_name()
1921 type_model = param_type_binding.get_type_model()
1922 raw_type_model = raw_type_binding.get_type_model()
1924 type_model = type_model.get_optional()
1925 raw_type_model = raw_type_model.get_optional()
1927 annotated_type = type_model.get_input_param_type_text()
1928 mode_type_binding = param_type_binding
1930 decl_parameter_list.append("%s %s" % (annotated_type, parameter_name))
1932 setter_argument = raw_type_model.get_event_setter_expression_pattern() % parameter_name
1933 if mode_type_binding.get_setter_value_expression_pattern():
1934 setter_argument = mode_type_binding.get_setter_value_expression_pattern() % setter_argument
1936 setter_code = " %s->set%s(\"%s\", %s);\n" % (method_struct_template.container_name, setter_type, parameter_name, setter_argument)
1938 setter_code = (" if (%s)\n " % parameter_name) + setter_code
1939 method_line_list.append(setter_code)
1941 method_struct_template.append_epilog(method_line_list)
1943 generator_method_list.append(method_template.substitute(None,
1944 domainName=domain_name,
1945 parameters=", ".join(decl_parameter_list),
1946 code="".join(method_line_list), **template_params))
1949 def resolve_param_type_and_generate_ad_hoc(cls, json_param, method_name, domain_name, ad_hoc_type_writer, container_relative_name_prefix_param):
1950 param_name = json_param["name"]
1951 return cls.resolve_type_and_generate_ad_hoc(json_param, param_name, method_name, domain_name, ad_hoc_type_writer, container_relative_name_prefix_param)
1954 def resolve_type_and_generate_ad_hoc(typable_element, element_name, method_name, domain_name, ad_hoc_type_writer, container_relative_name_prefix_param):
1955 ad_hoc_type_list = []
1957 class AdHocTypeContext:
1958 container_full_name_prefix = "<not yet defined>"
1959 container_relative_name_prefix = container_relative_name_prefix_param
1962 def get_type_name_fix():
1964 class_name = Capitalizer.lower_camel_case_to_upper(element_name)
1967 def output_comment(writer):
1968 writer.newline("// Named after parameter '%s' while generating command/event %s.\n" % (element_name, method_name))
1973 def add_type(binding):
1974 ad_hoc_type_list.append(binding)
1976 type_binding = resolve_param_type(typable_element, domain_name, AdHocTypeContext)
1978 class InterfaceForwardListener:
1980 def add_type_data(type_data):
1983 class InterfaceResolveContext:
1984 forward_listener = InterfaceForwardListener
1986 for type in ad_hoc_type_list:
1987 type.resolve_inner(InterfaceResolveContext)
1989 class InterfaceGenerateContext:
1990 validator_writer = "not supported in InterfaceGenerateContext"
1991 cpp_writer = validator_writer
1993 for type in ad_hoc_type_list:
1994 generator = type.get_code_generator()
1996 generator.generate_type_builder(ad_hoc_type_writer, InterfaceGenerateContext)
2001 def process_types(type_map):
2002 output = Generator.type_builder_fragments
2004 class GenerateContext:
2005 validator_writer = Writer(Generator.validator_impl_list, "")
2006 cpp_writer = Writer(Generator.type_builder_impl_list, "")
2008 def generate_all_domains_code(out, type_data_callback):
2009 writer = Writer(out, "")
2010 for domain_data in type_map.domains():
2011 namespace_declared = []
2013 def namespace_lazy_generator():
2014 if not namespace_declared:
2015 writer.newline("namespace ")
2016 writer.append(domain_data.name())
2017 writer.append(" {\n")
2018 # What is a better way to change value from outer scope?
2019 namespace_declared.append(True)
2022 for type_data in domain_data.types():
2023 type_data_callback(type_data, namespace_lazy_generator)
2025 if namespace_declared:
2026 writer.append("} // ")
2027 writer.append(domain_data.name())
2028 writer.append("\n\n")
2030 def create_type_builder_caller(generate_pass_id):
2031 def call_type_builder(type_data, writer_getter):
2032 code_generator = type_data.get_binding().get_code_generator()
2033 if code_generator and generate_pass_id == code_generator.get_generate_pass_id():
2034 writer = writer_getter()
2036 code_generator.generate_type_builder(writer, GenerateContext)
2037 return call_type_builder
2039 generate_all_domains_code(output, create_type_builder_caller(TypeBuilderPass.MAIN))
2041 Generator.type_builder_forwards.append("// Forward declarations.\n")
2043 def generate_forward_callback(type_data, writer_getter):
2044 if type_data in global_forward_listener.type_data_set:
2045 binding = type_data.get_binding()
2046 binding.get_code_generator().generate_forward_declaration(writer_getter())
2047 generate_all_domains_code(Generator.type_builder_forwards, generate_forward_callback)
2049 Generator.type_builder_forwards.append("// End of forward declarations.\n\n")
2051 Generator.type_builder_forwards.append("// Typedefs.\n")
2053 generate_all_domains_code(Generator.type_builder_forwards, create_type_builder_caller(TypeBuilderPass.TYPEDEF))
2055 Generator.type_builder_forwards.append("// End of typedefs.\n\n")
2058 def flatten_list(input):
2061 def fill_recursive(l):
2063 if isinstance(item, list):
2064 fill_recursive(item)
2067 fill_recursive(input)
2070 def output_file(file_name):
2071 return open(file_name, "w")
2076 backend_h_file = output_file(output_dirname + "/InspectorBackendDispatcher.h")
2077 backend_cpp_file = output_file(output_dirname + "/InspectorBackendDispatcher.cpp")
2079 frontend_h_file = output_file(output_dirname + "/InspectorFrontend.h")
2080 frontend_cpp_file = output_file(output_dirname + "/InspectorFrontend.cpp")
2082 typebuilder_h_file = output_file(output_dirname + "/InspectorTypeBuilder.h")
2083 typebuilder_cpp_file = output_file(output_dirname + "/InspectorTypeBuilder.cpp")
2086 backend_h_file.write(Templates.backend_h.substitute(None,
2087 virtualSetters="\n".join(Generator.backend_virtual_setters_list),
2088 agentInterfaces="".join(flatten_list(Generator.backend_agent_interface_list)),
2089 methodNamesEnumContent="\n".join(Generator.method_name_enum_list)))
2091 backend_cpp_file.write(Templates.backend_cpp.substitute(None,
2092 constructorInit="\n".join(Generator.backend_constructor_init_list),
2093 setters="\n".join(Generator.backend_setters_list),
2094 fieldDeclarations="\n".join(Generator.backend_field_list),
2095 methodNameDeclarations="\n".join(Generator.backend_method_name_declaration_list),
2096 methodNameDeclarationsIndex="\n".join(Generator.backend_method_name_declaration_index_list),
2097 methods="\n".join(Generator.backend_method_implementation_list),
2098 methodDeclarations="\n".join(Generator.backend_method_declaration_list),
2099 messageHandlers="\n".join(Generator.method_handler_list)))
2101 frontend_h_file.write(Templates.frontend_h.substitute(None,
2102 fieldDeclarations="".join(Generator.frontend_class_field_lines),
2103 domainClassList="".join(Generator.frontend_domain_class_lines)))
2105 frontend_cpp_file.write(Templates.frontend_cpp.substitute(None,
2106 constructorInit="".join(Generator.frontend_constructor_init_list),
2107 methods="\n".join(Generator.frontend_method_list)))
2109 typebuilder_h_file.write(Templates.typebuilder_h.substitute(None,
2110 typeBuilders="".join(flatten_list(Generator.type_builder_fragments)),
2111 forwards="".join(Generator.type_builder_forwards),
2112 validatorIfdefName=VALIDATOR_IFDEF_NAME))
2114 typebuilder_cpp_file.write(Templates.typebuilder_cpp.substitute(None,
2115 enumConstantValues=EnumConstants.get_enum_constant_code(),
2116 implCode="".join(flatten_list(Generator.type_builder_impl_list)),
2117 validatorCode="".join(flatten_list(Generator.validator_impl_list)),
2118 validatorIfdefName=VALIDATOR_IFDEF_NAME))
2120 backend_h_file.close()
2121 backend_cpp_file.close()
2123 frontend_h_file.close()
2124 frontend_cpp_file.close()
2126 typebuilder_h_file.close()
2127 typebuilder_cpp_file.close()