2 # Copyright (c) 2011 Google Inc. All rights reserved.
3 # Copyright (c) 2012 Intel Corporation. All rights reserved.
4 # Copyright (c) 2013 Apple Inc. All Rights Reserved.
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions are
10 # * Redistributions of source code must retain the above copyright
11 # notice, this list of conditions and the following disclaimer.
12 # * Redistributions in binary form must reproduce the above
13 # copyright notice, this list of conditions and the following disclaimer
14 # in the documentation and/or other materials provided with the
16 # * Neither the name of Google Inc. nor the names of its
17 # contributors may be used to endorse or promote products derived from
18 # this software without specific prior written permission.
20 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 import simplejson
as json
42 import CodeGeneratorInspectorStrings
45 DOMAIN_DEFINE_NAME_MAP
= {
46 "Database": "SQL_DATABASE",
47 "IndexedDB": "INDEXED_DATABASE",
48 "Replay": "WEB_REPLAY",
52 # Manually-filled map of type name replacements.
54 "RGBA": "Rgba", # RGBA is reported to be conflicting with a define name in Windows CE.
59 TYPES_WITH_RUNTIME_CAST_SET
= frozenset(["Runtime.RemoteObject", "Runtime.PropertyDescriptor", "Runtime.InternalPropertyDescriptor",
60 "Debugger.FunctionDetails", "Debugger.CallFrame",
61 "Canvas.TraceLog", "Canvas.ResourceInfo", "Canvas.ResourceState",
62 # This should be a temporary hack. TimelineEvent should be created via generated C++ API.
63 "Timeline.TimelineEvent"])
65 TYPES_WITH_OPEN_FIELD_LIST_SET
= frozenset(["Timeline.TimelineEvent",
66 # InspectorStyleSheet not only creates this property but wants to read it and modify it.
68 # InspectorResourceAgent needs to update mime-type.
71 EXACTLY_INT_SUPPORTED
= False
73 INSPECTOR_TYPES_GENERATOR_CONFIG_MAP
= {
76 "typebuilder_dependency": "",
77 "export_macro": "JS_EXPORT_PRIVATE",
81 "typebuilder_dependency": "#include <inspector/InspectorJSTypeBuilders.h>",
86 cmdline_parser
= optparse
.OptionParser(usage
="usage: %prog [options] <Inspector.json>")
87 cmdline_parser
.add_option("--output_h_dir")
88 cmdline_parser
.add_option("--output_cpp_dir")
89 cmdline_parser
.add_option("--output_js_dir")
90 cmdline_parser
.add_option("--output_type") # JavaScript, Web
91 cmdline_parser
.add_option("--write_always", action
="store_true")
92 cmdline_parser
.add_option("--no_verification", action
="store_true")
95 arg_options
, arg_values
= cmdline_parser
.parse_args()
96 if (len(arg_values
) < 1):
97 raise Exception("At least one plain argument expected")
99 input_json_filename
= arg_values
[0]
100 dependency_json_filenames
= arg_values
[1:]
102 output_header_dirname
= arg_options
.output_h_dir
103 output_cpp_dirname
= arg_options
.output_cpp_dir
104 output_js_dirname
= arg_options
.output_js_dir
105 output_type
= arg_options
.output_type
107 write_always
= arg_options
.write_always
108 verification
= not arg_options
.no_verification
109 if not output_header_dirname
:
110 raise Exception("Output .h directory must be specified")
111 if not output_cpp_dirname
:
112 raise Exception("Output .cpp directory must be specified")
113 if not output_js_dirname
:
114 raise Exception("Output .js directory must be specified")
115 if output_type
not in INSPECTOR_TYPES_GENERATOR_CONFIG_MAP
.keys():
116 raise Exception("Unknown output type. Allowed types are: %s" % INSPECTOR_TYPES_GENERATOR_CONFIG_MAP
.keys())
118 # Work with python 2 and 3 http://docs.python.org/py3k/howto/pyporting.html
119 exc
= sys
.exc_info()[1]
120 sys
.stderr
.write("Failed to parse command-line arguments: %s\n\n" % exc
)
121 sys
.stderr
.write("Usage: <script> Inspector.json --output_h_dir <output_header_dir> --output_cpp_dir <output_cpp_dir> --output_js_dir <output_js_dir> [--write_always] [--no_verification]\n")
125 def dash_to_camelcase(word
):
126 return ''.join(x
.capitalize() or '-' for x
in word
.split('-'))
129 def fix_camel_case(name
):
130 refined
= re
.sub(r
'-(\w)', lambda pat
: pat
.group(1).upper(), name
)
131 refined
= to_title_case(refined
)
132 return re
.sub(r
'(?i)HTML|XML|WML|API|GC|XHR|DOM|CSS', lambda pat
: pat
.group(0).upper(), refined
)
135 def to_title_case(name
):
136 return name
[:1].upper() + name
[1:]
141 def lower_camel_case_to_upper(str):
142 if len(str) > 0 and str[0].islower():
143 str = str[0].upper() + str[1:]
147 def upper_camel_case_to_lower(str):
149 while pos
< len(str) and str[pos
].isupper():
154 return str[0].lower() + str[1:]
157 possible_abbreviation
= str[0:pos
]
158 if possible_abbreviation
not in Capitalizer
.ABBREVIATION
:
159 raise Exception("Unknown abbreviation %s" % possible_abbreviation
)
160 str = possible_abbreviation
.lower() + str[pos
:]
164 def camel_case_to_capitalized_with_underscores(str):
167 output
= Capitalizer
.split_camel_case_(str)
168 return "_".join(output
).upper()
171 def split_camel_case_(str):
175 has_oneletter
= False
176 while pos
< len(str):
177 if str[pos
].isupper():
178 output
.append(str[pos_being
:pos
].upper())
179 if pos
- pos_being
== 1:
183 output
.append(str[pos_being
:])
186 while array_pos
< len(output
) - 1:
187 if len(output
[array_pos
]) == 1:
188 array_pos_end
= array_pos
+ 1
189 while array_pos_end
< len(output
) and len(output
[array_pos_end
]) == 1:
191 if array_pos_end
- array_pos
> 1:
192 possible_abbreviation
= "".join(output
[array_pos
:array_pos_end
])
193 if possible_abbreviation
.upper() in Capitalizer
.ABBREVIATION
:
194 output
[array_pos
:array_pos_end
] = [possible_abbreviation
]
196 array_pos
= array_pos_end
- 1
200 ABBREVIATION
= frozenset(["XHR", "DOM", "CSS"])
202 VALIDATOR_IFDEF_NAME
= "!ASSERT_DISABLED"
205 class DomainNameFixes
:
207 def get_fixed_data(cls
, domain_name
):
208 field_name_res
= Capitalizer
.upper_camel_case_to_lower(domain_name
) + "Agent"
211 skip_js_bind
= domain_name
in cls
.skip_js_bind_domains
215 if domain_name
in DOMAIN_DEFINE_NAME_MAP
:
216 define_name
= DOMAIN_DEFINE_NAME_MAP
[domain_name
]
220 def generate_open(output
):
221 output
.append("#if ENABLE(%s)\n" % define_name
)
224 def generate_close(output
):
225 output
.append("#endif // ENABLE(%s)\n" % define_name
)
231 skip_js_bind_domains
= set(["DOMDebugger"])
234 class RawTypes(object):
237 if json_type
== "boolean":
239 elif json_type
== "string":
240 return RawTypes
.String
241 elif json_type
== "array":
242 return RawTypes
.Array
243 elif json_type
== "object":
244 return RawTypes
.Object
245 elif json_type
== "integer":
247 elif json_type
== "number":
248 return RawTypes
.Number
249 elif json_type
== "any":
252 raise Exception("Unknown type: %s" % json_type
)
254 # For output parameter all values are passed by pointer except RefPtr-based types.
255 class OutputPassModel
:
258 def get_argument_prefix():
262 def get_parameter_type_suffix():
267 def get_argument_prefix():
271 def get_parameter_type_suffix():
274 class BaseType(object):
275 need_internal_runtime_cast_
= False
278 def request_raw_internal_runtime_cast(cls
):
279 if not cls
.need_internal_runtime_cast_
:
280 cls
.need_internal_runtime_cast_
= True
283 def get_raw_validator_call_text(cls
):
284 return "RuntimeCastHelper::assertType<Inspector::InspectorValue::Type%s>" % cls
.get_validate_method_params().template_type
286 class String(BaseType
):
288 def get_getter_name():
291 get_setter_name
= get_getter_name
294 def get_c_initializer():
298 def get_js_bind_type():
302 def get_validate_method_params():
303 class ValidateMethodParams
:
304 template_type
= "String"
305 return ValidateMethodParams
308 def get_output_pass_model():
309 return RawTypes
.OutputPassModel
.ByPointer
312 def is_heavy_value():
316 def get_array_item_raw_c_type_text():
320 def get_raw_type_model():
321 return TypeModel
.String
325 def get_getter_name():
329 def get_setter_name():
333 def get_c_initializer():
337 def get_js_bind_type():
341 def get_raw_validator_call_text(cls
):
342 return "RuntimeCastHelper::assertInt"
345 def get_output_pass_model():
346 return RawTypes
.OutputPassModel
.ByPointer
349 def is_heavy_value():
353 def get_array_item_raw_c_type_text():
357 def get_raw_type_model():
360 class Number(BaseType
):
362 def get_getter_name():
366 def get_setter_name():
370 def get_c_initializer():
374 def get_js_bind_type():
378 def get_validate_method_params():
379 class ValidateMethodParams
:
380 template_type
= "Number"
381 return ValidateMethodParams
384 def get_output_pass_model():
385 return RawTypes
.OutputPassModel
.ByPointer
388 def is_heavy_value():
392 def get_array_item_raw_c_type_text():
396 def get_raw_type_model():
397 return TypeModel
.Number
399 class Bool(BaseType
):
401 def get_getter_name():
404 get_setter_name
= get_getter_name
407 def get_c_initializer():
411 def get_js_bind_type():
415 def get_validate_method_params():
416 class ValidateMethodParams
:
417 template_type
= "Boolean"
418 return ValidateMethodParams
421 def get_output_pass_model():
422 return RawTypes
.OutputPassModel
.ByPointer
425 def is_heavy_value():
429 def get_array_item_raw_c_type_text():
433 def get_raw_type_model():
434 return TypeModel
.Bool
436 class Object(BaseType
):
438 def get_getter_name():
442 def get_setter_name():
446 def get_c_initializer():
447 return "InspectorObject::create()"
450 def get_js_bind_type():
454 def get_output_argument_prefix():
458 def get_validate_method_params():
459 class ValidateMethodParams
:
460 template_type
= "Object"
461 return ValidateMethodParams
464 def get_output_pass_model():
465 return RawTypes
.OutputPassModel
.ByReference
468 def is_heavy_value():
472 def get_array_item_raw_c_type_text():
473 return "Inspector::InspectorObject"
476 def get_raw_type_model():
477 return TypeModel
.Object
481 def get_getter_name():
484 get_setter_name
= get_getter_name
487 def get_c_initializer():
488 raise Exception("Unsupported")
491 def get_js_bind_type():
492 raise Exception("Unsupported")
495 def get_raw_validator_call_text():
496 return "RuntimeCastHelper::assertAny"
499 def get_output_pass_model():
500 return RawTypes
.OutputPassModel
.ByReference
503 def is_heavy_value():
507 def get_array_item_raw_c_type_text():
508 return "Inspector::InspectorValue"
511 def get_raw_type_model():
514 class Array(BaseType
):
516 def get_getter_name():
520 def get_setter_name():
524 def get_c_initializer():
525 return "InspectorArray::create()"
528 def get_js_bind_type():
532 def get_output_argument_prefix():
536 def get_validate_method_params():
537 class ValidateMethodParams
:
538 template_type
= "Array"
539 return ValidateMethodParams
542 def get_output_pass_model():
543 return RawTypes
.OutputPassModel
.ByReference
546 def is_heavy_value():
550 def get_array_item_raw_c_type_text():
551 return "Inspector::InspectorArray"
554 def get_raw_type_model():
555 return TypeModel
.Array
558 def replace_right_shift(input_str
):
559 return input_str
.replace(">>", "> >")
562 class CommandReturnPassModel
:
564 def __init__(self
, var_type
, set_condition
):
565 self
.var_type
= var_type
566 self
.set_condition
= set_condition
568 def get_return_var_type(self
):
572 def get_output_argument_prefix():
576 def get_output_to_raw_expression():
579 def get_output_parameter_type(self
):
580 return self
.var_type
+ "&"
582 def get_set_return_condition(self
):
583 return self
.set_condition
586 def __init__(self
, var_type
):
587 self
.var_type
= var_type
589 def get_return_var_type(self
):
593 def get_output_argument_prefix():
597 def get_output_to_raw_expression():
600 def get_output_parameter_type(self
):
601 return self
.var_type
+ "*"
604 def get_set_return_condition():
608 def __init__(self
, var_type
):
609 self
.var_type
= var_type
611 def get_return_var_type(self
):
612 return "Inspector::TypeBuilder::OptOutput<%s>" % self
.var_type
615 def get_output_argument_prefix():
619 def get_output_to_raw_expression():
620 return "%s.getValue()"
622 def get_output_parameter_type(self
):
623 return "Inspector::TypeBuilder::OptOutput<%s>*" % self
.var_type
626 def get_set_return_condition():
627 return "%s.isAssigned()"
631 class RefPtrBased(object):
632 def __init__(self
, class_name
):
633 self
.class_name
= class_name
634 self
.optional
= False
636 def get_optional(self
):
637 result
= TypeModel
.RefPtrBased(self
.class_name
)
638 result
.optional
= True
641 def get_command_return_pass_model(self
):
646 return CommandReturnPassModel
.ByReference(replace_right_shift("RefPtr<%s>" % self
.class_name
), set_condition
)
648 def get_input_param_type_text(self
):
649 return replace_right_shift("PassRefPtr<%s>" % self
.class_name
)
652 def get_event_setter_expression_pattern():
656 def __init__(self
, base_type_name
):
657 self
.type_name
= base_type_name
+ "::Enum"
659 def get_optional(base_self
):
662 def get_optional(cls
):
666 def get_command_return_pass_model():
667 return CommandReturnPassModel
.OptOutput(base_self
.type_name
)
670 def get_input_param_type_text():
671 return base_self
.type_name
+ "*"
674 def get_event_setter_expression_pattern():
675 raise Exception("TODO")
678 def get_command_return_pass_model(self
):
679 return CommandReturnPassModel
.ByPointer(self
.type_name
)
681 def get_input_param_type_text(self
):
682 return self
.type_name
685 def get_event_setter_expression_pattern():
688 class ValueType(object):
689 def __init__(self
, type_name
, is_heavy
):
690 self
.type_name
= type_name
691 self
.is_heavy
= is_heavy
693 def get_optional(self
):
694 return self
.ValueOptional(self
)
696 def get_command_return_pass_model(self
):
697 return CommandReturnPassModel
.ByPointer(self
.type_name
)
699 def get_input_param_type_text(self
):
701 return "const %s&" % self
.type_name
703 return self
.type_name
705 def get_opt_output_type_(self
):
706 return self
.type_name
709 def get_event_setter_expression_pattern():
713 def __init__(self
, base
):
716 def get_optional(self
):
719 def get_command_return_pass_model(self
):
720 return CommandReturnPassModel
.OptOutput(self
.base
.get_opt_output_type_())
722 def get_input_param_type_text(self
):
723 return "const %s* const" % self
.base
.type_name
726 def get_event_setter_expression_pattern():
729 class ExactlyInt(ValueType
):
731 TypeModel
.ValueType
.__init
__(self
, "int", False)
733 def get_input_param_type_text(self
):
734 return "Inspector::TypeBuilder::ExactlyInt"
736 def get_opt_output_type_(self
):
737 return "Inspector::TypeBuilder::ExactlyInt"
741 cls
.Bool
= cls
.ValueType("bool", False)
742 if EXACTLY_INT_SUPPORTED
:
743 cls
.Int
= cls
.ExactlyInt()
745 cls
.Int
= cls
.ValueType("int", False)
746 cls
.Number
= cls
.ValueType("double", False)
747 cls
.String
= cls
.ValueType("String", True,)
748 cls
.Object
= cls
.RefPtrBased("Inspector::InspectorObject")
749 cls
.Array
= cls
.RefPtrBased("Inspector::InspectorArray")
750 cls
.Any
= cls
.RefPtrBased("Inspector::InspectorValue")
752 TypeModel
.init_class()
755 # Collection of InspectorObject class methods that are likely to be overloaded in generated class.
756 # We must explicitly import all overloaded methods or they won't be available to user.
757 INSPECTOR_OBJECT_SETTER_NAMES
= frozenset(["setValue", "setBoolean", "setNumber", "setString", "setValue", "setObject", "setArray"])
760 def fix_type_name(json_name
):
761 if json_name
in TYPE_NAME_FIX_MAP
:
762 fixed
= TYPE_NAME_FIX_MAP
[json_name
]
764 class Result(object):
768 def output_comment(writer
):
769 writer
.newline("// Type originally was named '%s'.\n" % json_name
)
772 class Result(object):
773 class_name
= json_name
776 def output_comment(writer
):
783 def __init__(self
, output
, indent
):
787 def newline(self
, str):
789 self
.output
.append(self
.indent
)
790 self
.output
.append(str)
792 def append(self
, str):
793 self
.output
.append(str)
795 def newline_multiline(self
, str):
796 parts
= str.split('\n')
797 self
.newline(parts
[0])
799 self
.output
.append('\n')
803 def append_multiline(self
, str):
804 parts
= str.split('\n')
805 self
.append(parts
[0])
807 self
.output
.append('\n')
811 def get_indent(self
):
814 def get_indented(self
, additional_indent
):
815 return Writer(self
.output
, self
.indent
+ additional_indent
)
817 def insert_writer(self
, additional_indent
):
819 self
.output
.append(new_output
)
820 return Writer(new_output
, self
.indent
+ additional_indent
)
828 def add_constant(cls
, value
):
829 if value
in cls
.map_
:
830 return cls
.map_
[value
]
833 cls
.map_
[value
] = pos
834 cls
.constants_
.append(value
)
838 def get_enum_constant_code(cls
):
840 for item
in cls
.constants_
:
841 output
.append(" \"" + item
+ "\"")
842 return ",\n".join(output
) + "\n"
845 # Typebuilder code is generated in several passes: first typedefs, then other classes.
846 # Manual pass management is needed because we cannot have forward declarations for typedefs.
847 class TypeBuilderPass
:
854 def create_named_type_declaration(json_typable
, context_domain_name
, type_data
):
855 json_type
= type_data
.get_json_type()
859 full_name_prefix_for_use
= "Inspector::TypeBuilder::" + context_domain_name
+ "::"
860 full_name_prefix_for_impl
= "Inspector::TypeBuilder::" + context_domain_name
+ "::"
863 def write_doc(writer
):
864 if "description" in json_type
:
865 writer
.newline("/* ")
866 writer
.append(json_type
["description"])
867 writer
.append(" */\n")
870 def add_to_forward_listener(forward_listener
):
871 forward_listener
.add_type_data(type_data
)
874 fixed_type_name
= fix_type_name(json_type
["id"])
875 return TypeBindings
.create_type_declaration_(json_typable
, context_domain_name
, fixed_type_name
, Helper
)
878 def create_ad_hoc_type_declaration(json_typable
, context_domain_name
, ad_hoc_type_context
):
881 full_name_prefix_for_use
= ad_hoc_type_context
.container_relative_name_prefix
882 full_name_prefix_for_impl
= ad_hoc_type_context
.container_full_name_prefix
885 def write_doc(writer
):
889 def add_to_forward_listener(forward_listener
):
891 fixed_type_name
= ad_hoc_type_context
.get_type_name_fix()
892 return TypeBindings
.create_type_declaration_(json_typable
, context_domain_name
, fixed_type_name
, Helper
)
895 def create_type_declaration_(json_typable
, context_domain_name
, fixed_type_name
, helper
):
896 if json_typable
["type"] == "string":
897 if "enum" in json_typable
:
900 need_user_runtime_cast_
= False
901 need_internal_runtime_cast_
= False
904 def resolve_inner(cls
, resolve_context
):
908 def request_user_runtime_cast(cls
, request
):
910 cls
.need_user_runtime_cast_
= True
911 request
.acknowledge()
914 def request_internal_runtime_cast(cls
):
915 cls
.need_internal_runtime_cast_
= True
918 def get_code_generator(enum_binding_cls
):
919 #FIXME: generate ad-hoc enums too once we figure out how to better implement them in C++.
920 comment_out
= helper
.is_ad_hoc
924 def generate_type_builder(writer
, generate_context
):
925 enum
= json_typable
["enum"]
926 helper
.write_doc(writer
)
927 enum_name
= fixed_type_name
.class_name
928 fixed_type_name
.output_comment(writer
)
929 writer
.newline("struct ")
930 writer
.append(enum_name
)
931 writer
.append(" {\n")
932 writer
.newline(" enum Enum {\n")
933 for enum_item
in enum
:
934 enum_pos
= EnumConstants
.add_constant(enum_item
)
936 item_c_name
= fix_camel_case(enum_item
)
937 if item_c_name
in TYPE_NAME_FIX_MAP
:
938 item_c_name
= TYPE_NAME_FIX_MAP
[item_c_name
]
940 writer
.append(item_c_name
)
942 writer
.append("%s" % enum_pos
)
944 writer
.newline(" };\n")
945 if enum_binding_cls
.need_user_runtime_cast_
:
946 raise Exception("Not yet implemented")
948 if enum_binding_cls
.need_internal_runtime_cast_
:
949 writer
.append("#if %s\n" % VALIDATOR_IFDEF_NAME
)
950 writer
.newline(" static void assertCorrectValue(Inspector::InspectorValue* value);\n")
951 writer
.append("#endif // %s\n" % VALIDATOR_IFDEF_NAME
)
953 validator_writer
= generate_context
.validator_writer
955 domain_fixes
= DomainNameFixes
.get_fixed_data(context_domain_name
)
956 domain_guard
= domain_fixes
.get_guard()
958 domain_guard
.generate_open(validator_writer
)
960 validator_writer
.newline("void %s%s::assertCorrectValue(Inspector::InspectorValue* value)\n" % (helper
.full_name_prefix_for_impl
, enum_name
))
961 validator_writer
.newline("{\n")
962 validator_writer
.newline(" WTF::String s;\n")
963 validator_writer
.newline(" bool cast_res = value->asString(&s);\n")
964 validator_writer
.newline(" ASSERT(cast_res);\n")
967 for enum_item
in enum
:
968 enum_pos
= EnumConstants
.add_constant(enum_item
)
969 condition_list
.append("s == \"%s\"" % enum_item
)
970 validator_writer
.newline(" ASSERT(%s);\n" % " || ".join(condition_list
))
971 validator_writer
.newline("}\n")
974 domain_guard
.generate_close(validator_writer
)
976 validator_writer
.newline("\n\n")
978 writer
.newline("}; // struct ")
979 writer
.append(enum_name
)
983 def register_use(forward_listener
):
987 def get_generate_pass_id():
988 return TypeBuilderPass
.MAIN
993 def get_validator_call_text(cls
):
994 return helper
.full_name_prefix_for_use
+ fixed_type_name
.class_name
+ "::assertCorrectValue"
997 def get_array_item_c_type_text(cls
):
998 return helper
.full_name_prefix_for_use
+ fixed_type_name
.class_name
+ "::Enum"
1001 def get_setter_value_expression_pattern():
1002 return "Inspector::TypeBuilder::get%sEnumConstantValue(%s)"
1005 def reduce_to_raw_type():
1006 return RawTypes
.String
1009 def get_type_model():
1010 return TypeModel
.Enum(helper
.full_name_prefix_for_use
+ fixed_type_name
.class_name
)
1014 if helper
.is_ad_hoc
:
1018 def resolve_inner(cls
, resolve_context
):
1022 def request_user_runtime_cast(request
):
1023 raise Exception("Unsupported")
1026 def request_internal_runtime_cast():
1030 def get_code_generator():
1034 def get_validator_call_text(cls
):
1035 return RawTypes
.String
.get_raw_validator_call_text()
1038 def reduce_to_raw_type():
1039 return RawTypes
.String
1042 def get_type_model():
1043 return TypeModel
.String
1046 def get_setter_value_expression_pattern():
1050 def get_array_item_c_type_text(cls
):
1051 return cls
.reduce_to_raw_type().get_array_item_raw_c_type_text()
1057 class TypedefString
:
1059 def resolve_inner(cls
, resolve_context
):
1063 def request_user_runtime_cast(request
):
1064 raise Exception("Unsupported")
1067 def request_internal_runtime_cast():
1068 RawTypes
.String
.request_raw_internal_runtime_cast()
1071 def get_code_generator():
1072 class CodeGenerator
:
1074 def generate_type_builder(writer
, generate_context
):
1075 helper
.write_doc(writer
)
1076 fixed_type_name
.output_comment(writer
)
1077 writer
.newline("typedef String ")
1078 writer
.append(fixed_type_name
.class_name
)
1079 writer
.append(";\n\n")
1082 def register_use(forward_listener
):
1086 def get_generate_pass_id():
1087 return TypeBuilderPass
.TYPEDEF
1089 return CodeGenerator
1092 def get_validator_call_text(cls
):
1093 return RawTypes
.String
.get_raw_validator_call_text()
1096 def reduce_to_raw_type():
1097 return RawTypes
.String
1100 def get_type_model():
1101 return TypeModel
.ValueType("%s%s" % (helper
.full_name_prefix_for_use
, fixed_type_name
.class_name
), True)
1104 def get_setter_value_expression_pattern():
1108 def get_array_item_c_type_text(cls
):
1109 return "const %s%s&" % (helper
.full_name_prefix_for_use
, fixed_type_name
.class_name
)
1111 return TypedefString
1113 elif json_typable
["type"] == "integer":
1114 if helper
.is_ad_hoc
:
1118 def resolve_inner(cls
, resolve_context
):
1122 def request_user_runtime_cast(request
):
1123 raise Exception("Unsupported")
1126 def request_internal_runtime_cast():
1130 def get_code_generator():
1134 def get_validator_call_text(cls
):
1135 return RawTypes
.Int
.get_raw_validator_call_text()
1138 def reduce_to_raw_type():
1142 def get_type_model():
1143 return TypeModel
.Int
1146 def get_setter_value_expression_pattern():
1150 def get_array_item_c_type_text(cls
):
1151 return cls
.reduce_to_raw_type().get_array_item_raw_c_type_text()
1157 class TypedefInteger
:
1159 def resolve_inner(cls
, resolve_context
):
1163 def request_user_runtime_cast(request
):
1164 raise Exception("Unsupported")
1167 def request_internal_runtime_cast():
1168 RawTypes
.Int
.request_raw_internal_runtime_cast()
1171 def get_code_generator():
1172 class CodeGenerator
:
1174 def generate_type_builder(writer
, generate_context
):
1175 helper
.write_doc(writer
)
1176 fixed_type_name
.output_comment(writer
)
1177 writer
.newline("typedef int ")
1178 writer
.append(fixed_type_name
.class_name
)
1179 writer
.append(";\n\n")
1182 def register_use(forward_listener
):
1186 def get_generate_pass_id():
1187 return TypeBuilderPass
.TYPEDEF
1189 return CodeGenerator
1192 def get_validator_call_text(cls
):
1193 return RawTypes
.Int
.get_raw_validator_call_text()
1196 def reduce_to_raw_type():
1200 def get_type_model():
1201 return TypeModel
.Int
1204 def get_setter_value_expression_pattern():
1208 def get_array_item_c_type_text(cls
):
1209 return helper
.full_name_prefix_for_use
+ fixed_type_name
.class_name
1211 return TypedefInteger
1213 elif json_typable
["type"] == "object":
1214 if "properties" in json_typable
:
1217 resolve_data_
= None
1218 need_user_runtime_cast_
= False
1219 need_internal_runtime_cast_
= False
1222 def resolve_inner(cls
, resolve_context
):
1223 if cls
.resolve_data_
:
1226 properties
= json_typable
["properties"]
1230 ad_hoc_type_list
= []
1232 for prop
in properties
:
1233 prop_name
= prop
["name"]
1234 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
)
1235 binding
= resolve_param_type(prop
, context_domain_name
, ad_hoc_type_context
)
1237 code_generator
= binding
.get_code_generator()
1239 code_generator
.register_use(resolve_context
.forward_listener
)
1242 param_type_binding
= binding
1245 if prop
.get("optional"):
1246 optional
.append(PropertyData
)
1248 main
.append(PropertyData
)
1251 main_properties
= main
1252 optional_properties
= optional
1253 ad_hoc_types
= ad_hoc_type_list
1255 cls
.resolve_data_
= ResolveData
1257 for ad_hoc
in ad_hoc_type_list
:
1258 ad_hoc
.resolve_inner(resolve_context
)
1261 def request_user_runtime_cast(cls
, request
):
1264 cls
.need_user_runtime_cast_
= True
1265 request
.acknowledge()
1266 cls
.request_internal_runtime_cast()
1269 def request_internal_runtime_cast(cls
):
1270 if cls
.need_internal_runtime_cast_
:
1272 cls
.need_internal_runtime_cast_
= True
1273 for p
in cls
.resolve_data_
.main_properties
:
1274 p
.param_type_binding
.request_internal_runtime_cast()
1275 for p
in cls
.resolve_data_
.optional_properties
:
1276 p
.param_type_binding
.request_internal_runtime_cast()
1279 def get_code_generator(class_binding_cls
):
1280 class CodeGenerator
:
1282 def generate_type_builder(cls
, writer
, generate_context
):
1283 resolve_data
= class_binding_cls
.resolve_data_
1284 helper
.write_doc(writer
)
1285 class_name
= fixed_type_name
.class_name
1287 is_open_type
= (context_domain_name
+ "." + class_name
) in TYPES_WITH_OPEN_FIELD_LIST_SET
1289 fixed_type_name
.output_comment(writer
)
1290 writer
.newline("class ")
1291 writer
.append(class_name
)
1292 writer
.append(" : public ")
1294 writer
.append("Inspector::InspectorObject")
1296 writer
.append("Inspector::InspectorObjectBase")
1297 writer
.append(" {\n")
1298 writer
.newline("public:\n")
1299 ad_hoc_type_writer
= writer
.insert_writer(" ")
1301 for ad_hoc_type
in resolve_data
.ad_hoc_types
:
1302 code_generator
= ad_hoc_type
.get_code_generator()
1304 code_generator
.generate_type_builder(ad_hoc_type_writer
, generate_context
)
1306 writer
.newline_multiline(
1311 state_enum_items
= []
1312 if len(resolve_data
.main_properties
) > 0:
1314 for prop_data
in resolve_data
.main_properties
:
1315 item_name
= Capitalizer
.lower_camel_case_to_upper(prop_data
.p
["name"]) + "Set"
1316 state_enum_items
.append(item_name
)
1317 writer
.newline(" %s = 1 << %s,\n" % (item_name
, pos
))
1319 all_fields_set_value
= "(" + (" | ".join(state_enum_items
)) + ")"
1321 all_fields_set_value
= "0"
1323 writer
.newline_multiline(CodeGeneratorInspectorStrings
.class_binding_builder_part_1
1324 % (all_fields_set_value
, class_name
, class_name
))
1327 for prop_data
in resolve_data
.main_properties
:
1328 prop_name
= prop_data
.p
["name"]
1330 param_type_binding
= prop_data
.param_type_binding
1331 param_raw_type
= param_type_binding
.reduce_to_raw_type()
1333 writer
.newline_multiline(CodeGeneratorInspectorStrings
.class_binding_builder_part_2
1334 % (state_enum_items
[pos
],
1335 Capitalizer
.lower_camel_case_to_upper(prop_name
),
1336 param_type_binding
.get_type_model().get_input_param_type_text(),
1337 state_enum_items
[pos
], prop_name
,
1338 param_raw_type
.get_setter_name(), prop_name
,
1339 format_setter_value_expression(param_type_binding
, "value"),
1340 state_enum_items
[pos
]))
1344 writer
.newline_multiline(CodeGeneratorInspectorStrings
.class_binding_builder_part_3
1345 % (class_name
, class_name
, class_name
, class_name
, class_name
))
1347 writer
.newline(" /*\n")
1348 writer
.newline(" * Synthetic constructor:\n")
1349 writer
.newline(" * RefPtr<%s> result = %s::create()" % (class_name
, class_name
))
1350 for prop_data
in resolve_data
.main_properties
:
1351 writer
.append_multiline("\n * .set%s(...)" % Capitalizer
.lower_camel_case_to_upper(prop_data
.p
["name"]))
1352 writer
.append_multiline(";\n */\n")
1354 writer
.newline_multiline(CodeGeneratorInspectorStrings
.class_binding_builder_part_4
)
1356 writer
.newline(" typedef Inspector::TypeBuilder::StructItemTraits ItemTraits;\n")
1358 for prop_data
in resolve_data
.optional_properties
:
1359 prop_name
= prop_data
.p
["name"]
1360 param_type_binding
= prop_data
.param_type_binding
1361 setter_name
= "set%s" % Capitalizer
.lower_camel_case_to_upper(prop_name
)
1363 writer
.append_multiline("\n void %s" % setter_name
)
1364 writer
.append("(%s value)\n" % param_type_binding
.get_type_model().get_input_param_type_text())
1365 writer
.newline(" {\n")
1366 writer
.newline(" this->set%s(ASCIILiteral(\"%s\"), %s);\n"
1367 % (param_type_binding
.reduce_to_raw_type().get_setter_name(), prop_data
.p
["name"],
1368 format_setter_value_expression(param_type_binding
, "value")))
1369 writer
.newline(" }\n")
1372 if setter_name
in INSPECTOR_OBJECT_SETTER_NAMES
:
1373 writer
.newline(" using Inspector::InspectorObjectBase::%s;\n\n" % setter_name
)
1375 if class_binding_cls
.need_user_runtime_cast_
:
1376 writer
.newline(" static PassRefPtr<%s> runtimeCast(PassRefPtr<Inspector::InspectorValue> value)\n" % class_name
)
1377 writer
.newline(" {\n")
1378 writer
.newline(" RefPtr<Inspector::InspectorObject> object;\n")
1379 writer
.newline(" bool castRes = value->asObject(&object);\n")
1380 writer
.newline(" ASSERT_UNUSED(castRes, castRes);\n")
1381 writer
.append("#if %s\n" % VALIDATOR_IFDEF_NAME
)
1382 writer
.newline(" assertCorrectValue(object.get());\n")
1383 writer
.append("#endif // %s\n" % VALIDATOR_IFDEF_NAME
)
1384 writer
.newline(" COMPILE_ASSERT(sizeof(%s) == sizeof(Inspector::InspectorObjectBase), type_cast_problem);\n" % class_name
)
1385 writer
.newline(" return static_cast<%s*>(static_cast<Inspector::InspectorObjectBase*>(object.get()));\n" % class_name
)
1386 writer
.newline(" }\n")
1389 if class_binding_cls
.need_internal_runtime_cast_
:
1390 writer
.append("#if %s\n" % VALIDATOR_IFDEF_NAME
)
1391 writer
.newline(" static %s void assertCorrectValue(Inspector::InspectorValue* value);\n" % INSPECTOR_TYPES_GENERATOR_CONFIG_MAP
[output_type
]["export_macro"])
1392 writer
.append("#endif // %s\n" % VALIDATOR_IFDEF_NAME
)
1394 closed_field_set
= (context_domain_name
+ "." + class_name
) not in TYPES_WITH_OPEN_FIELD_LIST_SET
1396 validator_writer
= generate_context
.validator_writer
1398 domain_fixes
= DomainNameFixes
.get_fixed_data(context_domain_name
)
1399 domain_guard
= domain_fixes
.get_guard()
1401 domain_guard
.generate_open(validator_writer
)
1403 validator_writer
.newline("void %s%s::assertCorrectValue(Inspector::InspectorValue* value)\n" % (helper
.full_name_prefix_for_impl
, class_name
))
1404 validator_writer
.newline("{\n")
1405 validator_writer
.newline(" RefPtr<InspectorObject> object;\n")
1406 validator_writer
.newline(" bool castRes = value->asObject(&object);\n")
1407 validator_writer
.newline(" ASSERT_UNUSED(castRes, castRes);\n")
1408 for prop_data
in resolve_data
.main_properties
:
1409 validator_writer
.newline(" {\n")
1410 it_name
= "%sPos" % prop_data
.p
["name"]
1411 validator_writer
.newline(" InspectorObject::iterator %s;\n" % it_name
)
1412 validator_writer
.newline(" %s = object->find(\"%s\");\n" % (it_name
, prop_data
.p
["name"]))
1413 validator_writer
.newline(" ASSERT(%s != object->end());\n" % it_name
)
1414 validator_writer
.newline(" %s(%s->value.get());\n" % (prop_data
.param_type_binding
.get_validator_call_text(), it_name
))
1415 validator_writer
.newline(" }\n")
1417 if closed_field_set
:
1418 validator_writer
.newline(" int foundPropertiesCount = %s;\n" % len(resolve_data
.main_properties
))
1420 for prop_data
in resolve_data
.optional_properties
:
1421 validator_writer
.newline(" {\n")
1422 it_name
= "%sPos" % prop_data
.p
["name"]
1423 validator_writer
.newline(" InspectorObject::iterator %s;\n" % it_name
)
1424 validator_writer
.newline(" %s = object->find(\"%s\");\n" % (it_name
, prop_data
.p
["name"]))
1425 validator_writer
.newline(" if (%s != object->end()) {\n" % it_name
)
1426 validator_writer
.newline(" %s(%s->value.get());\n" % (prop_data
.param_type_binding
.get_validator_call_text(), it_name
))
1427 if closed_field_set
:
1428 validator_writer
.newline(" ++foundPropertiesCount;\n")
1429 validator_writer
.newline(" }\n")
1430 validator_writer
.newline(" }\n")
1432 if closed_field_set
:
1433 validator_writer
.newline(" if (foundPropertiesCount != object->size())\n")
1434 validator_writer
.newline(" FATAL(\"Unexpected properties in object: %s\\n\", object->toJSONString().ascii().data());\n")
1435 validator_writer
.newline("}\n")
1438 domain_guard
.generate_close(validator_writer
)
1440 validator_writer
.newline("\n\n")
1443 cpp_writer
= generate_context
.cpp_writer
1445 writer
.newline(" // Property names for type generated as open.\n")
1446 for prop_data
in resolve_data
.main_properties
+ resolve_data
.optional_properties
:
1447 prop_name
= prop_data
.p
["name"]
1448 prop_field_name
= Capitalizer
.lower_camel_case_to_upper(prop_name
)
1449 writer
.newline(" static const char* %s;\n" % (prop_field_name
))
1450 cpp_writer
.newline("const char* %s%s::%s = \"%s\";\n" % (helper
.full_name_prefix_for_impl
, class_name
, prop_field_name
, prop_name
))
1453 writer
.newline("};\n\n")
1456 def generate_forward_declaration(writer
):
1457 class_name
= fixed_type_name
.class_name
1458 writer
.newline("class ")
1459 writer
.append(class_name
)
1460 writer
.append(";\n")
1463 def register_use(forward_listener
):
1464 helper
.add_to_forward_listener(forward_listener
)
1467 def get_generate_pass_id():
1468 return TypeBuilderPass
.MAIN
1470 return CodeGenerator
1473 def get_validator_call_text():
1474 return helper
.full_name_prefix_for_use
+ fixed_type_name
.class_name
+ "::assertCorrectValue"
1477 def get_array_item_c_type_text(cls
):
1478 return helper
.full_name_prefix_for_use
+ fixed_type_name
.class_name
1481 def get_setter_value_expression_pattern():
1485 def reduce_to_raw_type():
1486 return RawTypes
.Object
1489 def get_type_model():
1490 return TypeModel
.RefPtrBased(helper
.full_name_prefix_for_use
+ fixed_type_name
.class_name
)
1492 class AdHocTypeContextImpl
:
1493 def __init__(self
, property_name
, class_name
, resolve_context
, ad_hoc_type_list
, parent_full_name_prefix
):
1494 self
.property_name
= property_name
1495 self
.class_name
= class_name
1496 self
.resolve_context
= resolve_context
1497 self
.ad_hoc_type_list
= ad_hoc_type_list
1498 self
.container_full_name_prefix
= parent_full_name_prefix
+ class_name
+ "::"
1499 self
.container_relative_name_prefix
= ""
1501 def get_type_name_fix(self
):
1503 class_name
= Capitalizer
.lower_camel_case_to_upper(self
.property_name
)
1506 def output_comment(writer
):
1507 writer
.newline("// Named after property name '%s' while generating %s.\n" % (self
.property_name
, self
.class_name
))
1511 def add_type(self
, binding
):
1512 self
.ad_hoc_type_list
.append(binding
)
1517 class PlainObjectBinding
:
1519 def resolve_inner(cls
, resolve_context
):
1523 def request_user_runtime_cast(request
):
1527 def request_internal_runtime_cast():
1528 RawTypes
.Object
.request_raw_internal_runtime_cast()
1531 def get_code_generator():
1535 def get_validator_call_text():
1536 return "RuntimeCastHelper::assertType<InspectorValue::TypeObject>"
1539 def get_array_item_c_type_text(cls
):
1540 return cls
.reduce_to_raw_type().get_array_item_raw_c_type_text()
1543 def get_setter_value_expression_pattern():
1547 def reduce_to_raw_type():
1548 return RawTypes
.Object
1551 def get_type_model():
1552 return TypeModel
.Object
1554 return PlainObjectBinding
1555 elif json_typable
["type"] == "array":
1556 if "items" in json_typable
:
1560 class AdHocTypeContext
:
1561 container_full_name_prefix
= "<not yet defined>"
1562 container_relative_name_prefix
= ""
1565 def get_type_name_fix():
1566 return fixed_type_name
1569 def add_type(binding
):
1570 ad_hoc_types
.append(binding
)
1572 item_binding
= resolve_param_type(json_typable
["items"], context_domain_name
, AdHocTypeContext
)
1575 resolve_data_
= None
1576 need_internal_runtime_cast_
= False
1579 def resolve_inner(cls
, resolve_context
):
1580 if cls
.resolve_data_
:
1584 item_type_binding
= item_binding
1585 ad_hoc_type_list
= ad_hoc_types
1587 cls
.resolve_data_
= ResolveData
1589 for t
in ad_hoc_types
:
1590 t
.resolve_inner(resolve_context
)
1593 def request_user_runtime_cast(cls
, request
):
1594 raise Exception("Not implemented yet")
1597 def request_internal_runtime_cast(cls
):
1598 if cls
.need_internal_runtime_cast_
:
1600 cls
.need_internal_runtime_cast_
= True
1601 cls
.resolve_data_
.item_type_binding
.request_internal_runtime_cast()
1604 def get_code_generator(array_binding_cls
):
1606 class CodeGenerator
:
1608 def generate_type_builder(writer
, generate_context
):
1609 ad_hoc_type_writer
= writer
1611 resolve_data
= array_binding_cls
.resolve_data_
1613 for ad_hoc_type
in resolve_data
.ad_hoc_type_list
:
1614 code_generator
= ad_hoc_type
.get_code_generator()
1616 code_generator
.generate_type_builder(ad_hoc_type_writer
, generate_context
)
1619 def generate_forward_declaration(writer
):
1623 def register_use(forward_listener
):
1624 item_code_generator
= item_binding
.get_code_generator()
1625 if item_code_generator
:
1626 item_code_generator
.register_use(forward_listener
)
1629 def get_generate_pass_id():
1630 return TypeBuilderPass
.MAIN
1632 return CodeGenerator
1635 def get_validator_call_text(cls
):
1636 return cls
.get_array_item_c_type_text() + "::assertCorrectValue"
1639 def get_array_item_c_type_text(cls
):
1640 return replace_right_shift("Inspector::TypeBuilder::Array<%s>" % cls
.resolve_data_
.item_type_binding
.get_array_item_c_type_text())
1643 def get_setter_value_expression_pattern():
1647 def reduce_to_raw_type():
1648 return RawTypes
.Array
1651 def get_type_model(cls
):
1652 return TypeModel
.RefPtrBased(cls
.get_array_item_c_type_text())
1656 # Fall-through to raw type.
1659 raw_type
= RawTypes
.get(json_typable
["type"])
1661 return RawTypeBinding(raw_type
)
1664 class RawTypeBinding
:
1665 def __init__(self
, raw_type
):
1666 self
.raw_type_
= raw_type
1668 def resolve_inner(self
, resolve_context
):
1671 def request_user_runtime_cast(self
, request
):
1672 raise Exception("Unsupported")
1674 def request_internal_runtime_cast(self
):
1675 self
.raw_type_
.request_raw_internal_runtime_cast()
1677 def get_code_generator(self
):
1680 def get_validator_call_text(self
):
1681 return self
.raw_type_
.get_raw_validator_call_text()
1683 def get_array_item_c_type_text(self
):
1684 return self
.raw_type_
.get_array_item_raw_c_type_text()
1686 def get_setter_value_expression_pattern(self
):
1689 def reduce_to_raw_type(self
):
1690 return self
.raw_type_
1692 def get_type_model(self
):
1693 return self
.raw_type_
.get_raw_type_model()
1696 class TypeData(object):
1697 def __init__(self
, json_type
, json_domain
, domain_data
):
1698 self
.json_type_
= json_type
1699 self
.json_domain_
= json_domain
1700 self
.domain_data_
= domain_data
1702 if "type" not in json_type
:
1703 raise Exception("Unknown type")
1705 json_type_name
= json_type
["type"]
1706 self
.raw_type_
= RawTypes
.get(json_type_name
)
1707 self
.binding_being_resolved_
= False
1708 self
.binding_
= None
1710 def get_raw_type(self
):
1711 return self
.raw_type_
1713 def get_binding(self
):
1714 if not self
.binding_
:
1715 if self
.binding_being_resolved_
:
1716 raise Exception("Type %s is already being resolved" % self
.json_type_
["type"])
1717 # Resolve only lazily, because resolving one named type may require resolving some other named type.
1718 self
.binding_being_resolved_
= True
1720 self
.binding_
= TypeBindings
.create_named_type_declaration(self
.json_type_
, self
.json_domain_
["domain"], self
)
1722 self
.binding_being_resolved_
= False
1724 return self
.binding_
1726 def get_json_type(self
):
1727 return self
.json_type_
1730 return self
.json_type_
["id"]
1732 def get_domain_name(self
):
1733 return self
.json_domain_
["domain"]
1737 def __init__(self
, json_domain
):
1738 self
.json_domain
= json_domain
1741 def add_type(self
, type_data
):
1742 self
.types_
.append(type_data
)
1745 return self
.json_domain
["domain"]
1752 def __init__(self
, api
, dependency_api
):
1755 self
.domains_to_generate_
= []
1756 for json_domain
in api
["domains"]:
1757 self
.add_domain(json_domain
, True)
1758 for json_domain
in dependency_api
["domains"]:
1759 self
.add_domain(json_domain
, False)
1761 def add_domain(self
, json_domain
, should_generate
):
1762 domain_name
= json_domain
["domain"]
1765 self
.map_
[domain_name
] = domain_map
1767 domain_data
= DomainData(json_domain
)
1768 self
.domains_
.append(domain_data
)
1771 # FIXME: The order of types should not matter. The generated code should work regardless of the order of types.
1772 if domain_name
== "Page":
1773 self
.domains_to_generate_
.insert(0, domain_data
)
1775 self
.domains_to_generate_
.append(domain_data
)
1777 if "types" in json_domain
:
1778 for json_type
in json_domain
["types"]:
1779 type_name
= json_type
["id"]
1780 type_data
= TypeData(json_type
, json_domain
, domain_data
)
1781 domain_map
[type_name
] = type_data
1782 domain_data
.add_type(type_data
)
1785 return self
.domains_
1787 def domains_to_generate(self
):
1788 return self
.domains_to_generate_
1790 def get(self
, domain_name
, type_name
):
1791 return self
.map_
[domain_name
][type_name
]
1794 def resolve_param_type(json_parameter
, scope_domain_name
, ad_hoc_type_context
):
1795 if "$ref" in json_parameter
:
1796 json_ref
= json_parameter
["$ref"]
1797 type_data
= get_ref_data(json_ref
, scope_domain_name
)
1798 return type_data
.get_binding()
1799 elif "type" in json_parameter
:
1800 result
= TypeBindings
.create_ad_hoc_type_declaration(json_parameter
, scope_domain_name
, ad_hoc_type_context
)
1801 ad_hoc_type_context
.add_type(result
)
1804 raise Exception("Unknown type")
1807 def resolve_param_raw_type(json_parameter
, scope_domain_name
):
1808 if "$ref" in json_parameter
:
1809 json_ref
= json_parameter
["$ref"]
1810 type_data
= get_ref_data(json_ref
, scope_domain_name
)
1811 return type_data
.get_raw_type()
1812 elif "type" in json_parameter
:
1813 json_type
= json_parameter
["type"]
1814 return RawTypes
.get(json_type
)
1816 raise Exception("Unknown type")
1819 def get_ref_data(json_ref
, scope_domain_name
):
1820 dot_pos
= json_ref
.find(".")
1822 domain_name
= scope_domain_name
1823 type_name
= json_ref
1825 domain_name
= json_ref
[:dot_pos
]
1826 type_name
= json_ref
[dot_pos
+ 1:]
1828 return type_map
.get(domain_name
, type_name
)
1831 input_file
= open(input_json_filename
, "r")
1832 json_string
= input_file
.read()
1833 json_api
= json
.loads(json_string
)
1835 if not "domains" in json_api
:
1836 json_api
= {"domains": [json_api]}
1838 dependency_api
= {"domains": []}
1839 for dependency_json_filename
in dependency_json_filenames
:
1840 dependency_input_file
= open(dependency_json_filename
, "r")
1841 dependency_json_string
= dependency_input_file
.read()
1842 dependency_json_api
= json
.loads(dependency_json_string
)
1843 dependency_input_file
.close()
1844 if not "domains" in dependency_json_api
:
1845 dependency_json_api
= {"domains": [dependency_json_api]}
1846 dependency_api
["domains"] += dependency_json_api
["domains"]
1850 def get_this_script_path_(absolute_path
):
1851 absolute_path
= os
.path
.abspath(absolute_path
)
1854 def fill_recursive(path_part
, depth
):
1855 if depth
<= 0 or path_part
== '/':
1857 fill_recursive(os
.path
.dirname(path_part
), depth
- 1)
1858 components
.append(os
.path
.basename(path_part
))
1860 # Typical path is /Source/WebCore/inspector/CodeGeneratorInspector.py
1861 # Let's take 4 components from the real path then.
1862 fill_recursive(absolute_path
, 4)
1864 return "/".join(components
)
1866 file_header_
= ("// File is generated by %s\n\n" % get_this_script_path_(sys
.argv
[0]) +
1867 """// Copyright (c) 2013 Apple Inc. All Rights Reserved.
1868 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
1869 // Use of this source code is governed by a BSD-style license that can be
1870 // found in the LICENSE file.
1873 frontend_domain_class
= string
.Template(CodeGeneratorInspectorStrings
.frontend_domain_class
)
1874 backend_dispatcher_constructor
= string
.Template(CodeGeneratorInspectorStrings
.backend_dispatcher_constructor
)
1875 backend_dispatcher_dispatch_method
= string
.Template(CodeGeneratorInspectorStrings
.backend_dispatcher_dispatch_method
)
1876 backend_dispatcher_dispatch_method_simple
= string
.Template(CodeGeneratorInspectorStrings
.backend_dispatcher_dispatch_method_simple
)
1877 backend_method
= string
.Template(CodeGeneratorInspectorStrings
.backend_method
)
1878 frontend_method
= string
.Template(CodeGeneratorInspectorStrings
.frontend_method
)
1879 callback_method
= string
.Template(CodeGeneratorInspectorStrings
.callback_method
)
1880 frontend_h
= string
.Template(file_header_
+ CodeGeneratorInspectorStrings
.frontend_h
)
1881 backend_h
= string
.Template(file_header_
+ CodeGeneratorInspectorStrings
.backend_h
)
1882 backend_cpp
= string
.Template(file_header_
+ CodeGeneratorInspectorStrings
.backend_cpp
)
1883 frontend_cpp
= string
.Template(file_header_
+ CodeGeneratorInspectorStrings
.frontend_cpp
)
1884 typebuilder_h
= string
.Template(file_header_
+ CodeGeneratorInspectorStrings
.typebuilder_h
)
1885 typebuilder_cpp
= string
.Template(file_header_
+ CodeGeneratorInspectorStrings
.typebuilder_cpp
)
1886 backend_js
= string
.Template(file_header_
+ CodeGeneratorInspectorStrings
.backend_js
)
1887 param_container_access_code
= CodeGeneratorInspectorStrings
.param_container_access_code
1893 type_map
= TypeMap(json_api
, dependency_api
)
1896 class NeedRuntimeCastRequest
:
1900 def acknowledge(self
):
1903 def is_acknowledged(self
):
1907 def resolve_all_types():
1908 runtime_cast_generate_requests
= {}
1909 for type_name
in TYPES_WITH_RUNTIME_CAST_SET
:
1910 runtime_cast_generate_requests
[type_name
] = NeedRuntimeCastRequest()
1912 class ForwardListener
:
1913 type_data_set
= set()
1914 already_declared_set
= set()
1917 def add_type_data(cls
, type_data
):
1918 if type_data
not in cls
.already_declared_set
:
1919 cls
.type_data_set
.add(type_data
)
1921 class ResolveContext
:
1922 forward_listener
= ForwardListener
1924 for domain_data
in type_map
.domains():
1925 for type_data
in domain_data
.types():
1926 binding
= type_data
.get_binding()
1927 binding
.resolve_inner(ResolveContext
)
1928 # Do not generate forwards for this type any longer.
1929 ForwardListener
.already_declared_set
.add(type_data
)
1931 for domain_data
in type_map
.domains():
1932 for type_data
in domain_data
.types():
1933 full_type_name
= "%s.%s" % (type_data
.get_domain_name(), type_data
.get_name())
1934 request
= runtime_cast_generate_requests
.pop(full_type_name
, None)
1935 binding
= type_data
.get_binding()
1937 binding
.request_user_runtime_cast(request
)
1939 if request
and not request
.is_acknowledged():
1940 raise Exception("Failed to generate runtimeCast in " + full_type_name
)
1942 # FIXME: This assumes all the domains are processed at once. Change this verification
1943 # to only verify runtime casts for the domains being generated.
1945 # for full_type_name in runtime_cast_generate_requests:
1946 # raise Exception("Failed to generate runtimeCast. Type " + full_type_name + " not found")
1948 return ForwardListener
1951 global_forward_listener
= resolve_all_types()
1954 def get_annotated_type_text(raw_type
, annotated_type
):
1955 if annotated_type
!= raw_type
:
1956 return "/*%s*/ %s" % (annotated_type
, raw_type
)
1961 def format_setter_value_expression(param_type_binding
, value_ref
):
1962 pattern
= param_type_binding
.get_setter_value_expression_pattern()
1964 return pattern
% (INSPECTOR_TYPES_GENERATOR_CONFIG_MAP
[output_type
]["prefix"], value_ref
)
1970 frontend_domain_class_lines
= []
1972 backend_method_implementation_list
= []
1973 frontend_method_list
= []
1974 backend_js_domain_initializer_list
= []
1976 backend_handler_interface_list
= []
1977 backend_handler_implementation_list
= []
1978 backend_dispatcher_interface_list
= []
1979 type_builder_fragments
= []
1980 type_builder_forwards
= []
1981 validator_impl_list
= []
1982 type_builder_impl_list
= []
1987 Generator
.process_types(type_map
)
1989 first_cycle_guardable_list_list
= [
1990 Generator
.backend_method_implementation_list
,
1991 Generator
.backend_handler_interface_list
,
1992 Generator
.backend_handler_implementation_list
,
1993 Generator
.backend_dispatcher_interface_list
]
1995 for json_domain
in json_api
["domains"]:
1996 domain_name
= json_domain
["domain"]
1997 domain_name_lower
= domain_name
.lower()
1999 domain_fixes
= DomainNameFixes
.get_fixed_data(domain_name
)
2001 domain_guard
= domain_fixes
.get_guard()
2004 for l
in first_cycle_guardable_list_list
:
2005 domain_guard
.generate_open(l
)
2007 frontend_method_declaration_lines
= []
2009 if ("commands" in json_domain
or "events" in json_domain
):
2010 Generator
.backend_js_domain_initializer_list
.append("// %s.\n" % domain_name
)
2011 if not domain_fixes
.skip_js_bind
:
2012 Generator
.backend_js_domain_initializer_list
.append("InspectorBackend.register%sDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, \"%s\");\n" % (domain_name
, domain_name
))
2014 if "types" in json_domain
:
2015 for json_type
in json_domain
["types"]:
2016 if "type" in json_type
and json_type
["type"] == "string" and "enum" in json_type
:
2017 enum_name
= "%s.%s" % (domain_name
, json_type
["id"])
2018 Generator
.process_enum(json_type
, enum_name
)
2019 elif json_type
["type"] == "object":
2020 if "properties" in json_type
:
2021 for json_property
in json_type
["properties"]:
2022 if "type" in json_property
and json_property
["type"] == "string" and "enum" in json_property
:
2023 enum_name
= "%s.%s%s" % (domain_name
, json_type
["id"], to_title_case(json_property
["name"]))
2024 Generator
.process_enum(json_property
, enum_name
)
2026 if "events" in json_domain
:
2028 domain_guard
.generate_open(Generator
.frontend_method_list
)
2029 domain_guard
.generate_open(Generator
.frontend_domain_class_lines
)
2031 for json_event
in json_domain
["events"]:
2032 Generator
.process_event(json_event
, domain_name
, frontend_method_declaration_lines
)
2034 Generator
.frontend_domain_class_lines
.append(Templates
.frontend_domain_class
.substitute(None,
2035 exportMacro
=INSPECTOR_TYPES_GENERATOR_CONFIG_MAP
[output_type
]["export_macro"],
2036 domainClassName
="Inspector%sFrontendDispatcher" % domain_name
,
2037 frontendDomainMethodDeclarations
="".join(flatten_list(frontend_method_declaration_lines
))))
2040 domain_guard
.generate_close(Generator
.frontend_method_list
)
2041 domain_guard
.generate_close(Generator
.frontend_domain_class_lines
)
2043 dispatcher_name
= "Inspector" + Capitalizer
.lower_camel_case_to_upper(domain_name
) + "BackendDispatcher"
2044 agent_interface_name
= dispatcher_name
+ "Handler"
2046 if "commands" in json_domain
:
2047 Generator
.backend_dispatcher_interface_list
.append("class %s %s final : public Inspector::InspectorSupplementalBackendDispatcher {\n" % (INSPECTOR_TYPES_GENERATOR_CONFIG_MAP
[output_type
]["export_macro"], dispatcher_name
))
2048 Generator
.backend_dispatcher_interface_list
.append("public:\n")
2049 Generator
.backend_dispatcher_interface_list
.append(" static PassRefPtr<%s> create(Inspector::InspectorBackendDispatcher*, %s*);\n" % (dispatcher_name
, agent_interface_name
))
2050 Generator
.backend_dispatcher_interface_list
.append(" virtual void dispatch(long callId, const String& method, PassRefPtr<Inspector::InspectorObject> message) override;\n")
2051 Generator
.backend_dispatcher_interface_list
.append("private:\n")
2053 Generator
.backend_handler_interface_list
.append("class %s %s {\n" % (INSPECTOR_TYPES_GENERATOR_CONFIG_MAP
[output_type
]["export_macro"], agent_interface_name
))
2054 Generator
.backend_handler_interface_list
.append("public:\n")
2056 backend_method_count
= len(Generator
.backend_method_implementation_list
)
2058 dispatcher_if_chain
= []
2059 dispatcher_commands_list
= []
2060 for json_command
in json_domain
["commands"]:
2061 Generator
.process_command(json_command
, domain_name
, agent_interface_name
, dispatcher_name
, dispatcher_if_chain
, dispatcher_commands_list
)
2063 Generator
.backend_handler_interface_list
.append("protected:\n")
2064 Generator
.backend_handler_interface_list
.append(" virtual ~%s();\n" % agent_interface_name
)
2065 Generator
.backend_handler_interface_list
.append("};\n\n")
2067 Generator
.backend_handler_implementation_list
.append("%s::~%s() { }\n" % (agent_interface_name
, agent_interface_name
))
2069 Generator
.backend_dispatcher_interface_list
.append("private:\n")
2070 Generator
.backend_dispatcher_interface_list
.append(" %s(Inspector::InspectorBackendDispatcher*, %s*);\n" % (dispatcher_name
, agent_interface_name
))
2071 Generator
.backend_dispatcher_interface_list
.append(" %s* m_agent;\n" % agent_interface_name
)
2072 Generator
.backend_dispatcher_interface_list
.append("};\n\n")
2074 Generator
.backend_method_implementation_list
.insert(backend_method_count
, Templates
.backend_dispatcher_constructor
.substitute(None,
2075 domainName
=domain_name
,
2076 dispatcherName
=dispatcher_name
,
2077 agentName
=agent_interface_name
))
2079 if len(json_domain
["commands"]) <= 5:
2080 Generator
.backend_method_implementation_list
.insert(backend_method_count
+ 1, Templates
.backend_dispatcher_dispatch_method_simple
.substitute(None,
2081 domainName
=domain_name
,
2082 dispatcherName
=dispatcher_name
,
2083 ifChain
="\n".join(dispatcher_if_chain
)))
2085 Generator
.backend_method_implementation_list
.insert(backend_method_count
+ 1, Templates
.backend_dispatcher_dispatch_method
.substitute(None,
2086 domainName
=domain_name
,
2087 dispatcherName
=dispatcher_name
,
2088 dispatcherCommands
="\n".join(dispatcher_commands_list
)))
2091 for l
in reversed(first_cycle_guardable_list_list
):
2092 domain_guard
.generate_close(l
)
2093 Generator
.backend_js_domain_initializer_list
.append("\n")
2096 def process_enum(json_enum
, enum_name
):
2098 for member
in json_enum
["enum"]:
2099 enum_members
.append("%s: \"%s\"" % (fix_camel_case(member
), member
))
2101 Generator
.backend_js_domain_initializer_list
.append("InspectorBackend.registerEnum(\"%s\", {%s});\n" % (
2102 enum_name
, ", ".join(enum_members
)))
2105 def process_event(json_event
, domain_name
, frontend_method_declaration_lines
):
2106 event_name
= json_event
["name"]
2108 ad_hoc_type_output
= []
2109 frontend_method_declaration_lines
.append(ad_hoc_type_output
)
2110 ad_hoc_type_writer
= Writer(ad_hoc_type_output
, " ")
2112 decl_parameter_list
= []
2114 json_parameters
= json_event
.get("parameters")
2115 Generator
.generate_send_method(json_parameters
, event_name
, domain_name
, ad_hoc_type_writer
,
2116 decl_parameter_list
,
2117 Generator
.EventMethodStructTemplate
,
2118 Generator
.frontend_method_list
, Templates
.frontend_method
, {"eventName": event_name}
)
2120 backend_js_event_param_list
= []
2122 for parameter
in json_parameters
:
2123 parameter_name
= parameter
["name"]
2124 backend_js_event_param_list
.append("\"%s\"" % parameter_name
)
2126 frontend_method_declaration_lines
.append(
2127 " void %s(%s);\n" % (event_name
, ", ".join(decl_parameter_list
)))
2129 Generator
.backend_js_domain_initializer_list
.append("InspectorBackend.registerEvent(\"%s.%s\", [%s]);\n" % (
2130 domain_name
, event_name
, ", ".join(backend_js_event_param_list
)))
2132 class EventMethodStructTemplate
:
2134 def append_prolog(line_list
):
2135 line_list
.append(" RefPtr<InspectorObject> paramsObject = InspectorObject::create();\n")
2138 def append_epilog(line_list
):
2139 line_list
.append(" jsonMessage->setObject(ASCIILiteral(\"params\"), paramsObject);\n")
2141 container_name
= "paramsObject"
2144 def process_command(json_command
, domain_name
, agent_interface_name
, dispatcher_name
, dispatcher_if_chain
, dispatcher_commands_list
):
2145 json_command_name
= json_command
["name"]
2147 ad_hoc_type_output
= []
2148 Generator
.backend_handler_interface_list
.append(ad_hoc_type_output
)
2149 ad_hoc_type_writer
= Writer(ad_hoc_type_output
, " ")
2151 Generator
.backend_dispatcher_interface_list
.append(" void %s(long callId, const Inspector::InspectorObject& message);\n" % json_command_name
)
2153 Generator
.backend_handler_interface_list
.append(" virtual void %s(ErrorString*" % json_command_name
)
2155 if not dispatcher_if_chain
:
2156 dispatcher_if_chain
.append(" if (method == \"%s\")" % json_command_name
)
2158 dispatcher_if_chain
.append(" else if (method == \"%s\")" % json_command_name
)
2159 dispatcher_if_chain
.append(" %s(callId, *message.get());" % json_command_name
)
2160 dispatcher_commands_list
.append(" { \"%s\", &%s::%s }," % (json_command_name
, dispatcher_name
, json_command_name
))
2162 method_in_params_handling
= []
2163 method_dispatch_handling
= []
2164 method_out_params_handling
= []
2165 method_ending_handling
= []
2166 method_request_message_param_name
= ""
2167 agent_call_param_list
= []
2168 js_parameters_text
= ""
2169 if "parameters" in json_command
:
2170 json_params
= json_command
["parameters"]
2171 method_request_message_param_name
= " message"
2172 method_in_params_handling
.append(" RefPtr<InspectorArray> protocolErrors = InspectorArray::create();\n")
2173 method_in_params_handling
.append(" RefPtr<InspectorObject> paramsContainer = message.getObject(ASCIILiteral(\"params\"));\n")
2174 method_in_params_handling
.append(" InspectorObject* paramsContainerPtr = paramsContainer.get();\n")
2175 method_in_params_handling
.append(" InspectorArray* protocolErrorsPtr = protocolErrors.get();\n")
2178 for json_parameter
in json_params
:
2179 json_param_name
= json_parameter
["name"]
2180 param_raw_type
= resolve_param_raw_type(json_parameter
, domain_name
)
2182 getter_name
= param_raw_type
.get_getter_name()
2184 optional
= json_parameter
.get("optional")
2186 non_optional_type_model
= param_raw_type
.get_raw_type_model()
2188 type_model
= non_optional_type_model
.get_optional()
2190 type_model
= non_optional_type_model
2193 code
= (" bool %s_valueFound = false;\n"
2194 " %s in_%s = InspectorBackendDispatcher::get%s(paramsContainerPtr, ASCIILiteral(\"%s\"), &%s_valueFound, protocolErrorsPtr);\n" %
2195 (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
))
2196 param
= ", %s_valueFound ? &in_%s : nullptr" % (json_param_name
, json_param_name
)
2197 # FIXME: pass optional refptr-values as PassRefPtr
2198 formal_param_type_pattern
= "const %s*"
2200 code
= (" %s in_%s = InspectorBackendDispatcher::get%s(paramsContainerPtr, ASCIILiteral(\"%s\"), nullptr, protocolErrorsPtr);\n" %
2201 (non_optional_type_model
.get_command_return_pass_model().get_return_var_type(), json_param_name
, getter_name
, json_param_name
))
2202 param
= ", in_%s" % json_param_name
2203 # FIXME: pass not-optional refptr-values as NonNullPassRefPtr
2204 if param_raw_type
.is_heavy_value():
2205 formal_param_type_pattern
= "const %s&"
2207 formal_param_type_pattern
= "%s"
2209 method_in_params_handling
.append(code
)
2210 agent_call_param_list
.append(param
)
2211 Generator
.backend_handler_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
))
2213 js_bind_type
= param_raw_type
.get_js_bind_type()
2214 js_param_text
= "{\"name\": \"%s\", \"type\": \"%s\", \"optional\": %s}" % (
2217 ("true" if ("optional" in json_parameter
and json_parameter
["optional"]) else "false"))
2219 js_param_list
.append(js_param_text
)
2221 method_in_params_handling
.append(" if (protocolErrors->length()) {\n")
2222 method_in_params_handling
.append(" String errorMessage = String::format(\"Some arguments of method '%%s' can't be processed\", \"%s.%s\");\n" % (domain_name
, json_command_name
))
2223 method_in_params_handling
.append(" m_backendDispatcher->reportProtocolError(&callId, InspectorBackendDispatcher::InvalidParams, errorMessage, protocolErrors.release());\n")
2224 method_in_params_handling
.append(" return;\n")
2225 method_in_params_handling
.append(" }\n")
2226 method_in_params_handling
.append("\n")
2228 js_parameters_text
= ", ".join(js_param_list
)
2230 method_dispatch_handling
.append(" ErrorString error;\n")
2231 method_dispatch_handling
.append(" RefPtr<InspectorObject> result = InspectorObject::create();\n")
2233 if json_command
.get("async") == True:
2234 callback_name
= Capitalizer
.lower_camel_case_to_upper(json_command_name
) + "Callback"
2236 callback_output
= []
2237 callback_writer
= Writer(callback_output
, ad_hoc_type_writer
.get_indent())
2239 decl_parameter_list
= []
2240 Generator
.generate_send_method(json_command
.get("returns"), json_command_name
, domain_name
, ad_hoc_type_writer
,
2241 decl_parameter_list
,
2242 Generator
.CallbackMethodStructTemplate
,
2243 Generator
.backend_method_implementation_list
, Templates
.callback_method
,
2244 {"callbackName": callback_name, "handlerName": agent_interface_name}
)
2246 callback_writer
.newline("class " + callback_name
+ " : public Inspector::InspectorBackendDispatcher::CallbackBase {\n")
2247 callback_writer
.newline("public:\n")
2248 callback_writer
.newline(" " + callback_name
+ "(PassRefPtr<Inspector::InspectorBackendDispatcher>, int id);\n")
2249 callback_writer
.newline(" void sendSuccess(" + ", ".join(decl_parameter_list
) + ");\n")
2250 callback_writer
.newline("};\n")
2252 ad_hoc_type_output
.append(callback_output
)
2254 method_dispatch_handling
.append(" RefPtr<%s::%s> callback = adoptRef(new %s::%s(m_backendDispatcher,callId));\n" % (agent_interface_name
, callback_name
, agent_interface_name
, callback_name
))
2255 method_ending_handling
.append(" if (error.length()) {\n")
2256 method_ending_handling
.append(" callback->disable();\n")
2257 method_ending_handling
.append(" m_backendDispatcher->reportProtocolError(&callId, Inspector::InspectorBackendDispatcher::ServerError, error);\n")
2258 method_ending_handling
.append(" return;\n")
2259 method_ending_handling
.append(" }")
2261 agent_call_param_list
.append(", callback")
2262 Generator
.backend_handler_interface_list
.append(", PassRefPtr<%s> callback" % callback_name
)
2263 elif "returns" in json_command
:
2264 has_multiple_returns
= len(json_command
["returns"]) > 1
2265 if has_multiple_returns
:
2266 method_out_params_handling
.append(" if (!error.length()) {\n")
2268 method_out_params_handling
.append(" if (!error.length())\n")
2270 for json_return
in json_command
["returns"]:
2272 json_return_name
= json_return
["name"]
2274 optional
= bool(json_return
.get("optional"))
2276 return_type_binding
= Generator
.resolve_type_and_generate_ad_hoc(json_return
, json_command_name
, domain_name
, ad_hoc_type_writer
, agent_interface_name
+ "::")
2278 raw_type
= return_type_binding
.reduce_to_raw_type()
2279 setter_type
= raw_type
.get_setter_name()
2280 initializer
= raw_type
.get_c_initializer()
2282 type_model
= return_type_binding
.get_type_model()
2284 type_model
= type_model
.get_optional()
2286 code
= " %s out_%s;\n" % (type_model
.get_command_return_pass_model().get_return_var_type(), json_return_name
)
2287 param
= ", %sout_%s" % (type_model
.get_command_return_pass_model().get_output_argument_prefix(), json_return_name
)
2288 var_name
= "out_%s" % json_return_name
2289 setter_argument
= type_model
.get_command_return_pass_model().get_output_to_raw_expression() % var_name
2290 if return_type_binding
.get_setter_value_expression_pattern():
2291 setter_argument
= return_type_binding
.get_setter_value_expression_pattern() % (INSPECTOR_TYPES_GENERATOR_CONFIG_MAP
[output_type
]["prefix"], setter_argument
)
2293 cook
= " result->set%s(ASCIILiteral(\"%s\"), %s);\n" % (setter_type
, json_return_name
, setter_argument
)
2295 set_condition_pattern
= type_model
.get_command_return_pass_model().get_set_return_condition()
2296 if set_condition_pattern
:
2297 cook
= (" if (%s)\n " % (set_condition_pattern
% var_name
)) + cook
2298 annotated_type
= type_model
.get_command_return_pass_model().get_output_parameter_type()
2300 param_name
= "out_%s" % json_return_name
2302 param_name
= "opt_" + param_name
2304 Generator
.backend_handler_interface_list
.append(", %s %s" % (annotated_type
, param_name
))
2305 method_out_params_handling
.append(cook
)
2306 method_dispatch_handling
.append(code
)
2308 agent_call_param_list
.append(param
)
2310 if has_multiple_returns
:
2311 method_out_params_handling
.append(" }\n")
2312 method_out_params_handling
.append("\n")
2314 method_dispatch_handling
.append(" m_agent->%s(&error%s);\n" % (json_command_name
, "".join(agent_call_param_list
)))
2315 method_dispatch_handling
.append("\n")
2317 if not method_ending_handling
:
2318 method_ending_handling
.append(" m_backendDispatcher->sendResponse(callId, result.release(), error);")
2320 backend_js_reply_param_list
= []
2321 if "returns" in json_command
:
2322 for json_return
in json_command
["returns"]:
2323 json_return_name
= json_return
["name"]
2324 backend_js_reply_param_list
.append("\"%s\"" % json_return_name
)
2326 js_reply_list
= "[%s]" % ", ".join(backend_js_reply_param_list
)
2328 Generator
.backend_method_implementation_list
.append(Templates
.backend_method
.substitute(None,
2329 dispatcherName
=dispatcher_name
,
2330 methodName
=json_command_name
,
2331 requestMessageObject
=method_request_message_param_name
,
2332 methodInParametersHandling
="".join(method_in_params_handling
),
2333 methodDispatchHandling
="".join(method_dispatch_handling
),
2334 methodOutParametersHandling
="".join(method_out_params_handling
),
2335 methodEndingHandling
="".join(method_ending_handling
)))
2337 Generator
.backend_js_domain_initializer_list
.append("InspectorBackend.registerCommand(\"%s.%s\", [%s], %s);\n" % (domain_name
, json_command_name
, js_parameters_text
, js_reply_list
))
2338 Generator
.backend_handler_interface_list
.append(") = 0;\n")
2340 class CallbackMethodStructTemplate
:
2342 def append_prolog(line_list
):
2346 def append_epilog(line_list
):
2349 container_name
= "jsonMessage"
2351 # Generates common code for event sending and callback response data sending.
2353 def generate_send_method(parameters
, event_name
, domain_name
, ad_hoc_type_writer
, decl_parameter_list
,
2354 method_struct_template
,
2355 generator_method_list
, method_template
, template_params
):
2356 method_line_list
= []
2358 method_struct_template
.append_prolog(method_line_list
)
2359 for json_parameter
in parameters
:
2360 parameter_name
= json_parameter
["name"]
2362 param_type_binding
= Generator
.resolve_type_and_generate_ad_hoc(json_parameter
, event_name
, domain_name
, ad_hoc_type_writer
, "")
2364 raw_type
= param_type_binding
.reduce_to_raw_type()
2365 raw_type_binding
= RawTypeBinding(raw_type
)
2367 optional
= bool(json_parameter
.get("optional"))
2369 setter_type
= raw_type
.get_setter_name()
2371 type_model
= param_type_binding
.get_type_model()
2372 raw_type_model
= raw_type_binding
.get_type_model()
2374 type_model
= type_model
.get_optional()
2375 raw_type_model
= raw_type_model
.get_optional()
2377 annotated_type
= type_model
.get_input_param_type_text()
2378 mode_type_binding
= param_type_binding
2380 decl_parameter_list
.append("%s %s" % (annotated_type
, parameter_name
))
2382 setter_argument
= raw_type_model
.get_event_setter_expression_pattern() % parameter_name
2383 if mode_type_binding
.get_setter_value_expression_pattern():
2384 setter_argument
= mode_type_binding
.get_setter_value_expression_pattern() % (INSPECTOR_TYPES_GENERATOR_CONFIG_MAP
[output_type
]["prefix"], setter_argument
)
2386 setter_code
= " %s->set%s(ASCIILiteral(\"%s\"), %s);\n" % (method_struct_template
.container_name
, setter_type
, parameter_name
, setter_argument
)
2388 setter_code
= (" if (%s)\n " % parameter_name
) + setter_code
2389 method_line_list
.append(setter_code
)
2391 method_struct_template
.append_epilog(method_line_list
)
2393 generator_method_list
.append(method_template
.substitute(None,
2394 domainName
=domain_name
,
2395 parameters
=", ".join(decl_parameter_list
),
2396 code
="".join(method_line_list
), **template_params
))
2399 def resolve_type_and_generate_ad_hoc(json_param
, method_name
, domain_name
, ad_hoc_type_writer
, container_relative_name_prefix_param
):
2400 param_name
= json_param
["name"]
2401 ad_hoc_type_list
= []
2403 class AdHocTypeContext
:
2404 container_full_name_prefix
= "<not yet defined>"
2405 container_relative_name_prefix
= container_relative_name_prefix_param
2408 def get_type_name_fix():
2410 class_name
= Capitalizer
.lower_camel_case_to_upper(param_name
)
2413 def output_comment(writer
):
2414 writer
.newline("// Named after parameter '%s' while generating command/event %s.\n" % (param_name
, method_name
))
2419 def add_type(binding
):
2420 ad_hoc_type_list
.append(binding
)
2422 type_binding
= resolve_param_type(json_param
, domain_name
, AdHocTypeContext
)
2424 class InterfaceForwardListener
:
2426 def add_type_data(type_data
):
2429 class InterfaceResolveContext
:
2430 forward_listener
= InterfaceForwardListener
2432 for type in ad_hoc_type_list
:
2433 type.resolve_inner(InterfaceResolveContext
)
2435 class InterfaceGenerateContext
:
2436 validator_writer
= "not supported in InterfaceGenerateContext"
2437 cpp_writer
= validator_writer
2439 for type in ad_hoc_type_list
:
2440 generator
= type.get_code_generator()
2442 generator
.generate_type_builder(ad_hoc_type_writer
, InterfaceGenerateContext
)
2447 def process_types(type_map
):
2448 output
= Generator
.type_builder_fragments
2450 class GenerateContext
:
2451 validator_writer
= Writer(Generator
.validator_impl_list
, "")
2452 cpp_writer
= Writer(Generator
.type_builder_impl_list
, "")
2454 def generate_all_domains_code(out
, type_data_callback
):
2455 writer
= Writer(out
, "")
2456 for domain_data
in type_map
.domains_to_generate():
2457 domain_fixes
= DomainNameFixes
.get_fixed_data(domain_data
.name())
2458 domain_guard
= domain_fixes
.get_guard()
2460 namespace_declared
= []
2462 def namespace_lazy_generator():
2463 if not namespace_declared
:
2465 domain_guard
.generate_open(out
)
2466 writer
.newline("namespace ")
2467 writer
.append(domain_data
.name())
2468 writer
.append(" {\n")
2469 # What is a better way to change value from outer scope?
2470 namespace_declared
.append(True)
2473 for type_data
in domain_data
.types():
2474 type_data_callback(type_data
, namespace_lazy_generator
)
2476 if namespace_declared
:
2477 writer
.append("} // ")
2478 writer
.append(domain_data
.name())
2479 writer
.append("\n\n")
2482 domain_guard
.generate_close(out
)
2484 def create_type_builder_caller(generate_pass_id
):
2485 def call_type_builder(type_data
, writer_getter
):
2486 code_generator
= type_data
.get_binding().get_code_generator()
2487 if code_generator
and generate_pass_id
== code_generator
.get_generate_pass_id():
2488 writer
= writer_getter()
2490 code_generator
.generate_type_builder(writer
, GenerateContext
)
2491 return call_type_builder
2493 generate_all_domains_code(output
, create_type_builder_caller(TypeBuilderPass
.MAIN
))
2495 Generator
.type_builder_forwards
.append("// Forward declarations.\n")
2497 def generate_forward_callback(type_data
, writer_getter
):
2498 if type_data
in global_forward_listener
.type_data_set
:
2499 binding
= type_data
.get_binding()
2500 binding
.get_code_generator().generate_forward_declaration(writer_getter())
2501 generate_all_domains_code(Generator
.type_builder_forwards
, generate_forward_callback
)
2503 Generator
.type_builder_forwards
.append("// End of forward declarations.\n\n")
2505 Generator
.type_builder_forwards
.append("// Typedefs.\n")
2507 generate_all_domains_code(Generator
.type_builder_forwards
, create_type_builder_caller(TypeBuilderPass
.TYPEDEF
))
2509 Generator
.type_builder_forwards
.append("// End of typedefs.\n\n")
2512 def flatten_list(input):
2515 def fill_recursive(l
):
2517 if isinstance(item
, list):
2518 fill_recursive(item
)
2521 fill_recursive(input)
2525 # A writer that only updates file if it actually changed to better support incremental build.
2527 def __init__(self
, file_name
):
2528 self
.file_name_
= file_name
2531 def write(self
, text
):
2532 self
.output_
+= text
2536 self
.output_
= self
.output_
.rstrip() + "\n"
2539 read_file
= open(self
.file_name_
, "r")
2540 old_text
= read_file
.read()
2542 text_changed
= old_text
!= self
.output_
2544 # Ignore, just overwrite by default
2547 if text_changed
or write_always
:
2548 out_file
= open(self
.file_name_
, "w")
2549 out_file
.write(self
.output_
)
2555 output_file_name_prefix
= INSPECTOR_TYPES_GENERATOR_CONFIG_MAP
[output_type
]["prefix"]
2557 backend_h_file
= SmartOutput(output_header_dirname
+ ("/Inspector%sBackendDispatchers.h" % output_file_name_prefix
))
2558 backend_cpp_file
= SmartOutput(output_cpp_dirname
+ ("/Inspector%sBackendDispatchers.cpp" % output_file_name_prefix
))
2560 frontend_h_file
= SmartOutput(output_header_dirname
+ ("/Inspector%sFrontendDispatchers.h" % output_file_name_prefix
))
2561 frontend_cpp_file
= SmartOutput(output_cpp_dirname
+ ("/Inspector%sFrontendDispatchers.cpp" % output_file_name_prefix
))
2563 typebuilder_h_file
= SmartOutput(output_header_dirname
+ ("/Inspector%sTypeBuilders.h" % output_file_name_prefix
))
2564 typebuilder_cpp_file
= SmartOutput(output_cpp_dirname
+ ("/Inspector%sTypeBuilders.cpp" % output_file_name_prefix
))
2566 backend_js_file
= SmartOutput(output_js_dirname
+ ("/Inspector%sBackendCommands.js" % output_file_name_prefix
))
2569 backend_h_file
.write(Templates
.backend_h
.substitute(None,
2570 outputFileNamePrefix
=output_file_name_prefix
,
2571 handlerInterfaces
="".join(flatten_list(Generator
.backend_handler_interface_list
)),
2572 dispatcherInterfaces
="".join(flatten_list(Generator
.backend_dispatcher_interface_list
))))
2574 backend_cpp_file
.write(Templates
.backend_cpp
.substitute(None,
2575 outputFileNamePrefix
=output_file_name_prefix
,
2576 handlerImplementations
="".join(flatten_list(Generator
.backend_handler_implementation_list
)),
2577 methods
="\n".join(Generator
.backend_method_implementation_list
)))
2579 frontend_h_file
.write(Templates
.frontend_h
.substitute(None,
2580 outputFileNamePrefix
=output_file_name_prefix
,
2581 domainClassList
="".join(Generator
.frontend_domain_class_lines
)))
2583 frontend_cpp_file
.write(Templates
.frontend_cpp
.substitute(None,
2584 outputFileNamePrefix
=output_file_name_prefix
,
2585 methods
="\n".join(Generator
.frontend_method_list
)))
2587 typebuilder_h_file
.write(Templates
.typebuilder_h
.substitute(None,
2588 outputFileNamePrefix
=output_file_name_prefix
,
2589 typeBuilderDependencies
=INSPECTOR_TYPES_GENERATOR_CONFIG_MAP
[output_type
]["typebuilder_dependency"],
2590 exportMacro
=INSPECTOR_TYPES_GENERATOR_CONFIG_MAP
[output_type
]["export_macro"],
2591 typeBuilders
="".join(flatten_list(Generator
.type_builder_fragments
)),
2592 forwards
="".join(Generator
.type_builder_forwards
),
2593 validatorIfdefName
=VALIDATOR_IFDEF_NAME
))
2595 typebuilder_cpp_file
.write(Templates
.typebuilder_cpp
.substitute(None,
2596 outputFileNamePrefix
=output_file_name_prefix
,
2597 enumConstantValues
=EnumConstants
.get_enum_constant_code(),
2598 implCode
="".join(flatten_list(Generator
.type_builder_impl_list
)),
2599 validatorCode
="".join(flatten_list(Generator
.validator_impl_list
)),
2600 validatorIfdefName
=VALIDATOR_IFDEF_NAME
))
2602 backend_js_file
.write(Templates
.backend_js
.substitute(None,
2603 domainInitializers
="".join(Generator
.backend_js_domain_initializer_list
)))
2605 backend_h_file
.close()
2606 backend_cpp_file
.close()
2608 frontend_h_file
.close()
2609 frontend_cpp_file
.close()
2611 typebuilder_h_file
.close()
2612 typebuilder_cpp_file
.close()
2614 backend_js_file
.close()