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