ce6dae1d6a62b7b97c4c1e9e2d55716dea11ac3b
[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.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 EXACTLY_INT_SUPPORTED = False
61
62 cmdline_parser = optparse.OptionParser()
63 cmdline_parser.add_option("--output_dir")
64
65 try:
66     arg_options, arg_values = cmdline_parser.parse_args()
67     if (len(arg_values) != 1):
68         raise Exception("Exactly one plain argument expected (found %s)" % len(arg_values))
69     input_json_filename = arg_values[0]
70     output_dirname = arg_options.output_dir
71     if not output_dirname:
72         raise Exception("Output directory must be specified")
73 except Exception:
74     # Work with python 2 and 3 http://docs.python.org/py3k/howto/pyporting.html
75     exc = sys.exc_info()[1]
76     sys.stderr.write("Failed to parse command-line arguments: %s\n\n" % exc)
77     sys.stderr.write("Usage: <script> --output_dir <output_dir> protocol.json\n")
78     exit(1)
79
80
81 # FIXME: move this methods under Capitalizer class below and remove duplications.
82 def dash_to_camelcase(word):
83     return ''.join(x.capitalize() or '-' for x in word.split('-'))
84
85
86 def fix_camel_case(name):
87     refined = re.sub(r'-(\w)', lambda pat: pat.group(1).upper(), name)
88     refined = to_title_case(refined)
89     return re.sub(r'(?i)HTML|XML|WML|API', lambda pat: pat.group(0).upper(), refined)
90
91
92 def to_title_case(name):
93     return name[:1].upper() + name[1:]
94
95
96 class Capitalizer:
97     @staticmethod
98     def lower_camel_case_to_upper(str):
99         if len(str) > 0 and str[0].islower():
100             str = str[0].upper() + str[1:]
101         return str
102
103     @staticmethod
104     def upper_camel_case_to_lower(str):
105         pos = 0
106         while pos < len(str) and str[pos].isupper():
107             pos += 1
108         if pos == 0:
109             return str
110         if pos == 1:
111             return str[0].lower() + str[1:]
112         if pos < len(str):
113             pos -= 1
114         possible_abbreviation = str[0:pos]
115         if possible_abbreviation not in Capitalizer.ABBREVIATION:
116             raise Exception("Unknown abbreviation %s" % possible_abbreviation)
117         str = possible_abbreviation.lower() + str[pos:]
118         return str
119
120     @staticmethod
121     def camel_case_to_capitalized_with_underscores(str):
122         if len(str) == 0:
123             return str
124         output = Capitalizer.split_camel_case_(str)
125         return "_".join(output).upper()
126
127     @staticmethod
128     def split_camel_case_(str):
129         output = []
130         pos_being = 0
131         pos = 1
132         has_oneletter = False
133         while pos < len(str):
134             if str[pos].isupper():
135                 output.append(str[pos_being:pos].upper())
136                 if pos - pos_being == 1:
137                     has_oneletter = True
138                 pos_being = pos
139             pos += 1
140         output.append(str[pos_being:])
141         if has_oneletter:
142             array_pos = 0
143             while array_pos < len(output) - 1:
144                 if len(output[array_pos]) == 1:
145                     array_pos_end = array_pos + 1
146                     while array_pos_end < len(output) and len(output[array_pos_end]) == 1:
147                         array_pos_end += 1
148                     if array_pos_end - array_pos > 1:
149                         possible_abbreviation = "".join(output[array_pos:array_pos_end])
150                         if possible_abbreviation.upper() in Capitalizer.ABBREVIATION:
151                             output[array_pos:array_pos_end] = [possible_abbreviation]
152                         else:
153                             array_pos = array_pos_end - 1
154                 array_pos += 1
155         return output
156
157     ABBREVIATION = frozenset(["XHR", "DOM", "CSS"])
158
159 VALIDATOR_IFDEF_NAME = "ASSERT_ENABLED"
160
161
162 class DomainNameFixes:
163     @classmethod
164     def get_fixed_data(cls, domain_name):
165         field_name_res = Capitalizer.upper_camel_case_to_lower(domain_name) + "Agent"
166
167         class Res(object):
168             agent_field_name = field_name_res
169
170         return Res
171
172
173 class RawTypes(object):
174     @staticmethod
175     def get(json_type):
176         if json_type == "boolean":
177             return RawTypes.Bool
178         elif json_type == "string":
179             return RawTypes.String
180         elif json_type == "array":
181             return RawTypes.Array
182         elif json_type == "object":
183             return RawTypes.Object
184         elif json_type == "integer":
185             return RawTypes.Int
186         elif json_type == "number":
187             return RawTypes.Number
188         elif json_type == "any":
189             return RawTypes.Any
190         else:
191             raise Exception("Unknown type: %s" % json_type)
192
193     # For output parameter all values are passed by pointer except RefPtr-based types.
194     class OutputPassModel:
195         class ByPointer:
196             @staticmethod
197             def get_argument_prefix():
198                 return "&"
199
200             @staticmethod
201             def get_parameter_type_suffix():
202                 return "*"
203
204         class ByReference:
205             @staticmethod
206             def get_argument_prefix():
207                 return ""
208
209             @staticmethod
210             def get_parameter_type_suffix():
211                 return "&"
212
213     class BaseType(object):
214         need_internal_runtime_cast_ = False
215
216         @classmethod
217         def request_raw_internal_runtime_cast(cls):
218             if not cls.need_internal_runtime_cast_:
219                 cls.need_internal_runtime_cast_ = True
220
221         @classmethod
222         def get_raw_validator_call_text(cls):
223             return "RuntimeCastHelper::assertType<JSONValue::Type%s>" % cls.get_validate_method_params().template_type
224
225         @staticmethod
226         def get_validate_method_params():
227             raise Exception("Abstract method")
228
229     class String(BaseType):
230         @staticmethod
231         def get_getter_name():
232             return "String"
233
234         get_setter_name = get_getter_name
235
236         @staticmethod
237         def get_constructor_pattern():
238             return "InspectorString::create(%s)"
239
240         @staticmethod
241         def get_c_initializer():
242             return "\"\""
243
244         @staticmethod
245         def get_validate_method_params():
246             class ValidateMethodParams:
247                 template_type = "String"
248             return ValidateMethodParams
249
250         @staticmethod
251         def get_output_pass_model():
252             return RawTypes.OutputPassModel.ByPointer
253
254         @staticmethod
255         def is_heavy_value():
256             return True
257
258         @staticmethod
259         def get_array_item_raw_c_type_text():
260             return "String"
261
262         @staticmethod
263         def get_raw_type_model():
264             return TypeModel.String
265
266     class Int(BaseType):
267         @staticmethod
268         def get_getter_name():
269             return "Int"
270
271         @staticmethod
272         def get_setter_name():
273             return "Number"
274
275         @staticmethod
276         def get_constructor_pattern():
277             return "InspectorBasicValue::create(%s)"
278
279         @staticmethod
280         def get_c_initializer():
281             return "0"
282
283         @classmethod
284         def get_raw_validator_call_text(cls):
285             return "RuntimeCastHelper::assertInt"
286
287         @staticmethod
288         def get_output_pass_model():
289             return RawTypes.OutputPassModel.ByPointer
290
291         @staticmethod
292         def is_heavy_value():
293             return False
294
295         @staticmethod
296         def get_array_item_raw_c_type_text():
297             return "int"
298
299         @staticmethod
300         def get_raw_type_model():
301             return TypeModel.Int
302
303     class Number(BaseType):
304         @staticmethod
305         def get_getter_name():
306             return "Double"
307
308         @staticmethod
309         def get_setter_name():
310             return "Number"
311
312         @staticmethod
313         def get_constructor_pattern():
314             return "InspectorBasicValue::create(%s)"
315
316         @staticmethod
317         def get_c_initializer():
318             return "0"
319
320         @staticmethod
321         def get_validate_method_params():
322             class ValidateMethodParams:
323                 template_type = "Number"
324             return ValidateMethodParams
325
326         @staticmethod
327         def get_output_pass_model():
328             return RawTypes.OutputPassModel.ByPointer
329
330         @staticmethod
331         def is_heavy_value():
332             return False
333
334         @staticmethod
335         def get_array_item_raw_c_type_text():
336             return "double"
337
338         @staticmethod
339         def get_raw_type_model():
340             return TypeModel.Number
341
342     class Bool(BaseType):
343         @staticmethod
344         def get_getter_name():
345             return "Boolean"
346
347         get_setter_name = get_getter_name
348
349         @staticmethod
350         def get_constructor_pattern():
351             return "InspectorBasicValue::create(%s)"
352
353         @staticmethod
354         def get_c_initializer():
355             return "false"
356
357         @staticmethod
358         def get_validate_method_params():
359             class ValidateMethodParams:
360                 template_type = "Boolean"
361             return ValidateMethodParams
362
363         @staticmethod
364         def get_output_pass_model():
365             return RawTypes.OutputPassModel.ByPointer
366
367         @staticmethod
368         def is_heavy_value():
369             return False
370
371         @staticmethod
372         def get_array_item_raw_c_type_text():
373             return "bool"
374
375         @staticmethod
376         def get_raw_type_model():
377             return TypeModel.Bool
378
379     class Object(BaseType):
380         @staticmethod
381         def get_getter_name():
382             return "Object"
383
384         @staticmethod
385         def get_setter_name():
386             return "Value"
387
388         @staticmethod
389         def get_constructor_pattern():
390             return "%s"
391
392         @staticmethod
393         def get_c_initializer():
394             return "JSONObject::create()"
395
396         @staticmethod
397         def get_output_argument_prefix():
398             return ""
399
400         @staticmethod
401         def get_validate_method_params():
402             class ValidateMethodParams:
403                 template_type = "Object"
404             return ValidateMethodParams
405
406         @staticmethod
407         def get_output_pass_model():
408             return RawTypes.OutputPassModel.ByReference
409
410         @staticmethod
411         def is_heavy_value():
412             return True
413
414         @staticmethod
415         def get_array_item_raw_c_type_text():
416             return "JSONObject"
417
418         @staticmethod
419         def get_raw_type_model():
420             return TypeModel.Object
421
422     class Any(BaseType):
423         @staticmethod
424         def get_getter_name():
425             return "Value"
426
427         get_setter_name = get_getter_name
428
429         @staticmethod
430         def get_c_initializer():
431             raise Exception("Unsupported")
432
433         @staticmethod
434         def get_constructor_pattern():
435             raise Exception("Unsupported")
436
437         @staticmethod
438         def get_raw_validator_call_text():
439             return "RuntimeCastHelper::assertAny"
440
441         @staticmethod
442         def get_output_pass_model():
443             return RawTypes.OutputPassModel.ByReference
444
445         @staticmethod
446         def is_heavy_value():
447             return True
448
449         @staticmethod
450         def get_array_item_raw_c_type_text():
451             return "JSONValue"
452
453         @staticmethod
454         def get_raw_type_model():
455             return TypeModel.Any
456
457     class Array(BaseType):
458         @staticmethod
459         def get_getter_name():
460             return "Array"
461
462         @staticmethod
463         def get_setter_name():
464             return "Value"
465
466         @staticmethod
467         def get_constructor_pattern():
468             return "%s"
469
470         @staticmethod
471         def get_c_initializer():
472             return "JSONArray::create()"
473
474         @staticmethod
475         def get_output_argument_prefix():
476             return ""
477
478         @staticmethod
479         def get_validate_method_params():
480             class ValidateMethodParams:
481                 template_type = "Array"
482             return ValidateMethodParams
483
484         @staticmethod
485         def get_output_pass_model():
486             return RawTypes.OutputPassModel.ByReference
487
488         @staticmethod
489         def is_heavy_value():
490             return True
491
492         @staticmethod
493         def get_array_item_raw_c_type_text():
494             return "JSONArray"
495
496         @staticmethod
497         def get_raw_type_model():
498             return TypeModel.Array
499
500
501 def replace_right_shift(input_str):
502     return input_str.replace(">>", "> >")
503
504
505 class CommandReturnPassModel:
506     class ByReference:
507         def __init__(self, var_type, set_condition):
508             self.var_type = var_type
509             self.set_condition = set_condition
510
511         def get_return_var_type(self):
512             return self.var_type
513
514         @staticmethod
515         def get_output_argument_prefix():
516             return ""
517
518         @staticmethod
519         def get_output_to_raw_expression():
520             return "%s"
521
522         def get_output_parameter_type(self):
523             return self.var_type + "&"
524
525         def get_set_return_condition(self):
526             return self.set_condition
527
528     class ByPointer:
529         def __init__(self, var_type):
530             self.var_type = var_type
531
532         def get_return_var_type(self):
533             return self.var_type
534
535         @staticmethod
536         def get_output_argument_prefix():
537             return "&"
538
539         @staticmethod
540         def get_output_to_raw_expression():
541             return "%s"
542
543         def get_output_parameter_type(self):
544             return self.var_type + "*"
545
546         @staticmethod
547         def get_set_return_condition():
548             return None
549
550     class OptOutput:
551         def __init__(self, var_type):
552             self.var_type = var_type
553
554         def get_return_var_type(self):
555             return "TypeBuilder::OptOutput<%s>" % self.var_type
556
557         @staticmethod
558         def get_output_argument_prefix():
559             return "&"
560
561         @staticmethod
562         def get_output_to_raw_expression():
563             return "%s.getValue()"
564
565         def get_output_parameter_type(self):
566             return "TypeBuilder::OptOutput<%s>*" % self.var_type
567
568         @staticmethod
569         def get_set_return_condition():
570             return "%s.isAssigned()"
571
572
573 class TypeModel:
574     class RefPtrBased(object):
575         def __init__(self, class_name):
576             self.class_name = class_name
577             self.optional = False
578
579         def get_optional(self):
580             result = TypeModel.RefPtrBased(self.class_name)
581             result.optional = True
582             return result
583
584         def get_command_return_pass_model(self):
585             if self.optional:
586                 set_condition = "%s"
587             else:
588                 set_condition = None
589             return CommandReturnPassModel.ByReference(replace_right_shift("RefPtr<%s>" % self.class_name), set_condition)
590
591         def get_input_param_type_text(self):
592             return replace_right_shift("PassRefPtr<%s>" % self.class_name)
593
594         @staticmethod
595         def get_event_setter_expression_pattern():
596             return "%s"
597
598     class Enum(object):
599         def __init__(self, base_type_name):
600             self.type_name = base_type_name + "::Enum"
601
602         def get_optional(base_self):
603             class EnumOptional:
604                 @classmethod
605                 def get_optional(cls):
606                     return cls
607
608                 @staticmethod
609                 def get_command_return_pass_model():
610                     return CommandReturnPassModel.OptOutput(base_self.type_name)
611
612                 @staticmethod
613                 def get_input_param_type_text():
614                     return base_self.type_name + "*"
615
616                 @staticmethod
617                 def get_event_setter_expression_pattern():
618                     raise Exception("TODO")
619             return EnumOptional
620
621         def get_command_return_pass_model(self):
622             return CommandReturnPassModel.ByPointer(self.type_name)
623
624         def get_input_param_type_text(self):
625             return self.type_name
626
627         @staticmethod
628         def get_event_setter_expression_pattern():
629             return "%s"
630
631     class ValueType(object):
632         def __init__(self, type_name, is_heavy):
633             self.type_name = type_name
634             self.is_heavy = is_heavy
635
636         def get_optional(self):
637             return self.ValueOptional(self)
638
639         def get_command_return_pass_model(self):
640             return CommandReturnPassModel.ByPointer(self.type_name)
641
642         def get_input_param_type_text(self):
643             if self.is_heavy:
644                 return "const %s&" % self.type_name
645             else:
646                 return self.type_name
647
648         def get_opt_output_type_(self):
649             return self.type_name
650
651         @staticmethod
652         def get_event_setter_expression_pattern():
653             return "%s"
654
655         class ValueOptional:
656             def __init__(self, base):
657                 self.base = base
658
659             def get_optional(self):
660                 return self
661
662             def get_command_return_pass_model(self):
663                 return CommandReturnPassModel.OptOutput(self.base.get_opt_output_type_())
664
665             def get_input_param_type_text(self):
666                 return "const %s* const" % self.base.type_name
667
668             @staticmethod
669             def get_event_setter_expression_pattern():
670                 return "*%s"
671
672     class ExactlyInt(ValueType):
673         def __init__(self):
674             TypeModel.ValueType.__init__(self, "int", False)
675
676         def get_input_param_type_text(self):
677             return "TypeBuilder::ExactlyInt"
678
679         def get_opt_output_type_(self):
680             return "TypeBuilder::ExactlyInt"
681
682     @classmethod
683     def init_class(cls):
684         cls.Bool = cls.ValueType("bool", False)
685         if EXACTLY_INT_SUPPORTED:
686             cls.Int = cls.ExactlyInt()
687         else:
688             cls.Int = cls.ValueType("int", False)
689         cls.Number = cls.ValueType("double", False)
690         cls.String = cls.ValueType("String", True,)
691         cls.Object = cls.RefPtrBased("JSONObject")
692         cls.Array = cls.RefPtrBased("JSONArray")
693         cls.Any = cls.RefPtrBased("JSONValue")
694
695 TypeModel.init_class()
696
697
698 # Collection of JSONObject class methods that are likely to be overloaded in generated class.
699 # We must explicitly import all overloaded methods or they won't be available to user.
700 INSPECTOR_OBJECT_SETTER_NAMES = frozenset(["setValue", "setBoolean", "setNumber", "setString", "setValue", "setObject", "setArray"])
701
702
703 def fix_type_name(json_name):
704     if json_name in TYPE_NAME_FIX_MAP:
705         fixed = TYPE_NAME_FIX_MAP[json_name]
706
707         class Result(object):
708             class_name = fixed
709
710             @staticmethod
711             def output_comment(writer):
712                 writer.newline("// Type originally was named '%s'.\n" % json_name)
713     else:
714
715         class Result(object):
716             class_name = json_name
717
718             @staticmethod
719             def output_comment(writer):
720                 pass
721
722     return Result
723
724
725 class Writer:
726     def __init__(self, output, indent):
727         self.output = output
728         self.indent = indent
729
730     def newline(self, str):
731         if (self.indent):
732             self.output.append(self.indent)
733         self.output.append(str)
734
735     def append(self, str):
736         self.output.append(str)
737
738     def newline_multiline(self, str):
739         parts = str.split('\n')
740         self.newline(parts[0])
741         for p in parts[1:]:
742             self.output.append('\n')
743             if p:
744                 self.newline(p)
745
746     def append_multiline(self, str):
747         parts = str.split('\n')
748         self.append(parts[0])
749         for p in parts[1:]:
750             self.output.append('\n')
751             if p:
752                 self.newline(p)
753
754     def get_indent(self):
755         return self.indent
756
757     def get_indented(self, additional_indent):
758         return Writer(self.output, self.indent + additional_indent)
759
760     def insert_writer(self, additional_indent):
761         new_output = []
762         self.output.append(new_output)
763         return Writer(new_output, self.indent + additional_indent)
764
765
766 class EnumConstants:
767     map_ = {}
768     constants_ = []
769
770     @classmethod
771     def add_constant(cls, value):
772         if value in cls.map_:
773             return cls.map_[value]
774         else:
775             pos = len(cls.map_)
776             cls.map_[value] = pos
777             cls.constants_.append(value)
778             return pos
779
780     @classmethod
781     def get_enum_constant_code(cls):
782         output = []
783         for item in cls.constants_:
784             output.append("    \"" + item + "\"")
785         return ",\n".join(output) + "\n"
786
787
788 # Typebuilder code is generated in several passes: first typedefs, then other classes.
789 # Manual pass management is needed because we cannot have forward declarations for typedefs.
790 class TypeBuilderPass:
791     TYPEDEF = "typedef"
792     MAIN = "main"
793
794
795 class TypeBindings:
796     @staticmethod
797     def create_named_type_declaration(json_typable, context_domain_name, type_data):
798         json_type = type_data.get_json_type()
799
800         class Helper:
801             is_ad_hoc = False
802             full_name_prefix_for_use = "TypeBuilder::" + context_domain_name + "::"
803             full_name_prefix_for_impl = "TypeBuilder::" + context_domain_name + "::"
804
805             @staticmethod
806             def write_doc(writer):
807                 if "description" in json_type:
808                     writer.newline("/* ")
809                     writer.append(json_type["description"])
810                     writer.append(" */\n")
811
812             @staticmethod
813             def add_to_forward_listener(forward_listener):
814                 forward_listener.add_type_data(type_data)
815
816
817         fixed_type_name = fix_type_name(json_type["id"])
818         return TypeBindings.create_type_declaration_(json_typable, context_domain_name, fixed_type_name, Helper)
819
820     @staticmethod
821     def create_ad_hoc_type_declaration(json_typable, context_domain_name, ad_hoc_type_context):
822         class Helper:
823             is_ad_hoc = True
824             full_name_prefix_for_use = ad_hoc_type_context.container_relative_name_prefix
825             full_name_prefix_for_impl = ad_hoc_type_context.container_full_name_prefix
826
827             @staticmethod
828             def write_doc(writer):
829                 pass
830
831             @staticmethod
832             def add_to_forward_listener(forward_listener):
833                 pass
834         fixed_type_name = ad_hoc_type_context.get_type_name_fix()
835         return TypeBindings.create_type_declaration_(json_typable, context_domain_name, fixed_type_name, Helper)
836
837     @staticmethod
838     def create_type_declaration_(json_typable, context_domain_name, fixed_type_name, helper):
839         if json_typable["type"] == "string":
840             if "enum" in json_typable:
841
842                 class EnumBinding:
843                     need_user_runtime_cast_ = False
844                     need_internal_runtime_cast_ = False
845
846                     @classmethod
847                     def resolve_inner(cls, resolve_context):
848                         pass
849
850                     @classmethod
851                     def request_user_runtime_cast(cls, request):
852                         if request:
853                             cls.need_user_runtime_cast_ = True
854                             request.acknowledge()
855
856                     @classmethod
857                     def request_internal_runtime_cast(cls):
858                         cls.need_internal_runtime_cast_ = True
859
860                     @classmethod
861                     def get_code_generator(enum_binding_cls):
862                         #FIXME: generate ad-hoc enums too once we figure out how to better implement them in C++.
863                         comment_out = helper.is_ad_hoc
864
865                         class CodeGenerator:
866                             @staticmethod
867                             def generate_type_builder(writer, generate_context):
868                                 enum = json_typable["enum"]
869                                 helper.write_doc(writer)
870                                 enum_name = fixed_type_name.class_name
871                                 fixed_type_name.output_comment(writer)
872                                 writer.newline("struct ")
873                                 writer.append(enum_name)
874                                 writer.append(" {\n")
875                                 writer.newline("    enum Enum {\n")
876                                 for enum_item in enum:
877                                     enum_pos = EnumConstants.add_constant(enum_item)
878
879                                     item_c_name = enum_item.replace('-', '_')
880                                     item_c_name = Capitalizer.lower_camel_case_to_upper(item_c_name)
881                                     if item_c_name in TYPE_NAME_FIX_MAP:
882                                         item_c_name = TYPE_NAME_FIX_MAP[item_c_name]
883                                     writer.newline("        ")
884                                     writer.append(item_c_name)
885                                     writer.append(" = ")
886                                     writer.append("%s" % enum_pos)
887                                     writer.append(",\n")
888                                 writer.newline("    };\n")
889                                 if enum_binding_cls.need_user_runtime_cast_:
890                                     raise Exception("Not yet implemented")
891
892                                 if enum_binding_cls.need_internal_runtime_cast_:
893                                     writer.append("#if %s\n" % VALIDATOR_IFDEF_NAME)
894                                     writer.newline("    static void assertCorrectValue(JSONValue* value);\n")
895                                     writer.append("#endif  // %s\n" % VALIDATOR_IFDEF_NAME)
896
897                                     validator_writer = generate_context.validator_writer
898
899                                     domain_fixes = DomainNameFixes.get_fixed_data(context_domain_name)
900
901                                     validator_writer.newline("void %s%s::assertCorrectValue(JSONValue* value)\n" % (helper.full_name_prefix_for_impl, enum_name))
902                                     validator_writer.newline("{\n")
903                                     validator_writer.newline("    WTF::String s;\n")
904                                     validator_writer.newline("    bool cast_res = value->asString(&s);\n")
905                                     validator_writer.newline("    ASSERT(cast_res);\n")
906                                     if len(enum) > 0:
907                                         condition_list = []
908                                         for enum_item in enum:
909                                             enum_pos = EnumConstants.add_constant(enum_item)
910                                             condition_list.append("s == \"%s\"" % enum_item)
911                                         validator_writer.newline("    ASSERT(%s);\n" % " || ".join(condition_list))
912                                     validator_writer.newline("}\n")
913
914                                     validator_writer.newline("\n\n")
915
916                                 writer.newline("}; // struct ")
917                                 writer.append(enum_name)
918                                 writer.append("\n\n")
919
920                             @staticmethod
921                             def register_use(forward_listener):
922                                 pass
923
924                             @staticmethod
925                             def get_generate_pass_id():
926                                 return TypeBuilderPass.MAIN
927
928                         return CodeGenerator
929
930                     @classmethod
931                     def get_validator_call_text(cls):
932                         return helper.full_name_prefix_for_use + fixed_type_name.class_name + "::assertCorrectValue"
933
934                     @classmethod
935                     def get_array_item_c_type_text(cls):
936                         return helper.full_name_prefix_for_use + fixed_type_name.class_name + "::Enum"
937
938                     @staticmethod
939                     def get_setter_value_expression_pattern():
940                         return "TypeBuilder::getEnumConstantValue(%s)"
941
942                     @staticmethod
943                     def reduce_to_raw_type():
944                         return RawTypes.String
945
946                     @staticmethod
947                     def get_type_model():
948                         return TypeModel.Enum(helper.full_name_prefix_for_use + fixed_type_name.class_name)
949
950                 return EnumBinding
951             else:
952                 if helper.is_ad_hoc:
953
954                     class PlainString:
955                         @classmethod
956                         def resolve_inner(cls, resolve_context):
957                             pass
958
959                         @staticmethod
960                         def request_user_runtime_cast(request):
961                             raise Exception("Unsupported")
962
963                         @staticmethod
964                         def request_internal_runtime_cast():
965                             pass
966
967                         @staticmethod
968                         def get_code_generator():
969                             return None
970
971                         @classmethod
972                         def get_validator_call_text(cls):
973                             return RawTypes.String.get_raw_validator_call_text()
974
975                         @staticmethod
976                         def reduce_to_raw_type():
977                             return RawTypes.String
978
979                         @staticmethod
980                         def get_type_model():
981                             return TypeModel.String
982
983                         @staticmethod
984                         def get_setter_value_expression_pattern():
985                             return None
986
987                         @classmethod
988                         def get_array_item_c_type_text(cls):
989                             return cls.reduce_to_raw_type().get_array_item_raw_c_type_text()
990
991                     return PlainString
992
993                 else:
994
995                     class TypedefString:
996                         @classmethod
997                         def resolve_inner(cls, resolve_context):
998                             pass
999
1000                         @staticmethod
1001                         def request_user_runtime_cast(request):
1002                             raise Exception("Unsupported")
1003
1004                         @staticmethod
1005                         def request_internal_runtime_cast():
1006                             RawTypes.String.request_raw_internal_runtime_cast()
1007
1008                         @staticmethod
1009                         def get_code_generator():
1010                             class CodeGenerator:
1011                                 @staticmethod
1012                                 def generate_type_builder(writer, generate_context):
1013                                     helper.write_doc(writer)
1014                                     fixed_type_name.output_comment(writer)
1015                                     writer.newline("typedef String ")
1016                                     writer.append(fixed_type_name.class_name)
1017                                     writer.append(";\n\n")
1018
1019                                 @staticmethod
1020                                 def register_use(forward_listener):
1021                                     pass
1022
1023                                 @staticmethod
1024                                 def get_generate_pass_id():
1025                                     return TypeBuilderPass.TYPEDEF
1026
1027                             return CodeGenerator
1028
1029                         @classmethod
1030                         def get_validator_call_text(cls):
1031                             return RawTypes.String.get_raw_validator_call_text()
1032
1033                         @staticmethod
1034                         def reduce_to_raw_type():
1035                             return RawTypes.String
1036
1037                         @staticmethod
1038                         def get_type_model():
1039                             return TypeModel.ValueType("%s%s" % (helper.full_name_prefix_for_use, fixed_type_name.class_name), True)
1040
1041                         @staticmethod
1042                         def get_setter_value_expression_pattern():
1043                             return None
1044
1045                         @classmethod
1046                         def get_array_item_c_type_text(cls):
1047                             return "%s%s" % (helper.full_name_prefix_for_use, fixed_type_name.class_name)
1048
1049                     return TypedefString
1050
1051         elif json_typable["type"] == "object":
1052             if "properties" in json_typable:
1053
1054                 class ClassBinding:
1055                     resolve_data_ = None
1056                     need_user_runtime_cast_ = False
1057                     need_internal_runtime_cast_ = False
1058
1059                     @classmethod
1060                     def resolve_inner(cls, resolve_context):
1061                         if cls.resolve_data_:
1062                             return
1063
1064                         properties = json_typable["properties"]
1065                         main = []
1066                         optional = []
1067
1068                         ad_hoc_type_list = []
1069
1070                         for prop in properties:
1071                             prop_name = prop["name"]
1072                             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)
1073                             binding = resolve_param_type(prop, context_domain_name, ad_hoc_type_context)
1074
1075                             code_generator = binding.get_code_generator()
1076                             if code_generator:
1077                                 code_generator.register_use(resolve_context.forward_listener)
1078
1079                             class PropertyData:
1080                                 param_type_binding = binding
1081                                 p = prop
1082
1083                             if prop.get("optional"):
1084                                 optional.append(PropertyData)
1085                             else:
1086                                 main.append(PropertyData)
1087
1088                         class ResolveData:
1089                             main_properties = main
1090                             optional_properties = optional
1091                             ad_hoc_types = ad_hoc_type_list
1092
1093                         cls.resolve_data_ = ResolveData
1094
1095                         for ad_hoc in ad_hoc_type_list:
1096                             ad_hoc.resolve_inner(resolve_context)
1097
1098                     @classmethod
1099                     def request_user_runtime_cast(cls, request):
1100                         if not request:
1101                             return
1102                         cls.need_user_runtime_cast_ = True
1103                         request.acknowledge()
1104                         cls.request_internal_runtime_cast()
1105
1106                     @classmethod
1107                     def request_internal_runtime_cast(cls):
1108                         if cls.need_internal_runtime_cast_:
1109                             return
1110                         cls.need_internal_runtime_cast_ = True
1111                         for p in cls.resolve_data_.main_properties:
1112                             p.param_type_binding.request_internal_runtime_cast()
1113                         for p in cls.resolve_data_.optional_properties:
1114                             p.param_type_binding.request_internal_runtime_cast()
1115
1116                     @classmethod
1117                     def get_code_generator(class_binding_cls):
1118                         class CodeGenerator:
1119                             @classmethod
1120                             def generate_type_builder(cls, writer, generate_context):
1121                                 resolve_data = class_binding_cls.resolve_data_
1122                                 helper.write_doc(writer)
1123                                 class_name = fixed_type_name.class_name
1124
1125                                 is_open_type = (context_domain_name + "." + class_name) in TYPES_WITH_OPEN_FIELD_LIST_SET
1126
1127                                 fixed_type_name.output_comment(writer)
1128                                 writer.newline("class ")
1129                                 writer.append(class_name)
1130                                 writer.append(" : public ")
1131                                 if is_open_type:
1132                                     writer.append("JSONObject")
1133                                 else:
1134                                     writer.append("JSONObjectBase")
1135                                 writer.append(" {\n")
1136                                 writer.newline("public:\n")
1137                                 ad_hoc_type_writer = writer.insert_writer("    ")
1138
1139                                 for ad_hoc_type in resolve_data.ad_hoc_types:
1140                                     code_generator = ad_hoc_type.get_code_generator()
1141                                     if code_generator:
1142                                         code_generator.generate_type_builder(ad_hoc_type_writer, generate_context)
1143
1144                                 writer.newline_multiline(
1145 """    enum {
1146         NoFieldsSet = 0,
1147 """)
1148
1149                                 state_enum_items = []
1150                                 if len(resolve_data.main_properties) > 0:
1151                                     pos = 0
1152                                     for prop_data in resolve_data.main_properties:
1153                                         item_name = Capitalizer.lower_camel_case_to_upper(prop_data.p["name"]) + "Set"
1154                                         state_enum_items.append(item_name)
1155                                         writer.newline("        %s = 1 << %s,\n" % (item_name, pos))
1156                                         pos += 1
1157                                     all_fields_set_value = "(" + (" | ".join(state_enum_items)) + ")"
1158                                 else:
1159                                     all_fields_set_value = "0"
1160
1161                                 writer.newline_multiline(CodeGeneratorInspectorStrings.class_binding_builder_part_1
1162                                                          % (all_fields_set_value, class_name, class_name))
1163
1164                                 pos = 0
1165                                 for prop_data in resolve_data.main_properties:
1166                                     prop_name = prop_data.p["name"]
1167
1168                                     param_type_binding = prop_data.param_type_binding
1169                                     param_raw_type = param_type_binding.reduce_to_raw_type()
1170
1171                                     writer.newline_multiline(CodeGeneratorInspectorStrings.class_binding_builder_part_2
1172                                         % (state_enum_items[pos],
1173                                            Capitalizer.lower_camel_case_to_upper(prop_name),
1174                                            param_type_binding.get_type_model().get_input_param_type_text(),
1175                                            state_enum_items[pos], prop_name,
1176                                            param_raw_type.get_setter_name(), prop_name,
1177                                            format_setter_value_expression(param_type_binding, "value"),
1178                                            state_enum_items[pos]))
1179
1180                                     pos += 1
1181
1182                                 writer.newline_multiline(CodeGeneratorInspectorStrings.class_binding_builder_part_3
1183                                                          % (class_name, class_name, class_name, class_name, class_name))
1184
1185                                 writer.newline("    /*\n")
1186                                 writer.newline("     * Synthetic constructor:\n")
1187                                 writer.newline("     * RefPtr<%s> result = %s::create()" % (class_name, class_name))
1188                                 for prop_data in resolve_data.main_properties:
1189                                     writer.append_multiline("\n     *     .set%s(...)" % Capitalizer.lower_camel_case_to_upper(prop_data.p["name"]))
1190                                 writer.append_multiline(";\n     */\n")
1191
1192                                 writer.newline_multiline(CodeGeneratorInspectorStrings.class_binding_builder_part_4)
1193
1194                                 writer.newline("    typedef TypeBuilder::StructItemTraits ItemTraits;\n")
1195
1196                                 for prop_data in resolve_data.main_properties:
1197                                     prop_name = prop_data.p["name"]
1198                                     param_type_binding = prop_data.param_type_binding
1199                                     raw_type = param_type_binding.reduce_to_raw_type()
1200                                     if isinstance(param_type_binding.get_type_model(), TypeModel.ValueType):
1201                                         writer.append_multiline("\n    void %s" % prop_name)
1202                                         writer.append("(%s value)\n" % param_type_binding.get_type_model().get_command_return_pass_model().get_output_parameter_type())
1203                                         writer.newline("    {\n")
1204                                         writer.newline("        JSONObjectBase::get%s(\"%s\", value);\n"
1205                                             % (param_type_binding.reduce_to_raw_type().get_setter_name(), prop_data.p["name"]))
1206                                         writer.newline("    }\n")
1207
1208                                 for prop_data in resolve_data.optional_properties:
1209                                     prop_name = prop_data.p["name"]
1210                                     param_type_binding = prop_data.param_type_binding
1211                                     setter_name = "set%s" % Capitalizer.lower_camel_case_to_upper(prop_name)
1212
1213                                     writer.append_multiline("\n    void %s" % setter_name)
1214                                     writer.append("(%s value)\n" % param_type_binding.get_type_model().get_input_param_type_text())
1215                                     writer.newline("    {\n")
1216                                     writer.newline("        this->set%s(\"%s\", %s);\n"
1217                                         % (param_type_binding.reduce_to_raw_type().get_setter_name(), prop_data.p["name"],
1218                                            format_setter_value_expression(param_type_binding, "value")))
1219                                     writer.newline("    }\n")
1220
1221                                     if setter_name in INSPECTOR_OBJECT_SETTER_NAMES:
1222                                         writer.newline("    using JSONObjectBase::%s;\n\n" % setter_name)
1223
1224                                 if class_binding_cls.need_user_runtime_cast_:
1225                                     writer.newline("    static PassRefPtr<%s> runtimeCast(PassRefPtr<JSONValue> value)\n" % class_name)
1226                                     writer.newline("    {\n")
1227                                     writer.newline("        RefPtr<JSONObject> object;\n")
1228                                     writer.newline("        bool castRes = value->asObject(&object);\n")
1229                                     writer.newline("        ASSERT_UNUSED(castRes, castRes);\n")
1230                                     writer.append("#if %s\n" % VALIDATOR_IFDEF_NAME)
1231                                     writer.newline("        assertCorrectValue(object.get());\n")
1232                                     writer.append("#endif  // %s\n" % VALIDATOR_IFDEF_NAME)
1233                                     writer.newline("        COMPILE_ASSERT(sizeof(%s) == sizeof(JSONObjectBase), type_cast_problem);\n" % class_name)
1234                                     writer.newline("        return static_cast<%s*>(static_cast<JSONObjectBase*>(object.get()));\n" % class_name)
1235                                     writer.newline("    }\n")
1236                                     writer.append("\n")
1237
1238                                 if class_binding_cls.need_internal_runtime_cast_:
1239                                     writer.append("#if %s\n" % VALIDATOR_IFDEF_NAME)
1240                                     writer.newline("    static void assertCorrectValue(JSONValue* value);\n")
1241                                     writer.append("#endif  // %s\n" % VALIDATOR_IFDEF_NAME)
1242
1243                                     closed_field_set = (context_domain_name + "." + class_name) not in TYPES_WITH_OPEN_FIELD_LIST_SET
1244
1245                                     validator_writer = generate_context.validator_writer
1246
1247                                     domain_fixes = DomainNameFixes.get_fixed_data(context_domain_name)
1248
1249                                     validator_writer.newline("void %s%s::assertCorrectValue(JSONValue* value)\n" % (helper.full_name_prefix_for_impl, class_name))
1250                                     validator_writer.newline("{\n")
1251                                     validator_writer.newline("    RefPtr<JSONObject> object;\n")
1252                                     validator_writer.newline("    bool castRes = value->asObject(&object);\n")
1253                                     validator_writer.newline("    ASSERT_UNUSED(castRes, castRes);\n")
1254                                     for prop_data in resolve_data.main_properties:
1255                                         validator_writer.newline("    {\n")
1256                                         it_name = "%sPos" % prop_data.p["name"]
1257                                         validator_writer.newline("        JSONObject::iterator %s;\n" % it_name)
1258                                         validator_writer.newline("        %s = object->find(\"%s\");\n" % (it_name, prop_data.p["name"]))
1259                                         validator_writer.newline("        ASSERT(%s != object->end());\n" % it_name)
1260                                         validator_writer.newline("        %s(%s->value.get());\n" % (prop_data.param_type_binding.get_validator_call_text(), it_name))
1261                                         validator_writer.newline("    }\n")
1262
1263                                     if closed_field_set:
1264                                         validator_writer.newline("    int foundPropertiesCount = %s;\n" % len(resolve_data.main_properties))
1265
1266                                     for prop_data in resolve_data.optional_properties:
1267                                         validator_writer.newline("    {\n")
1268                                         it_name = "%sPos" % prop_data.p["name"]
1269                                         validator_writer.newline("        JSONObject::iterator %s;\n" % it_name)
1270                                         validator_writer.newline("        %s = object->find(\"%s\");\n" % (it_name, prop_data.p["name"]))
1271                                         validator_writer.newline("        if (%s != object->end()) {\n" % it_name)
1272                                         validator_writer.newline("            %s(%s->value.get());\n" % (prop_data.param_type_binding.get_validator_call_text(), it_name))
1273                                         if closed_field_set:
1274                                             validator_writer.newline("            ++foundPropertiesCount;\n")
1275                                         validator_writer.newline("        }\n")
1276                                         validator_writer.newline("    }\n")
1277
1278                                     if closed_field_set:
1279                                         validator_writer.newline("    if (foundPropertiesCount != object->size()) {\n")
1280                                         validator_writer.newline("      FATAL(\"Unexpected properties in object: %s\\n\", object->toJSONString().ascii().data());\n")
1281                                         validator_writer.newline("    }\n")
1282                                     validator_writer.newline("}\n")
1283
1284                                     validator_writer.newline("\n\n")
1285
1286                                 if is_open_type:
1287                                     cpp_writer = generate_context.cpp_writer
1288                                     writer.append("\n")
1289                                     writer.newline("    // Property names for type generated as open.\n")
1290                                     for prop_data in resolve_data.main_properties + resolve_data.optional_properties:
1291                                         prop_name = prop_data.p["name"]
1292                                         prop_field_name = Capitalizer.lower_camel_case_to_upper(prop_name)
1293                                         writer.newline("    static const char %s[];\n" % (prop_field_name))
1294                                         cpp_writer.newline("const char %s%s::%s[] = \"%s\";\n" % (helper.full_name_prefix_for_impl, class_name, prop_field_name, prop_name))
1295
1296
1297                                 writer.newline("};\n\n")
1298
1299                             @staticmethod
1300                             def generate_forward_declaration(writer):
1301                                 class_name = fixed_type_name.class_name
1302                                 writer.newline("class ")
1303                                 writer.append(class_name)
1304                                 writer.append(";\n")
1305
1306                             @staticmethod
1307                             def register_use(forward_listener):
1308                                 helper.add_to_forward_listener(forward_listener)
1309
1310                             @staticmethod
1311                             def get_generate_pass_id():
1312                                 return TypeBuilderPass.MAIN
1313
1314                         return CodeGenerator
1315
1316                     @staticmethod
1317                     def get_validator_call_text():
1318                         return helper.full_name_prefix_for_use + fixed_type_name.class_name + "::assertCorrectValue"
1319
1320                     @classmethod
1321                     def get_array_item_c_type_text(cls):
1322                         return helper.full_name_prefix_for_use + fixed_type_name.class_name
1323
1324                     @staticmethod
1325                     def get_setter_value_expression_pattern():
1326                         return None
1327
1328                     @staticmethod
1329                     def reduce_to_raw_type():
1330                         return RawTypes.Object
1331
1332                     @staticmethod
1333                     def get_type_model():
1334                         return TypeModel.RefPtrBased(helper.full_name_prefix_for_use + fixed_type_name.class_name)
1335
1336                     class AdHocTypeContextImpl:
1337                         def __init__(self, property_name, class_name, resolve_context, ad_hoc_type_list, parent_full_name_prefix):
1338                             self.property_name = property_name
1339                             self.class_name = class_name
1340                             self.resolve_context = resolve_context
1341                             self.ad_hoc_type_list = ad_hoc_type_list
1342                             self.container_full_name_prefix = parent_full_name_prefix + class_name + "::"
1343                             self.container_relative_name_prefix = ""
1344
1345                         def get_type_name_fix(self):
1346                             class NameFix:
1347                                 class_name = Capitalizer.lower_camel_case_to_upper(self.property_name)
1348
1349                                 @staticmethod
1350                                 def output_comment(writer):
1351                                     writer.newline("// Named after property name '%s' while generating %s.\n" % (self.property_name, self.class_name))
1352
1353                             return NameFix
1354
1355                         def add_type(self, binding):
1356                             self.ad_hoc_type_list.append(binding)
1357
1358                 return ClassBinding
1359             else:
1360
1361                 class PlainObjectBinding:
1362                     @classmethod
1363                     def resolve_inner(cls, resolve_context):
1364                         pass
1365
1366                     @staticmethod
1367                     def request_user_runtime_cast(request):
1368                         pass
1369
1370                     @staticmethod
1371                     def request_internal_runtime_cast():
1372                         RawTypes.Object.request_raw_internal_runtime_cast()
1373
1374                     @staticmethod
1375                     def get_code_generator():
1376                         pass
1377
1378                     @staticmethod
1379                     def get_validator_call_text():
1380                         return "RuntimeCastHelper::assertType<JSONValue::TypeObject>"
1381
1382                     @classmethod
1383                     def get_array_item_c_type_text(cls):
1384                         return cls.reduce_to_raw_type().get_array_item_raw_c_type_text()
1385
1386                     @staticmethod
1387                     def get_setter_value_expression_pattern():
1388                         return None
1389
1390                     @staticmethod
1391                     def reduce_to_raw_type():
1392                         return RawTypes.Object
1393
1394                     @staticmethod
1395                     def get_type_model():
1396                         return TypeModel.Object
1397
1398                 return PlainObjectBinding
1399         elif json_typable["type"] == "array":
1400             if "items" in json_typable:
1401
1402                 ad_hoc_types = []
1403
1404                 class AdHocTypeContext:
1405                     container_full_name_prefix = "<not yet defined>"
1406                     container_relative_name_prefix = ""
1407
1408                     @staticmethod
1409                     def get_type_name_fix():
1410                         return fixed_type_name
1411
1412                     @staticmethod
1413                     def add_type(binding):
1414                         ad_hoc_types.append(binding)
1415
1416                 item_binding = resolve_param_type(json_typable["items"], context_domain_name, AdHocTypeContext)
1417
1418                 class ArrayBinding:
1419                     resolve_data_ = None
1420                     need_internal_runtime_cast_ = False
1421
1422                     @classmethod
1423                     def resolve_inner(cls, resolve_context):
1424                         if cls.resolve_data_:
1425                             return
1426
1427                         class ResolveData:
1428                             item_type_binding = item_binding
1429                             ad_hoc_type_list = ad_hoc_types
1430
1431                         cls.resolve_data_ = ResolveData
1432
1433                         for t in ad_hoc_types:
1434                             t.resolve_inner(resolve_context)
1435
1436                     @classmethod
1437                     def request_user_runtime_cast(cls, request):
1438                         raise Exception("Not implemented yet")
1439
1440                     @classmethod
1441                     def request_internal_runtime_cast(cls):
1442                         if cls.need_internal_runtime_cast_:
1443                             return
1444                         cls.need_internal_runtime_cast_ = True
1445                         cls.resolve_data_.item_type_binding.request_internal_runtime_cast()
1446
1447                     @classmethod
1448                     def get_code_generator(array_binding_cls):
1449
1450                         class CodeGenerator:
1451                             @staticmethod
1452                             def generate_type_builder(writer, generate_context):
1453                                 ad_hoc_type_writer = writer
1454
1455                                 resolve_data = array_binding_cls.resolve_data_
1456
1457                                 for ad_hoc_type in resolve_data.ad_hoc_type_list:
1458                                     code_generator = ad_hoc_type.get_code_generator()
1459                                     if code_generator:
1460                                         code_generator.generate_type_builder(ad_hoc_type_writer, generate_context)
1461
1462                             @staticmethod
1463                             def generate_forward_declaration(writer):
1464                                 pass
1465
1466                             @staticmethod
1467                             def register_use(forward_listener):
1468                                 item_code_generator = item_binding.get_code_generator()
1469                                 if item_code_generator:
1470                                     item_code_generator.register_use(forward_listener)
1471
1472                             @staticmethod
1473                             def get_generate_pass_id():
1474                                 return TypeBuilderPass.MAIN
1475
1476                         return CodeGenerator
1477
1478                     @classmethod
1479                     def get_validator_call_text(cls):
1480                         return cls.get_array_item_c_type_text() + "::assertCorrectValue"
1481
1482                     @classmethod
1483                     def get_array_item_c_type_text(cls):
1484                         return replace_right_shift("TypeBuilder::Array<%s>" % cls.resolve_data_.item_type_binding.get_array_item_c_type_text())
1485
1486                     @staticmethod
1487                     def get_setter_value_expression_pattern():
1488                         return None
1489
1490                     @staticmethod
1491                     def reduce_to_raw_type():
1492                         return RawTypes.Array
1493
1494                     @classmethod
1495                     def get_type_model(cls):
1496                         return TypeModel.RefPtrBased(cls.get_array_item_c_type_text())
1497
1498                 return ArrayBinding
1499             else:
1500                 # Fall-through to raw type.
1501                 pass
1502
1503         raw_type = RawTypes.get(json_typable["type"])
1504
1505         return RawTypeBinding(raw_type)
1506
1507
1508 class RawTypeBinding:
1509     def __init__(self, raw_type):
1510         self.raw_type_ = raw_type
1511
1512     def resolve_inner(self, resolve_context):
1513         pass
1514
1515     def request_user_runtime_cast(self, request):
1516         raise Exception("Unsupported")
1517
1518     def request_internal_runtime_cast(self):
1519         self.raw_type_.request_raw_internal_runtime_cast()
1520
1521     def get_code_generator(self):
1522         return None
1523
1524     def get_validator_call_text(self):
1525         return self.raw_type_.get_raw_validator_call_text()
1526
1527     def get_array_item_c_type_text(self):
1528         return self.raw_type_.get_array_item_raw_c_type_text()
1529
1530     def get_setter_value_expression_pattern(self):
1531         return None
1532
1533     def reduce_to_raw_type(self):
1534         return self.raw_type_
1535
1536     def get_type_model(self):
1537         return self.raw_type_.get_raw_type_model()
1538
1539
1540 class TypeData(object):
1541     def __init__(self, json_type, json_domain, domain_data):
1542         self.json_type_ = json_type
1543         self.json_domain_ = json_domain
1544         self.domain_data_ = domain_data
1545
1546         if "type" not in json_type:
1547             raise Exception("Unknown type")
1548
1549         json_type_name = json_type["type"]
1550         raw_type = RawTypes.get(json_type_name)
1551         self.raw_type_ = raw_type
1552         self.binding_being_resolved_ = False
1553         self.binding_ = None
1554
1555     def get_raw_type(self):
1556         return self.raw_type_
1557
1558     def get_binding(self):
1559         if not self.binding_:
1560             if self.binding_being_resolved_:
1561                 raise Error("Type %s is already being resolved" % self.json_type_["type"])
1562             # Resolve only lazily, because resolving one named type may require resolving some other named type.
1563             self.binding_being_resolved_ = True
1564             try:
1565                 self.binding_ = TypeBindings.create_named_type_declaration(self.json_type_, self.json_domain_["domain"], self)
1566             finally:
1567                 self.binding_being_resolved_ = False
1568
1569         return self.binding_
1570
1571     def get_json_type(self):
1572         return self.json_type_
1573
1574     def get_name(self):
1575         return self.json_type_["id"]
1576
1577     def get_domain_name(self):
1578         return self.json_domain_["domain"]
1579
1580
1581 class DomainData:
1582     def __init__(self, json_domain):
1583         self.json_domain = json_domain
1584         self.types_ = []
1585
1586     def add_type(self, type_data):
1587         self.types_.append(type_data)
1588
1589     def name(self):
1590         return self.json_domain["domain"]
1591
1592     def types(self):
1593         return self.types_
1594
1595
1596 class TypeMap:
1597     def __init__(self, api):
1598         self.map_ = {}
1599         self.domains_ = []
1600         for json_domain in api["domains"]:
1601             domain_name = json_domain["domain"]
1602
1603             domain_map = {}
1604             self.map_[domain_name] = domain_map
1605
1606             domain_data = DomainData(json_domain)
1607             self.domains_.append(domain_data)
1608
1609             if "types" in json_domain:
1610                 for json_type in json_domain["types"]:
1611                     type_name = json_type["id"]
1612                     type_data = TypeData(json_type, json_domain, domain_data)
1613                     domain_map[type_name] = type_data
1614                     domain_data.add_type(type_data)
1615
1616     def domains(self):
1617         return self.domains_
1618
1619     def get(self, domain_name, type_name):
1620         return self.map_[domain_name][type_name]
1621
1622
1623 def resolve_param_type(json_parameter, scope_domain_name, ad_hoc_type_context):
1624     if "$ref" in json_parameter:
1625         json_ref = json_parameter["$ref"]
1626         type_data = get_ref_data(json_ref, scope_domain_name)
1627         return type_data.get_binding()
1628     elif "type" in json_parameter:
1629         result = TypeBindings.create_ad_hoc_type_declaration(json_parameter, scope_domain_name, ad_hoc_type_context)
1630         ad_hoc_type_context.add_type(result)
1631         return result
1632     else:
1633         raise Exception("Unknown type")
1634
1635 def resolve_param_raw_type(json_parameter, scope_domain_name):
1636     if "$ref" in json_parameter:
1637         json_ref = json_parameter["$ref"]
1638         type_data = get_ref_data(json_ref, scope_domain_name)
1639         return type_data.get_raw_type()
1640     elif "type" in json_parameter:
1641         json_type = json_parameter["type"]
1642         return RawTypes.get(json_type)
1643     else:
1644         raise Exception("Unknown type")
1645
1646
1647 def get_ref_data(json_ref, scope_domain_name):
1648     dot_pos = json_ref.find(".")
1649     if dot_pos == -1:
1650         domain_name = scope_domain_name
1651         type_name = json_ref
1652     else:
1653         domain_name = json_ref[:dot_pos]
1654         type_name = json_ref[dot_pos + 1:]
1655
1656     return type_map.get(domain_name, type_name)
1657
1658
1659 input_file = open(input_json_filename, "r")
1660 json_string = input_file.read()
1661 json_api = json.loads(json_string)
1662
1663
1664 class Templates:
1665     def get_this_script_path_(absolute_path):
1666         absolute_path = os.path.abspath(absolute_path)
1667         components = []
1668
1669         def fill_recursive(path_part, depth):
1670             if depth <= 0 or path_part == '/':
1671                 return
1672             fill_recursive(os.path.dirname(path_part), depth - 1)
1673             components.append(os.path.basename(path_part))
1674
1675         # Typical path is /Source/WebCore/inspector/CodeGeneratorInspector.py
1676         # Let's take 4 components from the real path then.
1677         fill_recursive(absolute_path, 4)
1678
1679         return "/".join(components)
1680
1681     file_header_ = ("// File is generated by %s\n\n" % get_this_script_path_(sys.argv[0]) +
1682 """// Copyright (c) 2011 The Chromium Authors. All rights reserved.
1683 // Use of this source code is governed by a BSD-style license that can be
1684 // found in the LICENSE file.
1685 """)
1686
1687     frontend_domain_class = string.Template(CodeGeneratorInspectorStrings.frontend_domain_class)
1688     backend_method = string.Template(CodeGeneratorInspectorStrings.backend_method)
1689     frontend_method = string.Template(CodeGeneratorInspectorStrings.frontend_method)
1690     callback_main_methods = string.Template(CodeGeneratorInspectorStrings.callback_main_methods)
1691     callback_failure_method = string.Template(CodeGeneratorInspectorStrings.callback_failure_method)
1692     frontend_h = string.Template(file_header_ + CodeGeneratorInspectorStrings.frontend_h)
1693     backend_h = string.Template(file_header_ + CodeGeneratorInspectorStrings.backend_h)
1694     backend_cpp = string.Template(file_header_ + CodeGeneratorInspectorStrings.backend_cpp)
1695     frontend_cpp = string.Template(file_header_ + CodeGeneratorInspectorStrings.frontend_cpp)
1696     typebuilder_h = string.Template(file_header_ + CodeGeneratorInspectorStrings.typebuilder_h)
1697     typebuilder_cpp = string.Template(file_header_ + CodeGeneratorInspectorStrings.typebuilder_cpp)
1698     param_container_access_code = CodeGeneratorInspectorStrings.param_container_access_code
1699
1700
1701
1702
1703
1704 type_map = TypeMap(json_api)
1705
1706
1707 class NeedRuntimeCastRequest:
1708     def __init__(self):
1709         self.ack_ = None
1710
1711     def acknowledge(self):
1712         self.ack_ = True
1713
1714     def is_acknowledged(self):
1715         return self.ack_
1716
1717
1718 def resolve_all_types():
1719     runtime_cast_generate_requests = {}
1720     for type_name in TYPES_WITH_RUNTIME_CAST_SET:
1721         runtime_cast_generate_requests[type_name] = NeedRuntimeCastRequest()
1722
1723     class ForwardListener:
1724         type_data_set = set()
1725         already_declared_set = set()
1726
1727         @classmethod
1728         def add_type_data(cls, type_data):
1729             if type_data not in cls.already_declared_set:
1730                 cls.type_data_set.add(type_data)
1731
1732     class ResolveContext:
1733         forward_listener = ForwardListener
1734
1735     for domain_data in type_map.domains():
1736         for type_data in domain_data.types():
1737             # Do not generate forwards for this type any longer.
1738             ForwardListener.already_declared_set.add(type_data)
1739
1740             binding = type_data.get_binding()
1741             binding.resolve_inner(ResolveContext)
1742
1743     for domain_data in type_map.domains():
1744         for type_data in domain_data.types():
1745             full_type_name = "%s.%s" % (type_data.get_domain_name(), type_data.get_name())
1746             request = runtime_cast_generate_requests.pop(full_type_name, None)
1747             binding = type_data.get_binding()
1748             if request:
1749                 binding.request_user_runtime_cast(request)
1750
1751             if request and not request.is_acknowledged():
1752                 raise Exception("Failed to generate runtimeCast in " + full_type_name)
1753
1754     for full_type_name in runtime_cast_generate_requests:
1755         raise Exception("Failed to generate runtimeCast. Type " + full_type_name + " not found")
1756
1757     return ForwardListener
1758
1759
1760 global_forward_listener = resolve_all_types()
1761
1762
1763 def get_annotated_type_text(raw_type, annotated_type):
1764     if annotated_type != raw_type:
1765         return "/*%s*/ %s" % (annotated_type, raw_type)
1766     else:
1767         return raw_type
1768
1769
1770 def format_setter_value_expression(param_type_binding, value_ref):
1771     pattern = param_type_binding.get_setter_value_expression_pattern()
1772     if pattern:
1773         return pattern % value_ref
1774     else:
1775         return value_ref
1776
1777 class Generator:
1778     frontend_class_field_lines = []
1779     frontend_domain_class_lines = []
1780
1781     method_name_enum_list = []
1782     backend_method_declaration_list = []
1783     backend_method_implementation_list = []
1784     backend_method_name_declaration_list = []
1785     backend_method_name_declaration_index_list = []
1786     backend_method_name_declaration_current_index = 0
1787     method_handler_list = []
1788     frontend_method_list = []
1789
1790     backend_virtual_setters_list = []
1791     backend_agent_interface_list = []
1792     backend_setters_list = []
1793     backend_constructor_init_list = []
1794     backend_field_list = []
1795     frontend_constructor_init_list = []
1796     type_builder_fragments = []
1797     type_builder_forwards = []
1798     validator_impl_list = []
1799     type_builder_impl_list = []
1800
1801
1802     @staticmethod
1803     def go():
1804         Generator.process_types(type_map)
1805
1806         first_cycle_guardable_list_list = [
1807             Generator.backend_method_declaration_list,
1808             Generator.backend_method_implementation_list,
1809             Generator.backend_method_name_declaration_list,
1810             Generator.backend_method_name_declaration_index_list,
1811             Generator.backend_agent_interface_list,
1812             Generator.frontend_class_field_lines,
1813             Generator.frontend_constructor_init_list,
1814             Generator.frontend_domain_class_lines,
1815             Generator.frontend_method_list,
1816             Generator.method_handler_list,
1817             Generator.method_name_enum_list,
1818             Generator.backend_constructor_init_list,
1819             Generator.backend_virtual_setters_list,
1820             Generator.backend_setters_list,
1821             Generator.backend_field_list]
1822
1823         for json_domain in json_api["domains"]:
1824             domain_name = json_domain["domain"]
1825             domain_name_lower = domain_name.lower()
1826
1827             domain_fixes = DomainNameFixes.get_fixed_data(domain_name)
1828
1829             agent_field_name = domain_fixes.agent_field_name
1830
1831             frontend_method_declaration_lines = []
1832
1833             if "events" in json_domain:
1834                 for json_event in json_domain["events"]:
1835                     Generator.process_event(json_event, domain_name, frontend_method_declaration_lines)
1836
1837             Generator.frontend_class_field_lines.append("    %s m_%s;\n" % (domain_name, domain_name_lower))
1838             if Generator.frontend_constructor_init_list:
1839                 Generator.frontend_constructor_init_list.append("    , ")
1840             Generator.frontend_constructor_init_list.append("m_%s(inspectorFrontendChannel)\n" % domain_name_lower)
1841             Generator.frontend_domain_class_lines.append(Templates.frontend_domain_class.substitute(None,
1842                 domainClassName=domain_name,
1843                 domainFieldName=domain_name_lower,
1844                 frontendDomainMethodDeclarations="".join(flatten_list(frontend_method_declaration_lines))))
1845
1846             agent_interface_name = Capitalizer.lower_camel_case_to_upper(domain_name) + "CommandHandler"
1847             Generator.backend_agent_interface_list.append("    class %s {\n" % agent_interface_name)
1848             Generator.backend_agent_interface_list.append("    public:\n")
1849             if "commands" in json_domain:
1850                 for json_command in json_domain["commands"]:
1851                     Generator.process_command(json_command, domain_name, agent_field_name, agent_interface_name)
1852             Generator.backend_agent_interface_list.append("\n    protected:\n")
1853             Generator.backend_agent_interface_list.append("        virtual ~%s() { }\n" % agent_interface_name)
1854             Generator.backend_agent_interface_list.append("    };\n\n")
1855
1856             Generator.backend_constructor_init_list.append("        , m_%s(0)" % agent_field_name)
1857             Generator.backend_virtual_setters_list.append("    virtual void registerAgent(%s* %s) = 0;" % (agent_interface_name, agent_field_name))
1858             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))
1859             Generator.backend_field_list.append("    %s* m_%s;" % (agent_interface_name, agent_field_name))
1860
1861     @staticmethod
1862     def process_event(json_event, domain_name, frontend_method_declaration_lines):
1863         if (("handlers" in json_event) and (not ("renderer" in json_event["handlers"]))):
1864             return
1865
1866         event_name = json_event["name"]
1867
1868         ad_hoc_type_output = []
1869         frontend_method_declaration_lines.append(ad_hoc_type_output)
1870         ad_hoc_type_writer = Writer(ad_hoc_type_output, "        ")
1871
1872         decl_parameter_list = []
1873
1874         json_parameters = json_event.get("parameters")
1875         Generator.generate_send_method(json_parameters, event_name, domain_name, ad_hoc_type_writer,
1876                                        decl_parameter_list,
1877                                        Generator.EventMethodStructTemplate,
1878                                        Generator.frontend_method_list, Templates.frontend_method, {"eventName": event_name})
1879
1880         frontend_method_declaration_lines.append(
1881             "        void %s(%s);\n" % (event_name, ", ".join(decl_parameter_list)))
1882
1883     class EventMethodStructTemplate:
1884         @staticmethod
1885         def append_prolog(line_list):
1886             line_list.append("    RefPtr<JSONObject> paramsObject = JSONObject::create();\n")
1887
1888         @staticmethod
1889         def append_epilog(line_list):
1890             line_list.append("    jsonMessage->setObject(\"params\", paramsObject);\n")
1891
1892         container_name = "paramsObject"
1893
1894     @staticmethod
1895     def process_command(json_command, domain_name, agent_field_name, agent_interface_name):
1896         if (("handlers" in json_command) and (not ("renderer" in json_command["handlers"]))):
1897             return
1898
1899         json_command_name = json_command["name"]
1900
1901         cmd_enum_name = "k%s_%sCmd" % (domain_name, json_command["name"])
1902
1903         Generator.method_name_enum_list.append("        %s," % cmd_enum_name)
1904         Generator.method_handler_list.append("            &InspectorBackendDispatcherImpl::%s_%s," % (domain_name, json_command_name))
1905         Generator.backend_method_declaration_list.append("    void %s_%s(long callId, JSONObject* requestMessageObject, JSONArray* protocolErrors);" % (domain_name, json_command_name))
1906
1907         backend_agent_interface_list = [] if "redirect" in json_command else Generator.backend_agent_interface_list
1908
1909         ad_hoc_type_output = []
1910         backend_agent_interface_list.append(ad_hoc_type_output)
1911         ad_hoc_type_writer = Writer(ad_hoc_type_output, "        ")
1912
1913         backend_agent_interface_list.append("        virtual void %s(ErrorString*" % json_command_name)
1914
1915         method_in_code = ""
1916         method_out_code = ""
1917         result_object_declaration = ""
1918         agent_call_param_list = ["&error"]
1919         agent_call_params_declaration_list = ["    ErrorString error;"]
1920         send_response_call_params_list = ["error"]
1921         request_message_param = ""
1922         normal_response_cook_text = ""
1923         error_type_binding = None
1924         if "error" in json_command:
1925             json_error = json_command["error"]
1926             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 + "::")
1927             error_type_model = error_type_binding.get_type_model().get_optional()
1928             error_annotated_type = error_type_model.get_command_return_pass_model().get_output_parameter_type()
1929             agent_call_param_list.append("%serrorData" % error_type_model.get_command_return_pass_model().get_output_argument_prefix())
1930             backend_agent_interface_list.append(", %s errorData" % error_annotated_type)
1931             method_in_code += "    %s errorData;\n" % error_type_model.get_command_return_pass_model().get_return_var_type()
1932             send_response_call_params_list.append("errorData")
1933
1934         if "parameters" in json_command:
1935             json_params = json_command["parameters"]
1936             request_message_param = " requestMessageObject"
1937
1938             if json_params:
1939                 method_in_code += Templates.param_container_access_code
1940
1941             for json_parameter in json_params:
1942                 json_param_name = json_parameter["name"]
1943                 param_raw_type = resolve_param_raw_type(json_parameter, domain_name)
1944
1945                 getter_name = param_raw_type.get_getter_name()
1946
1947                 optional = json_parameter.get("optional")
1948
1949                 non_optional_type_model = param_raw_type.get_raw_type_model()
1950                 if optional:
1951                     type_model = non_optional_type_model.get_optional()
1952                 else:
1953                     type_model = non_optional_type_model
1954
1955                 if optional:
1956                     code = ("    bool %s_valueFound = false;\n"
1957                             "    %s in_%s = get%s(paramsContainerPtr, \"%s\", &%s_valueFound, protocolErrors);\n" %
1958                            (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))
1959                     param = "%s_valueFound ? &in_%s : 0" % (json_param_name, json_param_name)
1960                     # FIXME: pass optional refptr-values as PassRefPtr
1961                     formal_param_type_pattern = "const %s*"
1962                 else:
1963                     code = ("    %s in_%s = get%s(paramsContainerPtr, \"%s\", 0, protocolErrors);\n" %
1964                             (non_optional_type_model.get_command_return_pass_model().get_return_var_type(), json_param_name, getter_name, json_param_name))
1965                     param = "in_%s" % json_param_name
1966                     # FIXME: pass not-optional refptr-values as NonNullPassRefPtr
1967                     if param_raw_type.is_heavy_value():
1968                         formal_param_type_pattern = "const %s&"
1969                     else:
1970                         formal_param_type_pattern = "%s"
1971
1972                 method_in_code += code
1973                 agent_call_param_list.append(param)
1974                 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))
1975
1976         if json_command.get("async") == True:
1977             callback_name = Capitalizer.lower_camel_case_to_upper(json_command_name) + "Callback"
1978
1979             callback_output = []
1980             callback_writer = Writer(callback_output, ad_hoc_type_writer.get_indent())
1981
1982             decl_parameter_list = []
1983             Generator.generate_send_method(json_command.get("returns"), json_command_name, domain_name, ad_hoc_type_writer,
1984                                            decl_parameter_list,
1985                                            Generator.CallbackMethodStructTemplate,
1986                                            Generator.backend_method_implementation_list, Templates.callback_main_methods,
1987                                            {"callbackName": callback_name, "agentName": agent_interface_name})
1988
1989             callback_writer.newline("class " + callback_name + " : public CallbackBase {\n")
1990             callback_writer.newline("public:\n")
1991             callback_writer.newline("    " + callback_name + "(PassRefPtr<InspectorBackendDispatcherImpl>, int id);\n")
1992             callback_writer.newline("    void sendSuccess(" + ", ".join(decl_parameter_list) + ");\n")
1993             error_part_writer = callback_writer.insert_writer("")
1994             callback_writer.newline("};\n")
1995
1996             if error_type_binding:
1997                 annotated_type = error_type_model.get_input_param_type_text()
1998                 error_part_writer.newline("    void sendFailure(const ErrorString&, %s);\n" % annotated_type)
1999                 error_part_writer.newline("    using CallbackBase::sendFailure;\n")
2000
2001                 assigment_value = error_type_model.get_event_setter_expression_pattern() % "errorData"
2002                 assigment_value = error_type_binding.reduce_to_raw_type().get_constructor_pattern() % assigment_value
2003
2004                 Generator.backend_method_implementation_list.append(Templates.callback_failure_method.substitute(None,
2005                     agentName=agent_interface_name,
2006                     callbackName=callback_name,
2007                     parameter=annotated_type + " errorData",
2008                     argument=assigment_value))
2009
2010             ad_hoc_type_output.append(callback_output)
2011
2012             method_out_code += "    RefPtr<" + agent_interface_name + "::" + callback_name + "> callback = adoptRef(new " + agent_interface_name + "::" + callback_name + "(this, callId));\n"
2013             agent_call_param_list.append("callback")
2014             normal_response_cook_text += "    if (!error.length()) \n"
2015             normal_response_cook_text += "        return;\n"
2016             normal_response_cook_text += "    callback->disable();\n"
2017             backend_agent_interface_list.append(", PassRefPtr<%s> callback" % callback_name)
2018         else:
2019             if "returns" in json_command:
2020                 method_out_code += "\n"
2021                 agent_call_params_declaration_list.append("    RefPtr<JSONObject> result = JSONObject::create();")
2022                 send_response_call_params_list.append("result")
2023                 response_cook_list = []
2024                 for json_return in json_command["returns"]:
2025
2026                     json_return_name = json_return["name"]
2027
2028                     optional = bool(json_return.get("optional"))
2029
2030                     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 + "::")
2031
2032                     raw_type = return_type_binding.reduce_to_raw_type()
2033                     setter_type = raw_type.get_setter_name()
2034                     initializer = raw_type.get_c_initializer()
2035
2036                     type_model = return_type_binding.get_type_model()
2037                     if optional:
2038                         type_model = type_model.get_optional()
2039
2040                     code = "    %s out_%s;\n" % (type_model.get_command_return_pass_model().get_return_var_type(), json_return_name)
2041                     param = "%sout_%s" % (type_model.get_command_return_pass_model().get_output_argument_prefix(), json_return_name)
2042                     var_name = "out_%s" % json_return_name
2043                     setter_argument = type_model.get_command_return_pass_model().get_output_to_raw_expression() % var_name
2044                     if return_type_binding.get_setter_value_expression_pattern():
2045                         setter_argument = return_type_binding.get_setter_value_expression_pattern() % setter_argument
2046
2047                     cook = "        result->set%s(\"%s\", %s);\n" % (setter_type, json_return_name,
2048                                                                          setter_argument)
2049
2050                     set_condition_pattern = type_model.get_command_return_pass_model().get_set_return_condition()
2051                     if set_condition_pattern:
2052                         cook = ("        if (%s)\n    " % (set_condition_pattern % var_name)) + cook
2053                     annotated_type = type_model.get_command_return_pass_model().get_output_parameter_type()
2054
2055                     param_name = var_name
2056                     if optional:
2057                         param_name = "opt_" + param_name
2058
2059                     backend_agent_interface_list.append(", %s %s" % (annotated_type, param_name))
2060                     response_cook_list.append(cook)
2061
2062                     method_out_code += code
2063                     agent_call_param_list.append(param)
2064
2065                 normal_response_cook_text += "".join(response_cook_list)
2066
2067                 if len(normal_response_cook_text) != 0:
2068                     normal_response_cook_text = "    if (!error.length()) {\n" + normal_response_cook_text + "    }"
2069
2070         # Redirect to another agent's implementation.
2071         agent_field = "m_" + agent_field_name
2072         if "redirect" in json_command:
2073             domain_fixes = DomainNameFixes.get_fixed_data(json_command.get("redirect"))
2074             agent_field = "m_" + domain_fixes.agent_field_name
2075
2076         Generator.backend_method_implementation_list.append(Templates.backend_method.substitute(None,
2077             domainName=domain_name, methodName=json_command_name,
2078             agentField=agent_field,
2079             methodCode="".join([method_in_code, method_out_code]),
2080             agentCallParamsDeclaration="\n".join(agent_call_params_declaration_list),
2081             agentCallParams=", ".join(agent_call_param_list),
2082             requestMessageObject=request_message_param,
2083             responseCook=normal_response_cook_text,
2084             sendResponseCallParams=", ".join(send_response_call_params_list),
2085             commandNameIndex=cmd_enum_name))
2086         declaration_command_name = "%s.%s\\0" % (domain_name, json_command_name)
2087         Generator.backend_method_name_declaration_list.append("    \"%s\"" % declaration_command_name)
2088         Generator.backend_method_name_declaration_index_list.append("    %d," % Generator.backend_method_name_declaration_current_index)
2089         Generator.backend_method_name_declaration_current_index += len(declaration_command_name) - 1
2090
2091         backend_agent_interface_list.append(") = 0;\n")
2092
2093     class CallbackMethodStructTemplate:
2094         @staticmethod
2095         def append_prolog(line_list):
2096             pass
2097
2098         @staticmethod
2099         def append_epilog(line_list):
2100             pass
2101
2102         container_name = "jsonMessage"
2103
2104     # Generates common code for event sending and callback response data sending.
2105     @staticmethod
2106     def generate_send_method(parameters, event_name, domain_name, ad_hoc_type_writer, decl_parameter_list,
2107                              method_struct_template,
2108                              generator_method_list, method_template, template_params):
2109         method_line_list = []
2110         if parameters:
2111             method_struct_template.append_prolog(method_line_list)
2112             for json_parameter in parameters:
2113                 parameter_name = json_parameter["name"]
2114
2115                 param_type_binding = Generator.resolve_param_type_and_generate_ad_hoc(json_parameter, event_name, domain_name, ad_hoc_type_writer, "")
2116
2117                 raw_type = param_type_binding.reduce_to_raw_type()
2118                 raw_type_binding = RawTypeBinding(raw_type)
2119
2120                 optional = bool(json_parameter.get("optional"))
2121
2122                 setter_type = raw_type.get_setter_name()
2123
2124                 type_model = param_type_binding.get_type_model()
2125                 raw_type_model = raw_type_binding.get_type_model()
2126                 if optional:
2127                     type_model = type_model.get_optional()
2128                     raw_type_model = raw_type_model.get_optional()
2129
2130                 annotated_type = type_model.get_input_param_type_text()
2131                 mode_type_binding = param_type_binding
2132
2133                 decl_parameter_list.append("%s %s" % (annotated_type, parameter_name))
2134
2135                 setter_argument = raw_type_model.get_event_setter_expression_pattern() % parameter_name
2136                 if mode_type_binding.get_setter_value_expression_pattern():
2137                     setter_argument = mode_type_binding.get_setter_value_expression_pattern() % setter_argument
2138
2139                 setter_code = "    %s->set%s(\"%s\", %s);\n" % (method_struct_template.container_name, setter_type, parameter_name, setter_argument)
2140                 if optional:
2141                     setter_code = ("    if (%s)\n    " % parameter_name) + setter_code
2142                 method_line_list.append(setter_code)
2143
2144             method_struct_template.append_epilog(method_line_list)
2145
2146         generator_method_list.append(method_template.substitute(None,
2147             domainName=domain_name,
2148             parameters=", ".join(decl_parameter_list),
2149             code="".join(method_line_list), **template_params))
2150
2151     @classmethod
2152     def resolve_param_type_and_generate_ad_hoc(cls, json_param, method_name, domain_name, ad_hoc_type_writer, container_relative_name_prefix_param):
2153         param_name = json_param["name"]
2154         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)
2155
2156     @staticmethod
2157     def resolve_type_and_generate_ad_hoc(typable_element, element_name, method_name, domain_name, ad_hoc_type_writer, container_relative_name_prefix_param):
2158         ad_hoc_type_list = []
2159
2160         class AdHocTypeContext:
2161             container_full_name_prefix = "<not yet defined>"
2162             container_relative_name_prefix = container_relative_name_prefix_param
2163
2164             @staticmethod
2165             def get_type_name_fix():
2166                 class NameFix:
2167                     class_name = Capitalizer.lower_camel_case_to_upper(element_name)
2168
2169                     @staticmethod
2170                     def output_comment(writer):
2171                         writer.newline("// Named after parameter '%s' while generating command/event %s.\n" % (element_name, method_name))
2172
2173                 return NameFix
2174
2175             @staticmethod
2176             def add_type(binding):
2177                 ad_hoc_type_list.append(binding)
2178
2179         type_binding = resolve_param_type(typable_element, domain_name, AdHocTypeContext)
2180
2181         class InterfaceForwardListener:
2182             @staticmethod
2183             def add_type_data(type_data):
2184                 pass
2185
2186         class InterfaceResolveContext:
2187             forward_listener = InterfaceForwardListener
2188
2189         for type in ad_hoc_type_list:
2190             type.resolve_inner(InterfaceResolveContext)
2191
2192         class InterfaceGenerateContext:
2193             validator_writer = "not supported in InterfaceGenerateContext"
2194             cpp_writer = validator_writer
2195
2196         for type in ad_hoc_type_list:
2197             generator = type.get_code_generator()
2198             if generator:
2199                 generator.generate_type_builder(ad_hoc_type_writer, InterfaceGenerateContext)
2200
2201         return type_binding
2202
2203     @staticmethod
2204     def process_types(type_map):
2205         output = Generator.type_builder_fragments
2206
2207         class GenerateContext:
2208             validator_writer = Writer(Generator.validator_impl_list, "")
2209             cpp_writer = Writer(Generator.type_builder_impl_list, "")
2210
2211         def generate_all_domains_code(out, type_data_callback):
2212             writer = Writer(out, "")
2213             for domain_data in type_map.domains():
2214                 domain_fixes = DomainNameFixes.get_fixed_data(domain_data.name())
2215
2216                 namespace_declared = []
2217
2218                 def namespace_lazy_generator():
2219                     if not namespace_declared:
2220                         writer.newline("namespace ")
2221                         writer.append(domain_data.name())
2222                         writer.append(" {\n")
2223                         # What is a better way to change value from outer scope?
2224                         namespace_declared.append(True)
2225                     return writer
2226
2227                 for type_data in domain_data.types():
2228                     type_data_callback(type_data, namespace_lazy_generator)
2229
2230                 if namespace_declared:
2231                     writer.append("} // ")
2232                     writer.append(domain_data.name())
2233                     writer.append("\n\n")
2234
2235         def create_type_builder_caller(generate_pass_id):
2236             def call_type_builder(type_data, writer_getter):
2237                 code_generator = type_data.get_binding().get_code_generator()
2238                 if code_generator and generate_pass_id == code_generator.get_generate_pass_id():
2239                     writer = writer_getter()
2240
2241                     code_generator.generate_type_builder(writer, GenerateContext)
2242             return call_type_builder
2243
2244         generate_all_domains_code(output, create_type_builder_caller(TypeBuilderPass.MAIN))
2245
2246         Generator.type_builder_forwards.append("// Forward declarations.\n")
2247
2248         def generate_forward_callback(type_data, writer_getter):
2249             if type_data in global_forward_listener.type_data_set:
2250                 binding = type_data.get_binding()
2251                 binding.get_code_generator().generate_forward_declaration(writer_getter())
2252         generate_all_domains_code(Generator.type_builder_forwards, generate_forward_callback)
2253
2254         Generator.type_builder_forwards.append("// End of forward declarations.\n\n")
2255
2256         Generator.type_builder_forwards.append("// Typedefs.\n")
2257
2258         generate_all_domains_code(Generator.type_builder_forwards, create_type_builder_caller(TypeBuilderPass.TYPEDEF))
2259
2260         Generator.type_builder_forwards.append("// End of typedefs.\n\n")
2261
2262
2263 def flatten_list(input):
2264     res = []
2265
2266     def fill_recursive(l):
2267         for item in l:
2268             if isinstance(item, list):
2269                 fill_recursive(item)
2270             else:
2271                 res.append(item)
2272     fill_recursive(input)
2273     return res
2274
2275
2276 # A writer that only updates file if it actually changed to better support incremental build.
2277 class SmartOutput:
2278     def __init__(self, file_name):
2279         self.file_name_ = file_name
2280         self.output_ = ""
2281
2282     def write(self, text):
2283         self.output_ += text
2284
2285     def close(self):
2286         text_changed = True
2287
2288         try:
2289             read_file = open(self.file_name_, "r")
2290             old_text = read_file.read()
2291             read_file.close()
2292             text_changed = old_text != self.output_
2293         except:
2294             # Ignore, just overwrite by default
2295             pass
2296
2297         if text_changed:
2298             out_file = open(self.file_name_, "w")
2299             out_file.write(self.output_)
2300             out_file.close()
2301
2302
2303 def output_file(file_name):
2304     # For now, disable the incremental build optimisation in all cases.
2305     if False:
2306         return SmartOutput(file_name)
2307     else:
2308         return open(file_name, "w")
2309
2310
2311 Generator.go()
2312
2313 backend_h_file = output_file(output_dirname + "/InspectorBackendDispatcher.h")
2314 backend_cpp_file = output_file(output_dirname + "/InspectorBackendDispatcher.cpp")
2315
2316 frontend_h_file = output_file(output_dirname + "/InspectorFrontend.h")
2317 frontend_cpp_file = output_file(output_dirname + "/InspectorFrontend.cpp")
2318
2319 typebuilder_h_file = output_file(output_dirname + "/InspectorTypeBuilder.h")
2320 typebuilder_cpp_file = output_file(output_dirname + "/InspectorTypeBuilder.cpp")
2321
2322
2323 backend_h_file.write(Templates.backend_h.substitute(None,
2324     virtualSetters="\n".join(Generator.backend_virtual_setters_list),
2325     agentInterfaces="".join(flatten_list(Generator.backend_agent_interface_list)),
2326     methodNamesEnumContent="\n".join(Generator.method_name_enum_list)))
2327
2328 backend_cpp_file.write(Templates.backend_cpp.substitute(None,
2329     constructorInit="\n".join(Generator.backend_constructor_init_list),
2330     setters="\n".join(Generator.backend_setters_list),
2331     fieldDeclarations="\n".join(Generator.backend_field_list),
2332     methodNameDeclarations="\n".join(Generator.backend_method_name_declaration_list),
2333     methodNameDeclarationsIndex="\n".join(Generator.backend_method_name_declaration_index_list),
2334     methods="\n".join(Generator.backend_method_implementation_list),
2335     methodDeclarations="\n".join(Generator.backend_method_declaration_list),
2336     messageHandlers="\n".join(Generator.method_handler_list)))
2337
2338 frontend_h_file.write(Templates.frontend_h.substitute(None,
2339     fieldDeclarations="".join(Generator.frontend_class_field_lines),
2340     domainClassList="".join(Generator.frontend_domain_class_lines)))
2341
2342 frontend_cpp_file.write(Templates.frontend_cpp.substitute(None,
2343     constructorInit="".join(Generator.frontend_constructor_init_list),
2344     methods="\n".join(Generator.frontend_method_list)))
2345
2346 typebuilder_h_file.write(Templates.typebuilder_h.substitute(None,
2347     typeBuilders="".join(flatten_list(Generator.type_builder_fragments)),
2348     forwards="".join(Generator.type_builder_forwards),
2349     validatorIfdefName=VALIDATOR_IFDEF_NAME))
2350
2351 typebuilder_cpp_file.write(Templates.typebuilder_cpp.substitute(None,
2352     enumConstantValues=EnumConstants.get_enum_constant_code(),
2353     implCode="".join(flatten_list(Generator.type_builder_impl_list)),
2354     validatorCode="".join(flatten_list(Generator.validator_impl_list)),
2355     validatorIfdefName=VALIDATOR_IFDEF_NAME))
2356
2357 backend_h_file.close()
2358 backend_cpp_file.close()
2359
2360 frontend_h_file.close()
2361 frontend_cpp_file.close()
2362
2363 typebuilder_h_file.close()
2364 typebuilder_cpp_file.close()