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