Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / inspector / CodeGeneratorInspector.py
1 #!/usr/bin/env python
2 # Copyright (c) 2011 Google Inc. All rights reserved.
3 # Copyright (c) 2012 Intel Corporation. All rights reserved.
4 #
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions are
7 # met:
8 #
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
14 # distribution.
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.
18 #
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.
30
31 import os.path
32 import sys
33 import string
34 import optparse
35 import re
36 try:
37     import json
38 except ImportError:
39     import simplejson as json
40
41 import CodeGeneratorInspectorStrings
42
43 # Manually-filled map of type name replacements.
44 TYPE_NAME_FIX_MAP = {
45     "RGBA": "Rgba",  # RGBA is reported to be conflicting with a define name in Windows CE.
46     "": "Empty",
47 }
48
49
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"])
53
54 TYPES_WITH_OPEN_FIELD_LIST_SET = frozenset([
55                                             # InspectorStyleSheet not only creates this property but wants to read it and modify it.
56                                             "CSS.CSSProperty",
57                                             # InspectorResourceAgent needs to update mime-type.
58                                             "Network.Response"])
59
60 cmdline_parser = optparse.OptionParser()
61 cmdline_parser.add_option("--output_dir")
62
63 try:
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")
71 except Exception:
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")
76     exit(1)
77
78
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('-'))
82
83
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)
88
89
90 def to_title_case(name):
91     return name[:1].upper() + name[1:]
92
93
94 class Capitalizer:
95     @staticmethod
96     def lower_camel_case_to_upper(str):
97         if len(str) > 0 and str[0].islower():
98             str = str[0].upper() + str[1:]
99         return str
100
101     @staticmethod
102     def upper_camel_case_to_lower(str):
103         pos = 0
104         while pos < len(str) and str[pos].isupper():
105             pos += 1
106         if pos == 0:
107             return str
108         if pos == 1:
109             return str[0].lower() + str[1:]
110         if pos < len(str):
111             pos -= 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:]
116         return str
117
118     ABBREVIATION = frozenset(["XHR", "DOM", "CSS"])
119
120 VALIDATOR_IFDEF_NAME = "ENABLE(ASSERT)"
121
122
123 class DomainNameFixes:
124     @staticmethod
125     def get_fixed_data(domain_name):
126         return Capitalizer.upper_camel_case_to_lower(domain_name) + "Agent"
127
128 class RawTypes(object):
129     @staticmethod
130     def get(json_type):
131         if json_type == "boolean":
132             return RawTypes.Bool
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":
140             return RawTypes.Int
141         elif json_type == "number":
142             return RawTypes.Number
143         elif json_type == "any":
144             return RawTypes.Any
145         else:
146             raise Exception("Unknown type: %s" % json_type)
147
148     class BaseType(object):
149         @classmethod
150         def get_raw_validator_call_text(cls):
151             return "RuntimeCastHelper::assertType<JSONValue::Type%s>" % cls.get_getter_name()
152
153         @staticmethod
154         def get_getter_name():
155             raise Exception("Unsupported")
156
157     class String(BaseType):
158         @staticmethod
159         def get_getter_name():
160             return "String"
161
162         get_setter_name = get_getter_name
163
164         @staticmethod
165         def get_constructor_pattern():
166             return "InspectorString::create(%s)"
167
168         @staticmethod
169         def is_heavy_value():
170             return True
171
172         @staticmethod
173         def get_array_item_raw_c_type_text():
174             return "String"
175
176         @staticmethod
177         def get_raw_type_model():
178             return TypeModel.String
179
180     class Int(BaseType):
181         @staticmethod
182         def get_getter_name():
183             return "Int"
184
185         @staticmethod
186         def get_setter_name():
187             return "Number"
188
189         @staticmethod
190         def get_constructor_pattern():
191             return "InspectorBasicValue::create(%s)"
192
193         @classmethod
194         def get_raw_validator_call_text(cls):
195             return "RuntimeCastHelper::assertInt"
196
197         @staticmethod
198         def is_heavy_value():
199             return False
200
201         @staticmethod
202         def get_array_item_raw_c_type_text():
203             return "int"
204
205         @staticmethod
206         def get_raw_type_model():
207             return TypeModel.Int
208
209     class Number(BaseType):
210         @staticmethod
211         def get_getter_name():
212             return "Double"
213
214         @staticmethod
215         def get_setter_name():
216             return "Number"
217
218         @staticmethod
219         def get_constructor_pattern():
220             return "InspectorBasicValue::create(%s)"
221
222         @staticmethod
223         def get_raw_validator_call_text():
224             return "RuntimeCastHelper::assertType<JSONValue::TypeNumber>"
225
226         @staticmethod
227         def is_heavy_value():
228             return False
229
230         @staticmethod
231         def get_array_item_raw_c_type_text():
232             return "double"
233
234         @staticmethod
235         def get_raw_type_model():
236             return TypeModel.Number
237
238     class Bool(BaseType):
239         @staticmethod
240         def get_getter_name():
241             return "Boolean"
242
243         get_setter_name = get_getter_name
244
245         @staticmethod
246         def get_constructor_pattern():
247             return "InspectorBasicValue::create(%s)"
248
249         @staticmethod
250         def is_heavy_value():
251             return False
252
253         @staticmethod
254         def get_array_item_raw_c_type_text():
255             return "bool"
256
257         @staticmethod
258         def get_raw_type_model():
259             return TypeModel.Bool
260
261     class Object(BaseType):
262         @staticmethod
263         def get_getter_name():
264             return "Object"
265
266         @staticmethod
267         def get_setter_name():
268             return "Value"
269
270         @staticmethod
271         def get_constructor_pattern():
272             return "%s"
273
274         @staticmethod
275         def get_output_argument_prefix():
276             return ""
277
278         @staticmethod
279         def is_heavy_value():
280             return True
281
282         @staticmethod
283         def get_array_item_raw_c_type_text():
284             return "JSONObject"
285
286         @staticmethod
287         def get_raw_type_model():
288             return TypeModel.Object
289
290     class Any(BaseType):
291         @staticmethod
292         def get_getter_name():
293             return "Value"
294
295         get_setter_name = get_getter_name
296
297         @staticmethod
298         def get_constructor_pattern():
299             raise Exception("Unsupported")
300
301         @staticmethod
302         def get_raw_validator_call_text():
303             return "RuntimeCastHelper::assertAny"
304
305         @staticmethod
306         def is_heavy_value():
307             return True
308
309         @staticmethod
310         def get_array_item_raw_c_type_text():
311             return "JSONValue"
312
313         @staticmethod
314         def get_raw_type_model():
315             return TypeModel.Any
316
317     class Array(BaseType):
318         @staticmethod
319         def get_getter_name():
320             return "Array"
321
322         @staticmethod
323         def get_setter_name():
324             return "Value"
325
326         @staticmethod
327         def get_constructor_pattern():
328             return "%s"
329
330         @staticmethod
331         def get_output_argument_prefix():
332             return ""
333
334         @staticmethod
335         def is_heavy_value():
336             return True
337
338         @staticmethod
339         def get_array_item_raw_c_type_text():
340             return "JSONArray"
341
342         @staticmethod
343         def get_raw_type_model():
344             return TypeModel.Array
345
346
347 def replace_right_shift(input_str):
348     return input_str.replace(">>", "> >")
349
350
351 class CommandReturnPassModel:
352     class ByReference:
353         def __init__(self, var_type, set_condition):
354             self.var_type = var_type
355             self.set_condition = set_condition
356
357         def get_return_var_type(self):
358             return self.var_type
359
360         @staticmethod
361         def get_output_argument_prefix():
362             return ""
363
364         @staticmethod
365         def get_output_to_raw_expression():
366             return "%s"
367
368         def get_output_parameter_type(self):
369             return self.var_type + "&"
370
371         def get_set_return_condition(self):
372             return self.set_condition
373
374     class ByPointer:
375         def __init__(self, var_type):
376             self.var_type = var_type
377
378         def get_return_var_type(self):
379             return self.var_type
380
381         @staticmethod
382         def get_output_argument_prefix():
383             return "&"
384
385         @staticmethod
386         def get_output_to_raw_expression():
387             return "%s"
388
389         def get_output_parameter_type(self):
390             return self.var_type + "*"
391
392         @staticmethod
393         def get_set_return_condition():
394             return None
395
396     class OptOutput:
397         def __init__(self, var_type):
398             self.var_type = var_type
399
400         def get_return_var_type(self):
401             return "TypeBuilder::OptOutput<%s>" % self.var_type
402
403         @staticmethod
404         def get_output_argument_prefix():
405             return "&"
406
407         @staticmethod
408         def get_output_to_raw_expression():
409             return "%s.getValue()"
410
411         def get_output_parameter_type(self):
412             return "TypeBuilder::OptOutput<%s>*" % self.var_type
413
414         @staticmethod
415         def get_set_return_condition():
416             return "%s.isAssigned()"
417
418
419 class TypeModel:
420     class RefPtrBased(object):
421         def __init__(self, class_name):
422             self.class_name = class_name
423             self.optional = False
424
425         def get_optional(self):
426             result = TypeModel.RefPtrBased(self.class_name)
427             result.optional = True
428             return result
429
430         def get_command_return_pass_model(self):
431             if self.optional:
432                 set_condition = "%s"
433             else:
434                 set_condition = None
435             return CommandReturnPassModel.ByReference(replace_right_shift("RefPtr<%s>" % self.class_name), set_condition)
436
437         def get_input_param_type_text(self):
438             return replace_right_shift("PassRefPtr<%s>" % self.class_name)
439
440         @staticmethod
441         def get_event_setter_expression_pattern():
442             return "%s"
443
444     class Enum(object):
445         def __init__(self, base_type_name):
446             self.type_name = base_type_name + "::Enum"
447
448         def get_optional(base_self):
449             class EnumOptional:
450                 @classmethod
451                 def get_optional(cls):
452                     return cls
453
454                 @staticmethod
455                 def get_command_return_pass_model():
456                     return CommandReturnPassModel.OptOutput(base_self.type_name)
457
458                 @staticmethod
459                 def get_input_param_type_text():
460                     return base_self.type_name + "*"
461
462                 @staticmethod
463                 def get_event_setter_expression_pattern():
464                     raise Exception("TODO")
465             return EnumOptional
466
467         def get_command_return_pass_model(self):
468             return CommandReturnPassModel.ByPointer(self.type_name)
469
470         def get_input_param_type_text(self):
471             return self.type_name
472
473         @staticmethod
474         def get_event_setter_expression_pattern():
475             return "%s"
476
477     class ValueType(object):
478         def __init__(self, type_name, is_heavy):
479             self.type_name = type_name
480             self.is_heavy = is_heavy
481
482         def get_optional(self):
483             return self.ValueOptional(self)
484
485         def get_command_return_pass_model(self):
486             return CommandReturnPassModel.ByPointer(self.type_name)
487
488         def get_input_param_type_text(self):
489             if self.is_heavy:
490                 return "const %s&" % self.type_name
491             else:
492                 return self.type_name
493
494         def get_opt_output_type_(self):
495             return self.type_name
496
497         @staticmethod
498         def get_event_setter_expression_pattern():
499             return "%s"
500
501         class ValueOptional:
502             def __init__(self, base):
503                 self.base = base
504
505             def get_optional(self):
506                 return self
507
508             def get_command_return_pass_model(self):
509                 return CommandReturnPassModel.OptOutput(self.base.get_opt_output_type_())
510
511             def get_input_param_type_text(self):
512                 return "const %s* const" % self.base.type_name
513
514             @staticmethod
515             def get_event_setter_expression_pattern():
516                 return "*%s"
517
518     @classmethod
519     def init_class(cls):
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")
527
528 TypeModel.init_class()
529
530
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"])
534
535
536 def fix_type_name(json_name):
537     if json_name in TYPE_NAME_FIX_MAP:
538         fixed = TYPE_NAME_FIX_MAP[json_name]
539
540         class Result(object):
541             class_name = fixed
542
543             @staticmethod
544             def output_comment(writer):
545                 writer.newline("// Type originally was named '%s'.\n" % json_name)
546     else:
547
548         class Result(object):
549             class_name = json_name
550
551             @staticmethod
552             def output_comment(writer):
553                 pass
554
555     return Result
556
557
558 class Writer:
559     def __init__(self, output, indent):
560         self.output = output
561         self.indent = indent
562
563     def newline(self, str):
564         if (self.indent):
565             self.output.append(self.indent)
566         self.output.append(str)
567
568     def append(self, str):
569         self.output.append(str)
570
571     def newline_multiline(self, str):
572         parts = str.split('\n')
573         self.newline(parts[0])
574         for p in parts[1:]:
575             self.output.append('\n')
576             if p:
577                 self.newline(p)
578
579     def append_multiline(self, str):
580         parts = str.split('\n')
581         self.append(parts[0])
582         for p in parts[1:]:
583             self.output.append('\n')
584             if p:
585                 self.newline(p)
586
587     def get_indent(self):
588         return self.indent
589
590     def insert_writer(self, additional_indent):
591         new_output = []
592         self.output.append(new_output)
593         return Writer(new_output, self.indent + additional_indent)
594
595
596 class EnumConstants:
597     map_ = {}
598     constants_ = []
599
600     @classmethod
601     def add_constant(cls, value):
602         if value in cls.map_:
603             return cls.map_[value]
604         else:
605             pos = len(cls.map_)
606             cls.map_[value] = pos
607             cls.constants_.append(value)
608             return pos
609
610     @classmethod
611     def get_enum_constant_code(cls):
612         output = []
613         for item in cls.constants_:
614             output.append("    \"" + item + "\"")
615         return ",\n".join(output) + "\n"
616
617
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:
621     TYPEDEF = "typedef"
622     MAIN = "main"
623
624
625 class TypeBindings:
626     @staticmethod
627     def create_named_type_declaration(json_typable, context_domain_name, type_data):
628         json_type = type_data.get_json_type()
629
630         class Helper:
631             is_ad_hoc = False
632             full_name_prefix_for_use = "TypeBuilder::" + context_domain_name + "::"
633             full_name_prefix_for_impl = "TypeBuilder::" + context_domain_name + "::"
634
635             @staticmethod
636             def write_doc(writer):
637                 if "description" in json_type:
638                     writer.newline("/* ")
639                     writer.append(json_type["description"])
640                     writer.append(" */\n")
641
642             @staticmethod
643             def add_to_forward_listener(forward_listener):
644                 forward_listener.add_type_data(type_data)
645
646
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)
649
650     @staticmethod
651     def create_ad_hoc_type_declaration(json_typable, context_domain_name, ad_hoc_type_context):
652         class Helper:
653             is_ad_hoc = True
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
656
657             @staticmethod
658             def write_doc(writer):
659                 pass
660
661             @staticmethod
662             def add_to_forward_listener(forward_listener):
663                 pass
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)
666
667     @staticmethod
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:
671
672                 class EnumBinding:
673                     need_user_runtime_cast_ = False
674                     need_internal_runtime_cast_ = False
675
676                     @classmethod
677                     def resolve_inner(cls, resolve_context):
678                         pass
679
680                     @classmethod
681                     def request_user_runtime_cast(cls, request):
682                         if request:
683                             cls.need_user_runtime_cast_ = True
684                             request.acknowledge()
685
686                     @classmethod
687                     def request_internal_runtime_cast(cls):
688                         cls.need_internal_runtime_cast_ = True
689
690                     @classmethod
691                     def get_code_generator(enum_binding_cls):
692
693                         class CodeGenerator:
694                             @staticmethod
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)
706
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]
711                                     writer.newline("        ")
712                                     writer.append(item_c_name)
713                                     writer.append(" = ")
714                                     writer.append("%s" % enum_pos)
715                                     writer.append(",\n")
716                                 writer.newline("    };\n")
717                                 if enum_binding_cls.need_user_runtime_cast_:
718                                     raise Exception("Not yet implemented")
719
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)
724
725                                     validator_writer = generate_context.validator_writer
726
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")
732                                     if len(enum) > 0:
733                                         condition_list = []
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")
739
740                                     validator_writer.newline("\n\n")
741
742                                 writer.newline("}; // struct ")
743                                 writer.append(enum_name)
744                                 writer.append("\n\n")
745
746                             @staticmethod
747                             def register_use(forward_listener):
748                                 pass
749
750                             @staticmethod
751                             def get_generate_pass_id():
752                                 return TypeBuilderPass.MAIN
753
754                         return CodeGenerator
755
756                     @classmethod
757                     def get_validator_call_text(cls):
758                         return helper.full_name_prefix_for_use + fixed_type_name.class_name + "::assertCorrectValue"
759
760                     @classmethod
761                     def get_array_item_c_type_text(cls):
762                         return helper.full_name_prefix_for_use + fixed_type_name.class_name + "::Enum"
763
764                     @staticmethod
765                     def get_setter_value_expression_pattern():
766                         return "TypeBuilder::getEnumConstantValue(%s)"
767
768                     @staticmethod
769                     def reduce_to_raw_type():
770                         return RawTypes.String
771
772                     @staticmethod
773                     def get_type_model():
774                         return TypeModel.Enum(helper.full_name_prefix_for_use + fixed_type_name.class_name)
775
776                 return EnumBinding
777             else:
778                 if helper.is_ad_hoc:
779
780                     class PlainString:
781                         @classmethod
782                         def resolve_inner(cls, resolve_context):
783                             pass
784
785                         @staticmethod
786                         def request_user_runtime_cast(request):
787                             raise Exception("Unsupported")
788
789                         @staticmethod
790                         def request_internal_runtime_cast():
791                             pass
792
793                         @staticmethod
794                         def get_code_generator():
795                             return None
796
797                         @classmethod
798                         def get_validator_call_text(cls):
799                             return RawTypes.String.get_raw_validator_call_text()
800
801                         @staticmethod
802                         def reduce_to_raw_type():
803                             return RawTypes.String
804
805                         @staticmethod
806                         def get_type_model():
807                             return TypeModel.String
808
809                         @staticmethod
810                         def get_setter_value_expression_pattern():
811                             return None
812
813                         @classmethod
814                         def get_array_item_c_type_text(cls):
815                             return cls.reduce_to_raw_type().get_array_item_raw_c_type_text()
816
817                     return PlainString
818
819                 else:
820
821                     class TypedefString:
822                         @classmethod
823                         def resolve_inner(cls, resolve_context):
824                             pass
825
826                         @staticmethod
827                         def request_user_runtime_cast(request):
828                             raise Exception("Unsupported")
829
830                         @staticmethod
831                         def request_internal_runtime_cast():
832                             pass
833
834                         @staticmethod
835                         def get_code_generator():
836                             class CodeGenerator:
837                                 @staticmethod
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")
844
845                                 @staticmethod
846                                 def register_use(forward_listener):
847                                     pass
848
849                                 @staticmethod
850                                 def get_generate_pass_id():
851                                     return TypeBuilderPass.TYPEDEF
852
853                             return CodeGenerator
854
855                         @classmethod
856                         def get_validator_call_text(cls):
857                             return RawTypes.String.get_raw_validator_call_text()
858
859                         @staticmethod
860                         def reduce_to_raw_type():
861                             return RawTypes.String
862
863                         @staticmethod
864                         def get_type_model():
865                             return TypeModel.ValueType("%s%s" % (helper.full_name_prefix_for_use, fixed_type_name.class_name), True)
866
867                         @staticmethod
868                         def get_setter_value_expression_pattern():
869                             return None
870
871                         @classmethod
872                         def get_array_item_c_type_text(cls):
873                             return "%s%s" % (helper.full_name_prefix_for_use, fixed_type_name.class_name)
874
875                     return TypedefString
876
877         elif json_typable["type"] == "object":
878             if "properties" in json_typable:
879
880                 class ClassBinding:
881                     resolve_data_ = None
882                     need_user_runtime_cast_ = False
883                     need_internal_runtime_cast_ = False
884
885                     @classmethod
886                     def resolve_inner(cls, resolve_context):
887                         if cls.resolve_data_:
888                             return
889
890                         properties = json_typable["properties"]
891                         main = []
892                         optional = []
893
894                         ad_hoc_type_list = []
895
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)
900
901                             code_generator = binding.get_code_generator()
902                             if code_generator:
903                                 code_generator.register_use(resolve_context.forward_listener)
904
905                             class PropertyData:
906                                 param_type_binding = binding
907                                 p = prop
908
909                             if prop.get("optional"):
910                                 optional.append(PropertyData)
911                             else:
912                                 main.append(PropertyData)
913
914                         class ResolveData:
915                             main_properties = main
916                             optional_properties = optional
917                             ad_hoc_types = ad_hoc_type_list
918
919                         cls.resolve_data_ = ResolveData
920
921                         for ad_hoc in ad_hoc_type_list:
922                             ad_hoc.resolve_inner(resolve_context)
923
924                     @classmethod
925                     def request_user_runtime_cast(cls, request):
926                         if not request:
927                             return
928                         cls.need_user_runtime_cast_ = True
929                         request.acknowledge()
930                         cls.request_internal_runtime_cast()
931
932                     @classmethod
933                     def request_internal_runtime_cast(cls):
934                         if cls.need_internal_runtime_cast_:
935                             return
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()
941
942                     @classmethod
943                     def get_code_generator(class_binding_cls):
944                         class CodeGenerator:
945                             @classmethod
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
950
951                                 is_open_type = (context_domain_name + "." + class_name) in TYPES_WITH_OPEN_FIELD_LIST_SET
952
953                                 fixed_type_name.output_comment(writer)
954                                 writer.newline("class ")
955                                 writer.append(class_name)
956                                 writer.append(" : public ")
957                                 if is_open_type:
958                                     writer.append("JSONObject")
959                                 else:
960                                     writer.append("JSONObjectBase")
961                                 writer.append(" {\n")
962                                 writer.newline("public:\n")
963                                 ad_hoc_type_writer = writer.insert_writer("    ")
964
965                                 for ad_hoc_type in resolve_data.ad_hoc_types:
966                                     code_generator = ad_hoc_type.get_code_generator()
967                                     if code_generator:
968                                         code_generator.generate_type_builder(ad_hoc_type_writer, generate_context)
969
970                                 writer.newline_multiline(
971 """    enum {
972         NoFieldsSet = 0,
973 """)
974
975                                 state_enum_items = []
976                                 if len(resolve_data.main_properties) > 0:
977                                     pos = 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))
982                                         pos += 1
983                                     all_fields_set_value = "(" + (" | ".join(state_enum_items)) + ")"
984                                 else:
985                                     all_fields_set_value = "0"
986
987                                 writer.newline_multiline(CodeGeneratorInspectorStrings.class_binding_builder_part_1
988                                                          % (all_fields_set_value, class_name, class_name))
989
990                                 pos = 0
991                                 for prop_data in resolve_data.main_properties:
992                                     prop_name = prop_data.p["name"]
993
994                                     param_type_binding = prop_data.param_type_binding
995                                     param_raw_type = param_type_binding.reduce_to_raw_type()
996
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]))
1005
1006                                     pos += 1
1007
1008                                 writer.newline_multiline(CodeGeneratorInspectorStrings.class_binding_builder_part_3
1009                                                          % (class_name, class_name, class_name, class_name, class_name))
1010
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")
1017
1018                                 writer.newline_multiline(CodeGeneratorInspectorStrings.class_binding_builder_part_4)
1019
1020                                 writer.newline("    typedef TypeBuilder::StructItemTraits ItemTraits;\n")
1021
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")
1032
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)
1037
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")
1045
1046                                     if setter_name in INSPECTOR_OBJECT_SETTER_NAMES:
1047                                         writer.newline("    using JSONObjectBase::%s;\n\n" % setter_name)
1048
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")
1061                                     writer.append("\n")
1062
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)
1067
1068                                     closed_field_set = (context_domain_name + "." + class_name) not in TYPES_WITH_OPEN_FIELD_LIST_SET
1069
1070                                     validator_writer = generate_context.validator_writer
1071
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")
1085
1086                                     if closed_field_set:
1087                                         validator_writer.newline("    int foundPropertiesCount = %s;\n" % len(resolve_data.main_properties))
1088
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")
1100
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")
1106
1107                                     validator_writer.newline("\n\n")
1108
1109                                 if is_open_type:
1110                                     cpp_writer = generate_context.cpp_writer
1111                                     writer.append("\n")
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))
1118
1119
1120                                 writer.newline("};\n\n")
1121
1122                             @staticmethod
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")
1128
1129                             @staticmethod
1130                             def register_use(forward_listener):
1131                                 helper.add_to_forward_listener(forward_listener)
1132
1133                             @staticmethod
1134                             def get_generate_pass_id():
1135                                 return TypeBuilderPass.MAIN
1136
1137                         return CodeGenerator
1138
1139                     @staticmethod
1140                     def get_validator_call_text():
1141                         return helper.full_name_prefix_for_use + fixed_type_name.class_name + "::assertCorrectValue"
1142
1143                     @classmethod
1144                     def get_array_item_c_type_text(cls):
1145                         return helper.full_name_prefix_for_use + fixed_type_name.class_name
1146
1147                     @staticmethod
1148                     def get_setter_value_expression_pattern():
1149                         return None
1150
1151                     @staticmethod
1152                     def reduce_to_raw_type():
1153                         return RawTypes.Object
1154
1155                     @staticmethod
1156                     def get_type_model():
1157                         return TypeModel.RefPtrBased(helper.full_name_prefix_for_use + fixed_type_name.class_name)
1158
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 = ""
1167
1168                         def get_type_name_fix(self):
1169                             class NameFix:
1170                                 class_name = Capitalizer.lower_camel_case_to_upper(self.property_name)
1171
1172                                 @staticmethod
1173                                 def output_comment(writer):
1174                                     writer.newline("// Named after property name '%s' while generating %s.\n" % (self.property_name, self.class_name))
1175
1176                             return NameFix
1177
1178                         def add_type(self, binding):
1179                             self.ad_hoc_type_list.append(binding)
1180
1181                 return ClassBinding
1182             else:
1183
1184                 class PlainObjectBinding:
1185                     @classmethod
1186                     def resolve_inner(cls, resolve_context):
1187                         pass
1188
1189                     @staticmethod
1190                     def request_user_runtime_cast(request):
1191                         pass
1192
1193                     @staticmethod
1194                     def request_internal_runtime_cast():
1195                         pass
1196
1197                     @staticmethod
1198                     def get_code_generator():
1199                         pass
1200
1201                     @staticmethod
1202                     def get_validator_call_text():
1203                         return "RuntimeCastHelper::assertType<JSONValue::TypeObject>"
1204
1205                     @classmethod
1206                     def get_array_item_c_type_text(cls):
1207                         return cls.reduce_to_raw_type().get_array_item_raw_c_type_text()
1208
1209                     @staticmethod
1210                     def get_setter_value_expression_pattern():
1211                         return None
1212
1213                     @staticmethod
1214                     def reduce_to_raw_type():
1215                         return RawTypes.Object
1216
1217                     @staticmethod
1218                     def get_type_model():
1219                         return TypeModel.Object
1220
1221                 return PlainObjectBinding
1222         elif json_typable["type"] == "array":
1223             if "items" in json_typable:
1224
1225                 ad_hoc_types = []
1226
1227                 class AdHocTypeContext:
1228                     container_full_name_prefix = "<not yet defined>"
1229                     container_relative_name_prefix = ""
1230
1231                     @staticmethod
1232                     def get_type_name_fix():
1233                         return fixed_type_name
1234
1235                     @staticmethod
1236                     def add_type(binding):
1237                         ad_hoc_types.append(binding)
1238
1239                 item_binding = resolve_param_type(json_typable["items"], context_domain_name, AdHocTypeContext)
1240
1241                 class ArrayBinding:
1242                     resolve_data_ = None
1243                     need_internal_runtime_cast_ = False
1244
1245                     @classmethod
1246                     def resolve_inner(cls, resolve_context):
1247                         if cls.resolve_data_:
1248                             return
1249
1250                         class ResolveData:
1251                             item_type_binding = item_binding
1252                             ad_hoc_type_list = ad_hoc_types
1253
1254                         cls.resolve_data_ = ResolveData
1255
1256                         for t in ad_hoc_types:
1257                             t.resolve_inner(resolve_context)
1258
1259                     @classmethod
1260                     def request_user_runtime_cast(cls, request):
1261                         raise Exception("Not implemented yet")
1262
1263                     @classmethod
1264                     def request_internal_runtime_cast(cls):
1265                         if cls.need_internal_runtime_cast_:
1266                             return
1267                         cls.need_internal_runtime_cast_ = True
1268                         cls.resolve_data_.item_type_binding.request_internal_runtime_cast()
1269
1270                     @classmethod
1271                     def get_code_generator(array_binding_cls):
1272
1273                         class CodeGenerator:
1274                             @staticmethod
1275                             def generate_type_builder(writer, generate_context):
1276                                 ad_hoc_type_writer = writer
1277
1278                                 resolve_data = array_binding_cls.resolve_data_
1279
1280                                 for ad_hoc_type in resolve_data.ad_hoc_type_list:
1281                                     code_generator = ad_hoc_type.get_code_generator()
1282                                     if code_generator:
1283                                         code_generator.generate_type_builder(ad_hoc_type_writer, generate_context)
1284
1285                             @staticmethod
1286                             def generate_forward_declaration(writer):
1287                                 pass
1288
1289                             @staticmethod
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)
1294
1295                             @staticmethod
1296                             def get_generate_pass_id():
1297                                 return TypeBuilderPass.MAIN
1298
1299                         return CodeGenerator
1300
1301                     @classmethod
1302                     def get_validator_call_text(cls):
1303                         return cls.get_array_item_c_type_text() + "::assertCorrectValue"
1304
1305                     @classmethod
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())
1308
1309                     @staticmethod
1310                     def get_setter_value_expression_pattern():
1311                         return None
1312
1313                     @staticmethod
1314                     def reduce_to_raw_type():
1315                         return RawTypes.Array
1316
1317                     @classmethod
1318                     def get_type_model(cls):
1319                         return TypeModel.RefPtrBased(cls.get_array_item_c_type_text())
1320
1321                 return ArrayBinding
1322             else:
1323                 # Fall-through to raw type.
1324                 pass
1325
1326         raw_type = RawTypes.get(json_typable["type"])
1327
1328         return RawTypeBinding(raw_type)
1329
1330
1331 class RawTypeBinding:
1332     def __init__(self, raw_type):
1333         self.raw_type_ = raw_type
1334
1335     def resolve_inner(self, resolve_context):
1336         pass
1337
1338     def request_user_runtime_cast(self, request):
1339         raise Exception("Unsupported")
1340
1341     def request_internal_runtime_cast(self):
1342         pass
1343
1344     def get_code_generator(self):
1345         return None
1346
1347     def get_validator_call_text(self):
1348         return self.raw_type_.get_raw_validator_call_text()
1349
1350     def get_array_item_c_type_text(self):
1351         return self.raw_type_.get_array_item_raw_c_type_text()
1352
1353     def get_setter_value_expression_pattern(self):
1354         return None
1355
1356     def reduce_to_raw_type(self):
1357         return self.raw_type_
1358
1359     def get_type_model(self):
1360         return self.raw_type_.get_raw_type_model()
1361
1362
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
1368
1369         if "type" not in json_type:
1370             raise Exception("Unknown type")
1371
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
1377
1378     def get_raw_type(self):
1379         return self.raw_type_
1380
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
1387             try:
1388                 self.binding_ = TypeBindings.create_named_type_declaration(self.json_type_, self.json_domain_["domain"], self)
1389             finally:
1390                 self.binding_being_resolved_ = False
1391
1392         return self.binding_
1393
1394     def get_json_type(self):
1395         return self.json_type_
1396
1397     def get_name(self):
1398         return self.json_type_["id"]
1399
1400     def get_domain_name(self):
1401         return self.json_domain_["domain"]
1402
1403
1404 class DomainData:
1405     def __init__(self, json_domain):
1406         self.json_domain = json_domain
1407         self.types_ = []
1408
1409     def add_type(self, type_data):
1410         self.types_.append(type_data)
1411
1412     def name(self):
1413         return self.json_domain["domain"]
1414
1415     def types(self):
1416         return self.types_
1417
1418
1419 class TypeMap:
1420     def __init__(self, api):
1421         self.map_ = {}
1422         self.domains_ = []
1423         for json_domain in api["domains"]:
1424             domain_name = json_domain["domain"]
1425
1426             domain_map = {}
1427             self.map_[domain_name] = domain_map
1428
1429             domain_data = DomainData(json_domain)
1430             self.domains_.append(domain_data)
1431
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)
1438
1439     def domains(self):
1440         return self.domains_
1441
1442     def get(self, domain_name, type_name):
1443         return self.map_[domain_name][type_name]
1444
1445
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)
1454         return result
1455     else:
1456         raise Exception("Unknown type")
1457
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)
1466     else:
1467         raise Exception("Unknown type")
1468
1469
1470 def get_ref_data(json_ref, scope_domain_name):
1471     dot_pos = json_ref.find(".")
1472     if dot_pos == -1:
1473         domain_name = scope_domain_name
1474         type_name = json_ref
1475     else:
1476         domain_name = json_ref[:dot_pos]
1477         type_name = json_ref[dot_pos + 1:]
1478
1479     return type_map.get(domain_name, type_name)
1480
1481
1482 input_file = open(input_json_filename, "r")
1483 json_string = input_file.read()
1484 json_api = json.loads(json_string)
1485
1486
1487 class Templates:
1488     def get_this_script_path_(absolute_path):
1489         absolute_path = os.path.abspath(absolute_path)
1490         components = []
1491
1492         def fill_recursive(path_part, depth):
1493             if depth <= 0 or path_part == '/':
1494                 return
1495             fill_recursive(os.path.dirname(path_part), depth - 1)
1496             components.append(os.path.basename(path_part))
1497
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)
1501
1502         return "/".join(components)
1503
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.
1508 """)
1509
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
1522
1523
1524
1525
1526
1527 type_map = TypeMap(json_api)
1528
1529
1530 class NeedRuntimeCastRequest:
1531     def __init__(self):
1532         self.ack_ = None
1533
1534     def acknowledge(self):
1535         self.ack_ = True
1536
1537     def is_acknowledged(self):
1538         return self.ack_
1539
1540
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()
1545
1546     class ForwardListener:
1547         type_data_set = set()
1548         already_declared_set = set()
1549
1550         @classmethod
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)
1554
1555     class ResolveContext:
1556         forward_listener = ForwardListener
1557
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)
1562
1563             binding = type_data.get_binding()
1564             binding.resolve_inner(ResolveContext)
1565
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()
1571             if request:
1572                 binding.request_user_runtime_cast(request)
1573
1574             if request and not request.is_acknowledged():
1575                 raise Exception("Failed to generate runtimeCast in " + full_type_name)
1576
1577     for full_type_name in runtime_cast_generate_requests:
1578         raise Exception("Failed to generate runtimeCast. Type " + full_type_name + " not found")
1579
1580     return ForwardListener
1581
1582
1583 global_forward_listener = resolve_all_types()
1584
1585
1586 def get_annotated_type_text(raw_type, annotated_type):
1587     if annotated_type != raw_type:
1588         return "/*%s*/ %s" % (annotated_type, raw_type)
1589     else:
1590         return raw_type
1591
1592
1593 def format_setter_value_expression(param_type_binding, value_ref):
1594     pattern = param_type_binding.get_setter_value_expression_pattern()
1595     if pattern:
1596         return pattern % value_ref
1597     else:
1598         return value_ref
1599
1600 class Generator:
1601     frontend_class_field_lines = []
1602     frontend_domain_class_lines = []
1603
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 = []
1612
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 = []
1623
1624
1625     @staticmethod
1626     def go():
1627         Generator.process_types(type_map)
1628
1629         for json_domain in json_api["domains"]:
1630             domain_name = json_domain["domain"]
1631             domain_name_lower = domain_name.lower()
1632
1633             agent_field_name = DomainNameFixes.get_fixed_data(domain_name)
1634
1635             frontend_method_declaration_lines = []
1636
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)
1640
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))))
1649
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")
1659
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))
1664
1665     @staticmethod
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"]))):
1668             return
1669
1670         event_name = json_event["name"]
1671
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, "        ")
1675
1676         decl_parameter_list = []
1677
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})
1683
1684         frontend_method_declaration_lines.append(
1685             "        void %s(%s);\n" % (event_name, ", ".join(decl_parameter_list)))
1686
1687     class EventMethodStructTemplate:
1688         @staticmethod
1689         def append_prolog(line_list):
1690             line_list.append("    RefPtr<JSONObject> paramsObject = JSONObject::create();\n")
1691
1692         @staticmethod
1693         def append_epilog(line_list):
1694             line_list.append("    jsonMessage->setObject(\"params\", paramsObject);\n")
1695
1696         container_name = "paramsObject"
1697
1698     @staticmethod
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"]))):
1701             return
1702
1703         json_command_name = json_command["name"]
1704
1705         cmd_enum_name = "k%s_%sCmd" % (domain_name, json_command["name"])
1706
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))
1710
1711         backend_agent_interface_list = [] if "redirect" in json_command else Generator.backend_agent_interface_list
1712
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, "        ")
1716
1717         backend_agent_interface_list.append("        virtual void %s(ErrorString*" % json_command_name)
1718
1719         method_in_code = ""
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")
1736
1737         if "parameters" in json_command:
1738             json_params = json_command["parameters"]
1739             request_message_param = " requestMessageObject"
1740
1741             if json_params:
1742                 method_in_code += Templates.param_container_access_code
1743
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)
1747
1748                 getter_name = param_raw_type.get_getter_name()
1749
1750                 optional = json_parameter.get("optional")
1751
1752                 non_optional_type_model = param_raw_type.get_raw_type_model()
1753
1754                 if optional:
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*"
1761                 else:
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&"
1768                     else:
1769                         formal_param_type_pattern = "%s"
1770
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))
1774
1775         if json_command.get("async") == True:
1776             callback_name = Capitalizer.lower_camel_case_to_upper(json_command_name) + "Callback"
1777
1778             callback_output = []
1779             callback_writer = Writer(callback_output, ad_hoc_type_writer.get_indent())
1780
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})
1787
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")
1794
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")
1799
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
1802
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))
1808
1809             ad_hoc_type_output.append(callback_output)
1810
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)
1817         else:
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"]:
1824
1825                     json_return_name = json_return["name"]
1826
1827                     optional = bool(json_return.get("optional"))
1828
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 + "::")
1830
1831                     raw_type = return_type_binding.reduce_to_raw_type()
1832                     setter_type = raw_type.get_setter_name()
1833
1834                     type_model = return_type_binding.get_type_model()
1835                     if optional:
1836                         type_model = type_model.get_optional()
1837
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
1844
1845                     cook = "        result->set%s(\"%s\", %s);\n" % (setter_type, json_return_name,
1846                                                                          setter_argument)
1847
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()
1852
1853                     param_name = var_name
1854                     if optional:
1855                         param_name = "opt_" + param_name
1856
1857                     backend_agent_interface_list.append(", %s %s" % (annotated_type, param_name))
1858                     response_cook_list.append(cook)
1859
1860                     method_out_code += code
1861                     agent_call_param_list.append(param)
1862
1863                 normal_response_cook_text += "".join(response_cook_list)
1864
1865                 if len(normal_response_cook_text) != 0:
1866                     normal_response_cook_text = "    if (!error.length()) {\n" + normal_response_cook_text + "    }"
1867
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"))
1872
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
1887
1888         backend_agent_interface_list.append(") = 0;\n")
1889
1890     class CallbackMethodStructTemplate:
1891         @staticmethod
1892         def append_prolog(line_list):
1893             pass
1894
1895         @staticmethod
1896         def append_epilog(line_list):
1897             pass
1898
1899         container_name = "jsonMessage"
1900
1901     # Generates common code for event sending and callback response data sending.
1902     @staticmethod
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 = []
1907         if parameters:
1908             method_struct_template.append_prolog(method_line_list)
1909             for json_parameter in parameters:
1910                 parameter_name = json_parameter["name"]
1911
1912                 param_type_binding = Generator.resolve_param_type_and_generate_ad_hoc(json_parameter, event_name, domain_name, ad_hoc_type_writer, "")
1913
1914                 raw_type = param_type_binding.reduce_to_raw_type()
1915                 raw_type_binding = RawTypeBinding(raw_type)
1916
1917                 optional = bool(json_parameter.get("optional"))
1918
1919                 setter_type = raw_type.get_setter_name()
1920
1921                 type_model = param_type_binding.get_type_model()
1922                 raw_type_model = raw_type_binding.get_type_model()
1923                 if optional:
1924                     type_model = type_model.get_optional()
1925                     raw_type_model = raw_type_model.get_optional()
1926
1927                 annotated_type = type_model.get_input_param_type_text()
1928                 mode_type_binding = param_type_binding
1929
1930                 decl_parameter_list.append("%s %s" % (annotated_type, parameter_name))
1931
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
1935
1936                 setter_code = "    %s->set%s(\"%s\", %s);\n" % (method_struct_template.container_name, setter_type, parameter_name, setter_argument)
1937                 if optional:
1938                     setter_code = ("    if (%s)\n    " % parameter_name) + setter_code
1939                 method_line_list.append(setter_code)
1940
1941             method_struct_template.append_epilog(method_line_list)
1942
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))
1947
1948     @classmethod
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)
1952
1953     @staticmethod
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 = []
1956
1957         class AdHocTypeContext:
1958             container_full_name_prefix = "<not yet defined>"
1959             container_relative_name_prefix = container_relative_name_prefix_param
1960
1961             @staticmethod
1962             def get_type_name_fix():
1963                 class NameFix:
1964                     class_name = Capitalizer.lower_camel_case_to_upper(element_name)
1965
1966                     @staticmethod
1967                     def output_comment(writer):
1968                         writer.newline("// Named after parameter '%s' while generating command/event %s.\n" % (element_name, method_name))
1969
1970                 return NameFix
1971
1972             @staticmethod
1973             def add_type(binding):
1974                 ad_hoc_type_list.append(binding)
1975
1976         type_binding = resolve_param_type(typable_element, domain_name, AdHocTypeContext)
1977
1978         class InterfaceForwardListener:
1979             @staticmethod
1980             def add_type_data(type_data):
1981                 pass
1982
1983         class InterfaceResolveContext:
1984             forward_listener = InterfaceForwardListener
1985
1986         for type in ad_hoc_type_list:
1987             type.resolve_inner(InterfaceResolveContext)
1988
1989         class InterfaceGenerateContext:
1990             validator_writer = "not supported in InterfaceGenerateContext"
1991             cpp_writer = validator_writer
1992
1993         for type in ad_hoc_type_list:
1994             generator = type.get_code_generator()
1995             if generator:
1996                 generator.generate_type_builder(ad_hoc_type_writer, InterfaceGenerateContext)
1997
1998         return type_binding
1999
2000     @staticmethod
2001     def process_types(type_map):
2002         output = Generator.type_builder_fragments
2003
2004         class GenerateContext:
2005             validator_writer = Writer(Generator.validator_impl_list, "")
2006             cpp_writer = Writer(Generator.type_builder_impl_list, "")
2007
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 = []
2012
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)
2020                     return writer
2021
2022                 for type_data in domain_data.types():
2023                     type_data_callback(type_data, namespace_lazy_generator)
2024
2025                 if namespace_declared:
2026                     writer.append("} // ")
2027                     writer.append(domain_data.name())
2028                     writer.append("\n\n")
2029
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()
2035
2036                     code_generator.generate_type_builder(writer, GenerateContext)
2037             return call_type_builder
2038
2039         generate_all_domains_code(output, create_type_builder_caller(TypeBuilderPass.MAIN))
2040
2041         Generator.type_builder_forwards.append("// Forward declarations.\n")
2042
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)
2048
2049         Generator.type_builder_forwards.append("// End of forward declarations.\n\n")
2050
2051         Generator.type_builder_forwards.append("// Typedefs.\n")
2052
2053         generate_all_domains_code(Generator.type_builder_forwards, create_type_builder_caller(TypeBuilderPass.TYPEDEF))
2054
2055         Generator.type_builder_forwards.append("// End of typedefs.\n\n")
2056
2057
2058 def flatten_list(input):
2059     res = []
2060
2061     def fill_recursive(l):
2062         for item in l:
2063             if isinstance(item, list):
2064                 fill_recursive(item)
2065             else:
2066                 res.append(item)
2067     fill_recursive(input)
2068     return res
2069
2070 def output_file(file_name):
2071     return open(file_name, "w")
2072
2073
2074 Generator.go()
2075
2076 backend_h_file = output_file(output_dirname + "/InspectorBackendDispatcher.h")
2077 backend_cpp_file = output_file(output_dirname + "/InspectorBackendDispatcher.cpp")
2078
2079 frontend_h_file = output_file(output_dirname + "/InspectorFrontend.h")
2080 frontend_cpp_file = output_file(output_dirname + "/InspectorFrontend.cpp")
2081
2082 typebuilder_h_file = output_file(output_dirname + "/InspectorTypeBuilder.h")
2083 typebuilder_cpp_file = output_file(output_dirname + "/InspectorTypeBuilder.cpp")
2084
2085
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)))
2090
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)))
2100
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)))
2104
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)))
2108
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))
2113
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))
2119
2120 backend_h_file.close()
2121 backend_cpp_file.close()
2122
2123 frontend_h_file.close()
2124 frontend_cpp_file.close()
2125
2126 typebuilder_h_file.close()
2127 typebuilder_cpp_file.close()