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