| #!/usr/bin/env python |
| # Copyright (c) 2011 Google Inc. All rights reserved. |
| # Copyright (c) 2012 Intel Corporation. All rights reserved. |
| # |
| # Redistribution and use in source and binary forms, with or without |
| # modification, are permitted provided that the following conditions are |
| # met: |
| # |
| # * Redistributions of source code must retain the above copyright |
| # notice, this list of conditions and the following disclaimer. |
| # * Redistributions in binary form must reproduce the above |
| # copyright notice, this list of conditions and the following disclaimer |
| # in the documentation and/or other materials provided with the |
| # distribution. |
| # * Neither the name of Google Inc. nor the names of its |
| # contributors may be used to endorse or promote products derived from |
| # this software without specific prior written permission. |
| # |
| # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| import os.path |
| import sys |
| import string |
| import optparse |
| import re |
| try: |
| import json |
| except ImportError: |
| import simplejson as json |
| |
| import CodeGeneratorInspectorStrings |
| |
| # Manually-filled map of type name replacements. |
| TYPE_NAME_FIX_MAP = { |
| "RGBA": "Rgba", # RGBA is reported to be conflicting with a define name in Windows CE. |
| "": "Empty", |
| } |
| |
| |
| TYPES_WITH_RUNTIME_CAST_SET = frozenset(["Runtime.RemoteObject", "Runtime.PropertyDescriptor", "Runtime.InternalPropertyDescriptor", |
| "Debugger.FunctionDetails", "Debugger.CollectionEntry", "Debugger.CallFrame", "Debugger.Location", |
| "Canvas.TraceLog", "Canvas.ResourceState"]) |
| |
| TYPES_WITH_OPEN_FIELD_LIST_SET = frozenset([ |
| # InspectorStyleSheet not only creates this property but wants to read it and modify it. |
| "CSS.CSSProperty", |
| # InspectorResourceAgent needs to update mime-type. |
| "Network.Response"]) |
| |
| cmdline_parser = optparse.OptionParser() |
| cmdline_parser.add_option("--output_dir") |
| |
| try: |
| arg_options, arg_values = cmdline_parser.parse_args() |
| if (len(arg_values) != 1): |
| raise Exception("Exactly one plain argument expected (found %s)" % len(arg_values)) |
| input_json_filename = arg_values[0] |
| output_dirname = arg_options.output_dir |
| if not output_dirname: |
| raise Exception("Output directory must be specified") |
| except Exception: |
| # Work with python 2 and 3 http://docs.python.org/py3k/howto/pyporting.html |
| exc = sys.exc_info()[1] |
| sys.stderr.write("Failed to parse command-line arguments: %s\n\n" % exc) |
| sys.stderr.write("Usage: <script> --output_dir <output_dir> protocol.json\n") |
| exit(1) |
| |
| |
| # FIXME: move this methods under Capitalizer class below and remove duplications. |
| def dash_to_camelcase(word): |
| return ''.join(x.capitalize() or '-' for x in word.split('-')) |
| |
| |
| def fix_camel_case(name): |
| refined = re.sub(r'-(\w)', lambda pat: pat.group(1).upper(), name) |
| refined = to_title_case(refined) |
| return re.sub(r'(?i)HTML|XML|WML|API', lambda pat: pat.group(0).upper(), refined) |
| |
| |
| def to_title_case(name): |
| return name[:1].upper() + name[1:] |
| |
| |
| class Capitalizer: |
| @staticmethod |
| def lower_camel_case_to_upper(str): |
| if len(str) > 0 and str[0].islower(): |
| str = str[0].upper() + str[1:] |
| return str |
| |
| @staticmethod |
| def upper_camel_case_to_lower(str): |
| pos = 0 |
| while pos < len(str) and str[pos].isupper(): |
| pos += 1 |
| if pos == 0: |
| return str |
| if pos == 1: |
| return str[0].lower() + str[1:] |
| if pos < len(str): |
| pos -= 1 |
| possible_abbreviation = str[0:pos] |
| if possible_abbreviation not in Capitalizer.ABBREVIATION: |
| raise Exception("Unknown abbreviation %s" % possible_abbreviation) |
| str = possible_abbreviation.lower() + str[pos:] |
| return str |
| |
| ABBREVIATION = frozenset(["XHR", "DOM", "CSS"]) |
| |
| VALIDATOR_IFDEF_NAME = "ENABLE(ASSERT)" |
| |
| |
| class DomainNameFixes: |
| @staticmethod |
| def get_fixed_data(domain_name): |
| return Capitalizer.upper_camel_case_to_lower(domain_name) + "Agent" |
| |
| class RawTypes(object): |
| @staticmethod |
| def get(json_type): |
| if json_type == "boolean": |
| return RawTypes.Bool |
| elif json_type == "string": |
| return RawTypes.String |
| elif json_type == "array": |
| return RawTypes.Array |
| elif json_type == "object": |
| return RawTypes.Object |
| elif json_type == "integer": |
| return RawTypes.Int |
| elif json_type == "number": |
| return RawTypes.Number |
| elif json_type == "any": |
| return RawTypes.Any |
| else: |
| raise Exception("Unknown type: %s" % json_type) |
| |
| class BaseType(object): |
| @classmethod |
| def get_raw_validator_call_text(cls): |
| return "RuntimeCastHelper::assertType<JSONValue::Type%s>" % cls.get_getter_name() |
| |
| @staticmethod |
| def get_getter_name(): |
| raise Exception("Unsupported") |
| |
| class String(BaseType): |
| @staticmethod |
| def get_getter_name(): |
| return "String" |
| |
| get_setter_name = get_getter_name |
| |
| @staticmethod |
| def get_constructor_pattern(): |
| return "InspectorString::create(%s)" |
| |
| @staticmethod |
| def is_heavy_value(): |
| return True |
| |
| @staticmethod |
| def get_array_item_raw_c_type_text(): |
| return "String" |
| |
| @staticmethod |
| def get_raw_type_model(): |
| return TypeModel.String |
| |
| class Int(BaseType): |
| @staticmethod |
| def get_getter_name(): |
| return "Int" |
| |
| @staticmethod |
| def get_setter_name(): |
| return "Number" |
| |
| @staticmethod |
| def get_constructor_pattern(): |
| return "InspectorBasicValue::create(%s)" |
| |
| @classmethod |
| def get_raw_validator_call_text(cls): |
| return "RuntimeCastHelper::assertInt" |
| |
| @staticmethod |
| def is_heavy_value(): |
| return False |
| |
| @staticmethod |
| def get_array_item_raw_c_type_text(): |
| return "int" |
| |
| @staticmethod |
| def get_raw_type_model(): |
| return TypeModel.Int |
| |
| class Number(BaseType): |
| @staticmethod |
| def get_getter_name(): |
| return "Double" |
| |
| @staticmethod |
| def get_setter_name(): |
| return "Number" |
| |
| @staticmethod |
| def get_constructor_pattern(): |
| return "InspectorBasicValue::create(%s)" |
| |
| @staticmethod |
| def get_raw_validator_call_text(): |
| return "RuntimeCastHelper::assertType<JSONValue::TypeNumber>" |
| |
| @staticmethod |
| def is_heavy_value(): |
| return False |
| |
| @staticmethod |
| def get_array_item_raw_c_type_text(): |
| return "double" |
| |
| @staticmethod |
| def get_raw_type_model(): |
| return TypeModel.Number |
| |
| class Bool(BaseType): |
| @staticmethod |
| def get_getter_name(): |
| return "Boolean" |
| |
| get_setter_name = get_getter_name |
| |
| @staticmethod |
| def get_constructor_pattern(): |
| return "InspectorBasicValue::create(%s)" |
| |
| @staticmethod |
| def is_heavy_value(): |
| return False |
| |
| @staticmethod |
| def get_array_item_raw_c_type_text(): |
| return "bool" |
| |
| @staticmethod |
| def get_raw_type_model(): |
| return TypeModel.Bool |
| |
| class Object(BaseType): |
| @staticmethod |
| def get_getter_name(): |
| return "Object" |
| |
| @staticmethod |
| def get_setter_name(): |
| return "Value" |
| |
| @staticmethod |
| def get_constructor_pattern(): |
| return "%s" |
| |
| @staticmethod |
| def get_output_argument_prefix(): |
| return "" |
| |
| @staticmethod |
| def is_heavy_value(): |
| return True |
| |
| @staticmethod |
| def get_array_item_raw_c_type_text(): |
| return "JSONObject" |
| |
| @staticmethod |
| def get_raw_type_model(): |
| return TypeModel.Object |
| |
| class Any(BaseType): |
| @staticmethod |
| def get_getter_name(): |
| return "Value" |
| |
| get_setter_name = get_getter_name |
| |
| @staticmethod |
| def get_constructor_pattern(): |
| raise Exception("Unsupported") |
| |
| @staticmethod |
| def get_raw_validator_call_text(): |
| return "RuntimeCastHelper::assertAny" |
| |
| @staticmethod |
| def is_heavy_value(): |
| return True |
| |
| @staticmethod |
| def get_array_item_raw_c_type_text(): |
| return "JSONValue" |
| |
| @staticmethod |
| def get_raw_type_model(): |
| return TypeModel.Any |
| |
| class Array(BaseType): |
| @staticmethod |
| def get_getter_name(): |
| return "Array" |
| |
| @staticmethod |
| def get_setter_name(): |
| return "Value" |
| |
| @staticmethod |
| def get_constructor_pattern(): |
| return "%s" |
| |
| @staticmethod |
| def get_output_argument_prefix(): |
| return "" |
| |
| @staticmethod |
| def is_heavy_value(): |
| return True |
| |
| @staticmethod |
| def get_array_item_raw_c_type_text(): |
| return "JSONArray" |
| |
| @staticmethod |
| def get_raw_type_model(): |
| return TypeModel.Array |
| |
| |
| def replace_right_shift(input_str): |
| return input_str.replace(">>", "> >") |
| |
| |
| class CommandReturnPassModel: |
| class ByReference: |
| def __init__(self, var_type, set_condition): |
| self.var_type = var_type |
| self.set_condition = set_condition |
| |
| def get_return_var_type(self): |
| return self.var_type |
| |
| @staticmethod |
| def get_output_argument_prefix(): |
| return "" |
| |
| @staticmethod |
| def get_output_to_raw_expression(): |
| return "%s" |
| |
| def get_output_parameter_type(self): |
| return self.var_type + "&" |
| |
| def get_set_return_condition(self): |
| return self.set_condition |
| |
| class ByPointer: |
| def __init__(self, var_type): |
| self.var_type = var_type |
| |
| def get_return_var_type(self): |
| return self.var_type |
| |
| @staticmethod |
| def get_output_argument_prefix(): |
| return "&" |
| |
| @staticmethod |
| def get_output_to_raw_expression(): |
| return "%s" |
| |
| def get_output_parameter_type(self): |
| return self.var_type + "*" |
| |
| @staticmethod |
| def get_set_return_condition(): |
| return None |
| |
| class OptOutput: |
| def __init__(self, var_type): |
| self.var_type = var_type |
| |
| def get_return_var_type(self): |
| return "TypeBuilder::OptOutput<%s>" % self.var_type |
| |
| @staticmethod |
| def get_output_argument_prefix(): |
| return "&" |
| |
| @staticmethod |
| def get_output_to_raw_expression(): |
| return "%s.getValue()" |
| |
| def get_output_parameter_type(self): |
| return "TypeBuilder::OptOutput<%s>*" % self.var_type |
| |
| @staticmethod |
| def get_set_return_condition(): |
| return "%s.isAssigned()" |
| |
| |
| class TypeModel: |
| class RefPtrBased(object): |
| def __init__(self, class_name): |
| self.class_name = class_name |
| self.optional = False |
| |
| def get_optional(self): |
| result = TypeModel.RefPtrBased(self.class_name) |
| result.optional = True |
| return result |
| |
| def get_command_return_pass_model(self): |
| if self.optional: |
| set_condition = "%s" |
| else: |
| set_condition = None |
| return CommandReturnPassModel.ByReference(replace_right_shift("RefPtr<%s>" % self.class_name), set_condition) |
| |
| def get_input_param_type_text(self): |
| return replace_right_shift("PassRefPtr<%s>" % self.class_name) |
| |
| @staticmethod |
| def get_event_setter_expression_pattern(): |
| return "%s" |
| |
| class Enum(object): |
| def __init__(self, base_type_name): |
| self.type_name = base_type_name + "::Enum" |
| |
| def get_optional(base_self): |
| class EnumOptional: |
| @classmethod |
| def get_optional(cls): |
| return cls |
| |
| @staticmethod |
| def get_command_return_pass_model(): |
| return CommandReturnPassModel.OptOutput(base_self.type_name) |
| |
| @staticmethod |
| def get_input_param_type_text(): |
| return base_self.type_name + "*" |
| |
| @staticmethod |
| def get_event_setter_expression_pattern(): |
| raise Exception("TODO") |
| return EnumOptional |
| |
| def get_command_return_pass_model(self): |
| return CommandReturnPassModel.ByPointer(self.type_name) |
| |
| def get_input_param_type_text(self): |
| return self.type_name |
| |
| @staticmethod |
| def get_event_setter_expression_pattern(): |
| return "%s" |
| |
| class ValueType(object): |
| def __init__(self, type_name, is_heavy): |
| self.type_name = type_name |
| self.is_heavy = is_heavy |
| |
| def get_optional(self): |
| return self.ValueOptional(self) |
| |
| def get_command_return_pass_model(self): |
| return CommandReturnPassModel.ByPointer(self.type_name) |
| |
| def get_input_param_type_text(self): |
| if self.is_heavy: |
| return "const %s&" % self.type_name |
| else: |
| return self.type_name |
| |
| def get_opt_output_type_(self): |
| return self.type_name |
| |
| @staticmethod |
| def get_event_setter_expression_pattern(): |
| return "%s" |
| |
| class ValueOptional: |
| def __init__(self, base): |
| self.base = base |
| |
| def get_optional(self): |
| return self |
| |
| def get_command_return_pass_model(self): |
| return CommandReturnPassModel.OptOutput(self.base.get_opt_output_type_()) |
| |
| def get_input_param_type_text(self): |
| return "const %s* const" % self.base.type_name |
| |
| @staticmethod |
| def get_event_setter_expression_pattern(): |
| return "*%s" |
| |
| @classmethod |
| def init_class(cls): |
| cls.Bool = cls.ValueType("bool", False) |
| cls.Int = cls.ValueType("int", False) |
| cls.Number = cls.ValueType("double", False) |
| cls.String = cls.ValueType("String", True,) |
| cls.Object = cls.RefPtrBased("JSONObject") |
| cls.Array = cls.RefPtrBased("JSONArray") |
| cls.Any = cls.RefPtrBased("JSONValue") |
| |
| TypeModel.init_class() |
| |
| |
| # Collection of JSONObject class methods that are likely to be overloaded in generated class. |
| # We must explicitly import all overloaded methods or they won't be available to user. |
| INSPECTOR_OBJECT_SETTER_NAMES = frozenset(["setValue", "setBoolean", "setNumber", "setString", "setValue", "setObject", "setArray"]) |
| |
| |
| def fix_type_name(json_name): |
| if json_name in TYPE_NAME_FIX_MAP: |
| fixed = TYPE_NAME_FIX_MAP[json_name] |
| |
| class Result(object): |
| class_name = fixed |
| |
| @staticmethod |
| def output_comment(writer): |
| writer.newline("// Type originally was named '%s'.\n" % json_name) |
| else: |
| |
| class Result(object): |
| class_name = json_name |
| |
| @staticmethod |
| def output_comment(writer): |
| pass |
| |
| return Result |
| |
| |
| class Writer: |
| def __init__(self, output, indent): |
| self.output = output |
| self.indent = indent |
| |
| def newline(self, str): |
| if (self.indent): |
| self.output.append(self.indent) |
| self.output.append(str) |
| |
| def append(self, str): |
| self.output.append(str) |
| |
| def newline_multiline(self, str): |
| parts = str.split('\n') |
| self.newline(parts[0]) |
| for p in parts[1:]: |
| self.output.append('\n') |
| if p: |
| self.newline(p) |
| |
| def append_multiline(self, str): |
| parts = str.split('\n') |
| self.append(parts[0]) |
| for p in parts[1:]: |
| self.output.append('\n') |
| if p: |
| self.newline(p) |
| |
| def get_indent(self): |
| return self.indent |
| |
| def insert_writer(self, additional_indent): |
| new_output = [] |
| self.output.append(new_output) |
| return Writer(new_output, self.indent + additional_indent) |
| |
| |
| class EnumConstants: |
| map_ = {} |
| constants_ = [] |
| |
| @classmethod |
| def add_constant(cls, value): |
| if value in cls.map_: |
| return cls.map_[value] |
| else: |
| pos = len(cls.map_) |
| cls.map_[value] = pos |
| cls.constants_.append(value) |
| return pos |
| |
| @classmethod |
| def get_enum_constant_code(cls): |
| output = [] |
| for item in cls.constants_: |
| output.append(" \"" + item + "\"") |
| return ",\n".join(output) + "\n" |
| |
| |
| # Typebuilder code is generated in several passes: first typedefs, then other classes. |
| # Manual pass management is needed because we cannot have forward declarations for typedefs. |
| class TypeBuilderPass: |
| TYPEDEF = "typedef" |
| MAIN = "main" |
| |
| |
| class TypeBindings: |
| @staticmethod |
| def create_named_type_declaration(json_typable, context_domain_name, type_data): |
| json_type = type_data.get_json_type() |
| |
| class Helper: |
| is_ad_hoc = False |
| full_name_prefix_for_use = "TypeBuilder::" + context_domain_name + "::" |
| full_name_prefix_for_impl = "TypeBuilder::" + context_domain_name + "::" |
| |
| @staticmethod |
| def write_doc(writer): |
| if "description" in json_type: |
| writer.newline("/* ") |
| writer.append(json_type["description"]) |
| writer.append(" */\n") |
| |
| @staticmethod |
| def add_to_forward_listener(forward_listener): |
| forward_listener.add_type_data(type_data) |
| |
| |
| fixed_type_name = fix_type_name(json_type["id"]) |
| return TypeBindings.create_type_declaration_(json_typable, context_domain_name, fixed_type_name, Helper) |
| |
| @staticmethod |
| def create_ad_hoc_type_declaration(json_typable, context_domain_name, ad_hoc_type_context): |
| class Helper: |
| is_ad_hoc = True |
| full_name_prefix_for_use = ad_hoc_type_context.container_relative_name_prefix |
| full_name_prefix_for_impl = ad_hoc_type_context.container_full_name_prefix |
| |
| @staticmethod |
| def write_doc(writer): |
| pass |
| |
| @staticmethod |
| def add_to_forward_listener(forward_listener): |
| pass |
| fixed_type_name = ad_hoc_type_context.get_type_name_fix() |
| return TypeBindings.create_type_declaration_(json_typable, context_domain_name, fixed_type_name, Helper) |
| |
| @staticmethod |
| def create_type_declaration_(json_typable, context_domain_name, fixed_type_name, helper): |
| if json_typable["type"] == "string": |
| if "enum" in json_typable: |
| |
| class EnumBinding: |
| need_user_runtime_cast_ = False |
| need_internal_runtime_cast_ = False |
| |
| @classmethod |
| def resolve_inner(cls, resolve_context): |
| pass |
| |
| @classmethod |
| def request_user_runtime_cast(cls, request): |
| if request: |
| cls.need_user_runtime_cast_ = True |
| request.acknowledge() |
| |
| @classmethod |
| def request_internal_runtime_cast(cls): |
| cls.need_internal_runtime_cast_ = True |
| |
| @classmethod |
| def get_code_generator(enum_binding_cls): |
| |
| class CodeGenerator: |
| @staticmethod |
| def generate_type_builder(writer, generate_context): |
| enum = json_typable["enum"] |
| helper.write_doc(writer) |
| enum_name = fixed_type_name.class_name |
| fixed_type_name.output_comment(writer) |
| writer.newline("struct ") |
| writer.append(enum_name) |
| writer.append(" {\n") |
| writer.newline(" enum Enum {\n") |
| for enum_item in enum: |
| enum_pos = EnumConstants.add_constant(enum_item) |
| |
| item_c_name = enum_item.replace('-', '_') |
| item_c_name = Capitalizer.lower_camel_case_to_upper(item_c_name) |
| if item_c_name in TYPE_NAME_FIX_MAP: |
| item_c_name = TYPE_NAME_FIX_MAP[item_c_name] |
| writer.newline(" ") |
| writer.append(item_c_name) |
| writer.append(" = ") |
| writer.append("%s" % enum_pos) |
| writer.append(",\n") |
| writer.newline(" };\n") |
| if enum_binding_cls.need_user_runtime_cast_: |
| raise Exception("Not yet implemented") |
| |
| if enum_binding_cls.need_internal_runtime_cast_: |
| writer.append("#if %s\n" % VALIDATOR_IFDEF_NAME) |
| writer.newline(" static void assertCorrectValue(JSONValue* value);\n") |
| writer.append("#endif // %s\n" % VALIDATOR_IFDEF_NAME) |
| |
| validator_writer = generate_context.validator_writer |
| |
| validator_writer.newline("void %s%s::assertCorrectValue(JSONValue* value)\n" % (helper.full_name_prefix_for_impl, enum_name)) |
| validator_writer.newline("{\n") |
| validator_writer.newline(" WTF::String s;\n") |
| validator_writer.newline(" bool cast_res = value->asString(&s);\n") |
| validator_writer.newline(" ASSERT(cast_res);\n") |
| if len(enum) > 0: |
| condition_list = [] |
| for enum_item in enum: |
| enum_pos = EnumConstants.add_constant(enum_item) |
| condition_list.append("s == \"%s\"" % enum_item) |
| validator_writer.newline(" ASSERT(%s);\n" % " || ".join(condition_list)) |
| validator_writer.newline("}\n") |
| |
| validator_writer.newline("\n\n") |
| |
| writer.newline("}; // struct ") |
| writer.append(enum_name) |
| writer.append("\n\n") |
| |
| @staticmethod |
| def register_use(forward_listener): |
| pass |
| |
| @staticmethod |
| def get_generate_pass_id(): |
| return TypeBuilderPass.MAIN |
| |
| return CodeGenerator |
| |
| @classmethod |
| def get_validator_call_text(cls): |
| return helper.full_name_prefix_for_use + fixed_type_name.class_name + "::assertCorrectValue" |
| |
| @classmethod |
| def get_array_item_c_type_text(cls): |
| return helper.full_name_prefix_for_use + fixed_type_name.class_name + "::Enum" |
| |
| @staticmethod |
| def get_setter_value_expression_pattern(): |
| return "TypeBuilder::getEnumConstantValue(%s)" |
| |
| @staticmethod |
| def reduce_to_raw_type(): |
| return RawTypes.String |
| |
| @staticmethod |
| def get_type_model(): |
| return TypeModel.Enum(helper.full_name_prefix_for_use + fixed_type_name.class_name) |
| |
| return EnumBinding |
| else: |
| if helper.is_ad_hoc: |
| |
| class PlainString: |
| @classmethod |
| def resolve_inner(cls, resolve_context): |
| pass |
| |
| @staticmethod |
| def request_user_runtime_cast(request): |
| raise Exception("Unsupported") |
| |
| @staticmethod |
| def request_internal_runtime_cast(): |
| pass |
| |
| @staticmethod |
| def get_code_generator(): |
| return None |
| |
| @classmethod |
| def get_validator_call_text(cls): |
| return RawTypes.String.get_raw_validator_call_text() |
| |
| @staticmethod |
| def reduce_to_raw_type(): |
| return RawTypes.String |
| |
| @staticmethod |
| def get_type_model(): |
| return TypeModel.String |
| |
| @staticmethod |
| def get_setter_value_expression_pattern(): |
| return None |
| |
| @classmethod |
| def get_array_item_c_type_text(cls): |
| return cls.reduce_to_raw_type().get_array_item_raw_c_type_text() |
| |
| return PlainString |
| |
| else: |
| |
| class TypedefString: |
| @classmethod |
| def resolve_inner(cls, resolve_context): |
| pass |
| |
| @staticmethod |
| def request_user_runtime_cast(request): |
| raise Exception("Unsupported") |
| |
| @staticmethod |
| def request_internal_runtime_cast(): |
| pass |
| |
| @staticmethod |
| def get_code_generator(): |
| class CodeGenerator: |
| @staticmethod |
| def generate_type_builder(writer, generate_context): |
| helper.write_doc(writer) |
| fixed_type_name.output_comment(writer) |
| writer.newline("typedef String ") |
| writer.append(fixed_type_name.class_name) |
| writer.append(";\n\n") |
| |
| @staticmethod |
| def register_use(forward_listener): |
| pass |
| |
| @staticmethod |
| def get_generate_pass_id(): |
| return TypeBuilderPass.TYPEDEF |
| |
| return CodeGenerator |
| |
| @classmethod |
| def get_validator_call_text(cls): |
| return RawTypes.String.get_raw_validator_call_text() |
| |
| @staticmethod |
| def reduce_to_raw_type(): |
| return RawTypes.String |
| |
| @staticmethod |
| def get_type_model(): |
| return TypeModel.ValueType("%s%s" % (helper.full_name_prefix_for_use, fixed_type_name.class_name), True) |
| |
| @staticmethod |
| def get_setter_value_expression_pattern(): |
| return None |
| |
| @classmethod |
| def get_array_item_c_type_text(cls): |
| return "%s%s" % (helper.full_name_prefix_for_use, fixed_type_name.class_name) |
| |
| return TypedefString |
| |
| elif json_typable["type"] == "object": |
| if "properties" in json_typable: |
| |
| class ClassBinding: |
| resolve_data_ = None |
| need_user_runtime_cast_ = False |
| need_internal_runtime_cast_ = False |
| |
| @classmethod |
| def resolve_inner(cls, resolve_context): |
| if cls.resolve_data_: |
| return |
| |
| properties = json_typable["properties"] |
| main = [] |
| optional = [] |
| |
| ad_hoc_type_list = [] |
| |
| for prop in properties: |
| prop_name = prop["name"] |
| 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) |
| binding = resolve_param_type(prop, context_domain_name, ad_hoc_type_context) |
| |
| code_generator = binding.get_code_generator() |
| if code_generator: |
| code_generator.register_use(resolve_context.forward_listener) |
| |
| class PropertyData: |
| param_type_binding = binding |
| p = prop |
| |
| if prop.get("optional"): |
| optional.append(PropertyData) |
| else: |
| main.append(PropertyData) |
| |
| class ResolveData: |
| main_properties = main |
| optional_properties = optional |
| ad_hoc_types = ad_hoc_type_list |
| |
| cls.resolve_data_ = ResolveData |
| |
| for ad_hoc in ad_hoc_type_list: |
| ad_hoc.resolve_inner(resolve_context) |
| |
| @classmethod |
| def request_user_runtime_cast(cls, request): |
| if not request: |
| return |
| cls.need_user_runtime_cast_ = True |
| request.acknowledge() |
| cls.request_internal_runtime_cast() |
| |
| @classmethod |
| def request_internal_runtime_cast(cls): |
| if cls.need_internal_runtime_cast_: |
| return |
| cls.need_internal_runtime_cast_ = True |
| for p in cls.resolve_data_.main_properties: |
| p.param_type_binding.request_internal_runtime_cast() |
| for p in cls.resolve_data_.optional_properties: |
| p.param_type_binding.request_internal_runtime_cast() |
| |
| @classmethod |
| def get_code_generator(class_binding_cls): |
| class CodeGenerator: |
| @classmethod |
| def generate_type_builder(cls, writer, generate_context): |
| resolve_data = class_binding_cls.resolve_data_ |
| helper.write_doc(writer) |
| class_name = fixed_type_name.class_name |
| |
| is_open_type = (context_domain_name + "." + class_name) in TYPES_WITH_OPEN_FIELD_LIST_SET |
| |
| fixed_type_name.output_comment(writer) |
| writer.newline("class ") |
| writer.append(class_name) |
| writer.append(" : public ") |
| if is_open_type: |
| writer.append("JSONObject") |
| else: |
| writer.append("JSONObjectBase") |
| writer.append(" {\n") |
| writer.newline("public:\n") |
| ad_hoc_type_writer = writer.insert_writer(" ") |
| |
| for ad_hoc_type in resolve_data.ad_hoc_types: |
| code_generator = ad_hoc_type.get_code_generator() |
| if code_generator: |
| code_generator.generate_type_builder(ad_hoc_type_writer, generate_context) |
| |
| writer.newline_multiline( |
| """ enum { |
| NoFieldsSet = 0, |
| """) |
| |
| state_enum_items = [] |
| if len(resolve_data.main_properties) > 0: |
| pos = 0 |
| for prop_data in resolve_data.main_properties: |
| item_name = Capitalizer.lower_camel_case_to_upper(prop_data.p["name"]) + "Set" |
| state_enum_items.append(item_name) |
| writer.newline(" %s = 1 << %s,\n" % (item_name, pos)) |
| pos += 1 |
| all_fields_set_value = "(" + (" | ".join(state_enum_items)) + ")" |
| else: |
| all_fields_set_value = "0" |
| |
| writer.newline_multiline(CodeGeneratorInspectorStrings.class_binding_builder_part_1 |
| % (all_fields_set_value, class_name, class_name)) |
| |
| pos = 0 |
| for prop_data in resolve_data.main_properties: |
| prop_name = prop_data.p["name"] |
| |
| param_type_binding = prop_data.param_type_binding |
| param_raw_type = param_type_binding.reduce_to_raw_type() |
| |
| writer.newline_multiline(CodeGeneratorInspectorStrings.class_binding_builder_part_2 |
| % (state_enum_items[pos], |
| Capitalizer.lower_camel_case_to_upper(prop_name), |
| param_type_binding.get_type_model().get_input_param_type_text(), |
| state_enum_items[pos], prop_name, |
| param_raw_type.get_setter_name(), prop_name, |
| format_setter_value_expression(param_type_binding, "value"), |
| state_enum_items[pos])) |
| |
| pos += 1 |
| |
| writer.newline_multiline(CodeGeneratorInspectorStrings.class_binding_builder_part_3 |
| % (class_name, class_name, class_name, class_name, class_name)) |
| |
| writer.newline(" /*\n") |
| writer.newline(" * Synthetic constructor:\n") |
| writer.newline(" * RefPtr<%s> result = %s::create()" % (class_name, class_name)) |
| for prop_data in resolve_data.main_properties: |
| writer.append_multiline("\n * .set%s(...)" % Capitalizer.lower_camel_case_to_upper(prop_data.p["name"])) |
| writer.append_multiline(";\n */\n") |
| |
| writer.newline_multiline(CodeGeneratorInspectorStrings.class_binding_builder_part_4) |
| |
| writer.newline(" typedef TypeBuilder::StructItemTraits ItemTraits;\n") |
| |
| for prop_data in resolve_data.main_properties: |
| prop_name = prop_data.p["name"] |
| param_type_binding = prop_data.param_type_binding |
| if isinstance(param_type_binding.get_type_model(), TypeModel.ValueType): |
| writer.append_multiline("\n void %s" % prop_name) |
| writer.append("(%s value)\n" % param_type_binding.get_type_model().get_command_return_pass_model().get_output_parameter_type()) |
| writer.newline(" {\n") |
| writer.newline(" JSONObjectBase::get%s(\"%s\", value);\n" |
| % (param_type_binding.reduce_to_raw_type().get_setter_name(), prop_data.p["name"])) |
| writer.newline(" }\n") |
| |
| for prop_data in resolve_data.optional_properties: |
| prop_name = prop_data.p["name"] |
| param_type_binding = prop_data.param_type_binding |
| setter_name = "set%s" % Capitalizer.lower_camel_case_to_upper(prop_name) |
| |
| writer.append_multiline("\n void %s" % setter_name) |
| writer.append("(%s value)\n" % param_type_binding.get_type_model().get_input_param_type_text()) |
| writer.newline(" {\n") |
| writer.newline(" this->set%s(\"%s\", %s);\n" |
| % (param_type_binding.reduce_to_raw_type().get_setter_name(), prop_data.p["name"], |
| format_setter_value_expression(param_type_binding, "value"))) |
| writer.newline(" }\n") |
| |
| if setter_name in INSPECTOR_OBJECT_SETTER_NAMES: |
| writer.newline(" using JSONObjectBase::%s;\n\n" % setter_name) |
| |
| if class_binding_cls.need_user_runtime_cast_: |
| writer.newline(" static PassRefPtr<%s> runtimeCast(PassRefPtr<JSONValue> value)\n" % class_name) |
| writer.newline(" {\n") |
| writer.newline(" RefPtr<JSONObject> object;\n") |
| writer.newline(" bool castRes = value->asObject(&object);\n") |
| writer.newline(" ASSERT_UNUSED(castRes, castRes);\n") |
| writer.append("#if %s\n" % VALIDATOR_IFDEF_NAME) |
| writer.newline(" assertCorrectValue(object.get());\n") |
| writer.append("#endif // %s\n" % VALIDATOR_IFDEF_NAME) |
| writer.newline(" COMPILE_ASSERT(sizeof(%s) == sizeof(JSONObjectBase), type_cast_problem);\n" % class_name) |
| writer.newline(" return static_cast<%s*>(static_cast<JSONObjectBase*>(object.get()));\n" % class_name) |
| writer.newline(" }\n") |
| writer.append("\n") |
| |
| if class_binding_cls.need_internal_runtime_cast_: |
| writer.append("#if %s\n" % VALIDATOR_IFDEF_NAME) |
| writer.newline(" static void assertCorrectValue(JSONValue* value);\n") |
| writer.append("#endif // %s\n" % VALIDATOR_IFDEF_NAME) |
| |
| closed_field_set = (context_domain_name + "." + class_name) not in TYPES_WITH_OPEN_FIELD_LIST_SET |
| |
| validator_writer = generate_context.validator_writer |
| |
| validator_writer.newline("void %s%s::assertCorrectValue(JSONValue* value)\n" % (helper.full_name_prefix_for_impl, class_name)) |
| validator_writer.newline("{\n") |
| validator_writer.newline(" RefPtr<JSONObject> object;\n") |
| validator_writer.newline(" bool castRes = value->asObject(&object);\n") |
| validator_writer.newline(" ASSERT_UNUSED(castRes, castRes);\n") |
| for prop_data in resolve_data.main_properties: |
| validator_writer.newline(" {\n") |
| it_name = "%sPos" % prop_data.p["name"] |
| validator_writer.newline(" JSONObject::iterator %s;\n" % it_name) |
| validator_writer.newline(" %s = object->find(\"%s\");\n" % (it_name, prop_data.p["name"])) |
| validator_writer.newline(" ASSERT(%s != object->end());\n" % it_name) |
| validator_writer.newline(" %s(%s->value.get());\n" % (prop_data.param_type_binding.get_validator_call_text(), it_name)) |
| validator_writer.newline(" }\n") |
| |
| if closed_field_set: |
| validator_writer.newline(" int foundPropertiesCount = %s;\n" % len(resolve_data.main_properties)) |
| |
| for prop_data in resolve_data.optional_properties: |
| validator_writer.newline(" {\n") |
| it_name = "%sPos" % prop_data.p["name"] |
| validator_writer.newline(" JSONObject::iterator %s;\n" % it_name) |
| validator_writer.newline(" %s = object->find(\"%s\");\n" % (it_name, prop_data.p["name"])) |
| validator_writer.newline(" if (%s != object->end()) {\n" % it_name) |
| validator_writer.newline(" %s(%s->value.get());\n" % (prop_data.param_type_binding.get_validator_call_text(), it_name)) |
| if closed_field_set: |
| validator_writer.newline(" ++foundPropertiesCount;\n") |
| validator_writer.newline(" }\n") |
| validator_writer.newline(" }\n") |
| |
| if closed_field_set: |
| validator_writer.newline(" if (foundPropertiesCount != object->size()) {\n") |
| validator_writer.newline(" FATAL(\"Unexpected properties in object: %s\\n\", object->toJSONString().ascii().data());\n") |
| validator_writer.newline(" }\n") |
| validator_writer.newline("}\n") |
| |
| validator_writer.newline("\n\n") |
| |
| if is_open_type: |
| cpp_writer = generate_context.cpp_writer |
| writer.append("\n") |
| writer.newline(" // Property names for type generated as open.\n") |
| for prop_data in resolve_data.main_properties + resolve_data.optional_properties: |
| prop_name = prop_data.p["name"] |
| prop_field_name = Capitalizer.lower_camel_case_to_upper(prop_name) |
| writer.newline(" static const char %s[];\n" % (prop_field_name)) |
| cpp_writer.newline("const char %s%s::%s[] = \"%s\";\n" % (helper.full_name_prefix_for_impl, class_name, prop_field_name, prop_name)) |
| |
| |
| writer.newline("};\n\n") |
| |
| @staticmethod |
| def generate_forward_declaration(writer): |
| class_name = fixed_type_name.class_name |
| writer.newline("class ") |
| writer.append(class_name) |
| writer.append(";\n") |
| |
| @staticmethod |
| def register_use(forward_listener): |
| helper.add_to_forward_listener(forward_listener) |
| |
| @staticmethod |
| def get_generate_pass_id(): |
| return TypeBuilderPass.MAIN |
| |
| return CodeGenerator |
| |
| @staticmethod |
| def get_validator_call_text(): |
| return helper.full_name_prefix_for_use + fixed_type_name.class_name + "::assertCorrectValue" |
| |
| @classmethod |
| def get_array_item_c_type_text(cls): |
| return helper.full_name_prefix_for_use + fixed_type_name.class_name |
| |
| @staticmethod |
| def get_setter_value_expression_pattern(): |
| return None |
| |
| @staticmethod |
| def reduce_to_raw_type(): |
| return RawTypes.Object |
| |
| @staticmethod |
| def get_type_model(): |
| return TypeModel.RefPtrBased(helper.full_name_prefix_for_use + fixed_type_name.class_name) |
| |
| class AdHocTypeContextImpl: |
| def __init__(self, property_name, class_name, resolve_context, ad_hoc_type_list, parent_full_name_prefix): |
| self.property_name = property_name |
| self.class_name = class_name |
| self.resolve_context = resolve_context |
| self.ad_hoc_type_list = ad_hoc_type_list |
| self.container_full_name_prefix = parent_full_name_prefix + class_name + "::" |
| self.container_relative_name_prefix = "" |
| |
| def get_type_name_fix(self): |
| class NameFix: |
| class_name = Capitalizer.lower_camel_case_to_upper(self.property_name) |
| |
| @staticmethod |
| def output_comment(writer): |
| writer.newline("// Named after property name '%s' while generating %s.\n" % (self.property_name, self.class_name)) |
| |
| return NameFix |
| |
| def add_type(self, binding): |
| self.ad_hoc_type_list.append(binding) |
| |
| return ClassBinding |
| else: |
| |
| class PlainObjectBinding: |
| @classmethod |
| def resolve_inner(cls, resolve_context): |
| pass |
| |
| @staticmethod |
| def request_user_runtime_cast(request): |
| pass |
| |
| @staticmethod |
| def request_internal_runtime_cast(): |
| pass |
| |
| @staticmethod |
| def get_code_generator(): |
| pass |
| |
| @staticmethod |
| def get_validator_call_text(): |
| return "RuntimeCastHelper::assertType<JSONValue::TypeObject>" |
| |
| @classmethod |
| def get_array_item_c_type_text(cls): |
| return cls.reduce_to_raw_type().get_array_item_raw_c_type_text() |
| |
| @staticmethod |
| def get_setter_value_expression_pattern(): |
| return None |
| |
| @staticmethod |
| def reduce_to_raw_type(): |
| return RawTypes.Object |
| |
| @staticmethod |
| def get_type_model(): |
| return TypeModel.Object |
| |
| return PlainObjectBinding |
| elif json_typable["type"] == "array": |
| if "items" in json_typable: |
| |
| ad_hoc_types = [] |
| |
| class AdHocTypeContext: |
| container_full_name_prefix = "<not yet defined>" |
| container_relative_name_prefix = "" |
| |
| @staticmethod |
| def get_type_name_fix(): |
| return fixed_type_name |
| |
| @staticmethod |
| def add_type(binding): |
| ad_hoc_types.append(binding) |
| |
| item_binding = resolve_param_type(json_typable["items"], context_domain_name, AdHocTypeContext) |
| |
| class ArrayBinding: |
| resolve_data_ = None |
| need_internal_runtime_cast_ = False |
| |
| @classmethod |
| def resolve_inner(cls, resolve_context): |
| if cls.resolve_data_: |
| return |
| |
| class ResolveData: |
| item_type_binding = item_binding |
| ad_hoc_type_list = ad_hoc_types |
| |
| cls.resolve_data_ = ResolveData |
| |
| for t in ad_hoc_types: |
| t.resolve_inner(resolve_context) |
| |
| @classmethod |
| def request_user_runtime_cast(cls, request): |
| raise Exception("Not implemented yet") |
| |
| @classmethod |
| def request_internal_runtime_cast(cls): |
| if cls.need_internal_runtime_cast_: |
| return |
| cls.need_internal_runtime_cast_ = True |
| cls.resolve_data_.item_type_binding.request_internal_runtime_cast() |
| |
| @classmethod |
| def get_code_generator(array_binding_cls): |
| |
| class CodeGenerator: |
| @staticmethod |
| def generate_type_builder(writer, generate_context): |
| ad_hoc_type_writer = writer |
| |
| resolve_data = array_binding_cls.resolve_data_ |
| |
| for ad_hoc_type in resolve_data.ad_hoc_type_list: |
| code_generator = ad_hoc_type.get_code_generator() |
| if code_generator: |
| code_generator.generate_type_builder(ad_hoc_type_writer, generate_context) |
| |
| @staticmethod |
| def generate_forward_declaration(writer): |
| pass |
| |
| @staticmethod |
| def register_use(forward_listener): |
| item_code_generator = item_binding.get_code_generator() |
| if item_code_generator: |
| item_code_generator.register_use(forward_listener) |
| |
| @staticmethod |
| def get_generate_pass_id(): |
| return TypeBuilderPass.MAIN |
| |
| return CodeGenerator |
| |
| @classmethod |
| def get_validator_call_text(cls): |
| return cls.get_array_item_c_type_text() + "::assertCorrectValue" |
| |
| @classmethod |
| def get_array_item_c_type_text(cls): |
| return replace_right_shift("TypeBuilder::Array<%s>" % cls.resolve_data_.item_type_binding.get_array_item_c_type_text()) |
| |
| @staticmethod |
| def get_setter_value_expression_pattern(): |
| return None |
| |
| @staticmethod |
| def reduce_to_raw_type(): |
| return RawTypes.Array |
| |
| @classmethod |
| def get_type_model(cls): |
| return TypeModel.RefPtrBased(cls.get_array_item_c_type_text()) |
| |
| return ArrayBinding |
| else: |
| # Fall-through to raw type. |
| pass |
| |
| raw_type = RawTypes.get(json_typable["type"]) |
| |
| return RawTypeBinding(raw_type) |
| |
| |
| class RawTypeBinding: |
| def __init__(self, raw_type): |
| self.raw_type_ = raw_type |
| |
| def resolve_inner(self, resolve_context): |
| pass |
| |
| def request_user_runtime_cast(self, request): |
| raise Exception("Unsupported") |
| |
| def request_internal_runtime_cast(self): |
| pass |
| |
| def get_code_generator(self): |
| return None |
| |
| def get_validator_call_text(self): |
| return self.raw_type_.get_raw_validator_call_text() |
| |
| def get_array_item_c_type_text(self): |
| return self.raw_type_.get_array_item_raw_c_type_text() |
| |
| def get_setter_value_expression_pattern(self): |
| return None |
| |
| def reduce_to_raw_type(self): |
| return self.raw_type_ |
| |
| def get_type_model(self): |
| return self.raw_type_.get_raw_type_model() |
| |
| |
| class TypeData(object): |
| def __init__(self, json_type, json_domain, domain_data): |
| self.json_type_ = json_type |
| self.json_domain_ = json_domain |
| self.domain_data_ = domain_data |
| |
| if "type" not in json_type: |
| raise Exception("Unknown type") |
| |
| json_type_name = json_type["type"] |
| raw_type = RawTypes.get(json_type_name) |
| self.raw_type_ = raw_type |
| self.binding_being_resolved_ = False |
| self.binding_ = None |
| |
| def get_raw_type(self): |
| return self.raw_type_ |
| |
| def get_binding(self): |
| if not self.binding_: |
| if self.binding_being_resolved_: |
| raise Error("Type %s is already being resolved" % self.json_type_["type"]) |
| # Resolve only lazily, because resolving one named type may require resolving some other named type. |
| self.binding_being_resolved_ = True |
| try: |
| self.binding_ = TypeBindings.create_named_type_declaration(self.json_type_, self.json_domain_["domain"], self) |
| finally: |
| self.binding_being_resolved_ = False |
| |
| return self.binding_ |
| |
| def get_json_type(self): |
| return self.json_type_ |
| |
| def get_name(self): |
| return self.json_type_["id"] |
| |
| def get_domain_name(self): |
| return self.json_domain_["domain"] |
| |
| |
| class DomainData: |
| def __init__(self, json_domain): |
| self.json_domain = json_domain |
| self.types_ = [] |
| |
| def add_type(self, type_data): |
| self.types_.append(type_data) |
| |
| def name(self): |
| return self.json_domain["domain"] |
| |
| def types(self): |
| return self.types_ |
| |
| |
| class TypeMap: |
| def __init__(self, api): |
| self.map_ = {} |
| self.domains_ = [] |
| for json_domain in api["domains"]: |
| domain_name = json_domain["domain"] |
| |
| domain_map = {} |
| self.map_[domain_name] = domain_map |
| |
| domain_data = DomainData(json_domain) |
| self.domains_.append(domain_data) |
| |
| if "types" in json_domain: |
| for json_type in json_domain["types"]: |
| type_name = json_type["id"] |
| type_data = TypeData(json_type, json_domain, domain_data) |
| domain_map[type_name] = type_data |
| domain_data.add_type(type_data) |
| |
| def domains(self): |
| return self.domains_ |
| |
| def get(self, domain_name, type_name): |
| return self.map_[domain_name][type_name] |
| |
| |
| def resolve_param_type(json_parameter, scope_domain_name, ad_hoc_type_context): |
| if "$ref" in json_parameter: |
| json_ref = json_parameter["$ref"] |
| type_data = get_ref_data(json_ref, scope_domain_name) |
| return type_data.get_binding() |
| elif "type" in json_parameter: |
| result = TypeBindings.create_ad_hoc_type_declaration(json_parameter, scope_domain_name, ad_hoc_type_context) |
| ad_hoc_type_context.add_type(result) |
| return result |
| else: |
| raise Exception("Unknown type") |
| |
| def resolve_param_raw_type(json_parameter, scope_domain_name): |
| if "$ref" in json_parameter: |
| json_ref = json_parameter["$ref"] |
| type_data = get_ref_data(json_ref, scope_domain_name) |
| return type_data.get_raw_type() |
| elif "type" in json_parameter: |
| json_type = json_parameter["type"] |
| return RawTypes.get(json_type) |
| else: |
| raise Exception("Unknown type") |
| |
| |
| def get_ref_data(json_ref, scope_domain_name): |
| dot_pos = json_ref.find(".") |
| if dot_pos == -1: |
| domain_name = scope_domain_name |
| type_name = json_ref |
| else: |
| domain_name = json_ref[:dot_pos] |
| type_name = json_ref[dot_pos + 1:] |
| |
| return type_map.get(domain_name, type_name) |
| |
| |
| input_file = open(input_json_filename, "r") |
| json_string = input_file.read() |
| json_api = json.loads(json_string) |
| |
| |
| class Templates: |
| def get_this_script_path_(absolute_path): |
| absolute_path = os.path.abspath(absolute_path) |
| components = [] |
| |
| def fill_recursive(path_part, depth): |
| if depth <= 0 or path_part == '/': |
| return |
| fill_recursive(os.path.dirname(path_part), depth - 1) |
| components.append(os.path.basename(path_part)) |
| |
| # Typical path is /Source/WebCore/inspector/CodeGeneratorInspector.py |
| # Let's take 4 components from the real path then. |
| fill_recursive(absolute_path, 4) |
| |
| return "/".join(components) |
| |
| file_header_ = ("// File is generated by %s\n\n" % get_this_script_path_(sys.argv[0]) + |
| """// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| """) |
| |
| frontend_domain_class = string.Template(CodeGeneratorInspectorStrings.frontend_domain_class) |
| backend_method = string.Template(CodeGeneratorInspectorStrings.backend_method) |
| frontend_method = string.Template(CodeGeneratorInspectorStrings.frontend_method) |
| callback_main_methods = string.Template(CodeGeneratorInspectorStrings.callback_main_methods) |
| callback_failure_method = string.Template(CodeGeneratorInspectorStrings.callback_failure_method) |
| frontend_h = string.Template(file_header_ + CodeGeneratorInspectorStrings.frontend_h) |
| backend_h = string.Template(file_header_ + CodeGeneratorInspectorStrings.backend_h) |
| backend_cpp = string.Template(file_header_ + CodeGeneratorInspectorStrings.backend_cpp) |
| frontend_cpp = string.Template(file_header_ + CodeGeneratorInspectorStrings.frontend_cpp) |
| typebuilder_h = string.Template(file_header_ + CodeGeneratorInspectorStrings.typebuilder_h) |
| typebuilder_cpp = string.Template(file_header_ + CodeGeneratorInspectorStrings.typebuilder_cpp) |
| param_container_access_code = CodeGeneratorInspectorStrings.param_container_access_code |
| |
| |
| |
| |
| |
| type_map = TypeMap(json_api) |
| |
| |
| class NeedRuntimeCastRequest: |
| def __init__(self): |
| self.ack_ = None |
| |
| def acknowledge(self): |
| self.ack_ = True |
| |
| def is_acknowledged(self): |
| return self.ack_ |
| |
| |
| def resolve_all_types(): |
| runtime_cast_generate_requests = {} |
| for type_name in TYPES_WITH_RUNTIME_CAST_SET: |
| runtime_cast_generate_requests[type_name] = NeedRuntimeCastRequest() |
| |
| class ForwardListener: |
| type_data_set = set() |
| already_declared_set = set() |
| |
| @classmethod |
| def add_type_data(cls, type_data): |
| if type_data not in cls.already_declared_set: |
| cls.type_data_set.add(type_data) |
| |
| class ResolveContext: |
| forward_listener = ForwardListener |
| |
| for domain_data in type_map.domains(): |
| for type_data in domain_data.types(): |
| # Do not generate forwards for this type any longer. |
| ForwardListener.already_declared_set.add(type_data) |
| |
| binding = type_data.get_binding() |
| binding.resolve_inner(ResolveContext) |
| |
| for domain_data in type_map.domains(): |
| for type_data in domain_data.types(): |
| full_type_name = "%s.%s" % (type_data.get_domain_name(), type_data.get_name()) |
| request = runtime_cast_generate_requests.pop(full_type_name, None) |
| binding = type_data.get_binding() |
| if request: |
| binding.request_user_runtime_cast(request) |
| |
| if request and not request.is_acknowledged(): |
| raise Exception("Failed to generate runtimeCast in " + full_type_name) |
| |
| for full_type_name in runtime_cast_generate_requests: |
| raise Exception("Failed to generate runtimeCast. Type " + full_type_name + " not found") |
| |
| return ForwardListener |
| |
| |
| global_forward_listener = resolve_all_types() |
| |
| |
| def get_annotated_type_text(raw_type, annotated_type): |
| if annotated_type != raw_type: |
| return "/*%s*/ %s" % (annotated_type, raw_type) |
| else: |
| return raw_type |
| |
| |
| def format_setter_value_expression(param_type_binding, value_ref): |
| pattern = param_type_binding.get_setter_value_expression_pattern() |
| if pattern: |
| return pattern % value_ref |
| else: |
| return value_ref |
| |
| class Generator: |
| frontend_class_field_lines = [] |
| frontend_domain_class_lines = [] |
| |
| method_name_enum_list = [] |
| backend_method_declaration_list = [] |
| backend_method_implementation_list = [] |
| backend_method_name_declaration_list = [] |
| backend_method_name_declaration_index_list = [] |
| backend_method_name_declaration_current_index = 0 |
| method_handler_list = [] |
| frontend_method_list = [] |
| |
| backend_virtual_setters_list = [] |
| backend_agent_interface_list = [] |
| backend_setters_list = [] |
| backend_constructor_init_list = [] |
| backend_field_list = [] |
| frontend_constructor_init_list = [] |
| type_builder_fragments = [] |
| type_builder_forwards = [] |
| validator_impl_list = [] |
| type_builder_impl_list = [] |
| |
| |
| @staticmethod |
| def go(): |
| Generator.process_types(type_map) |
| |
| for json_domain in json_api["domains"]: |
| domain_name = json_domain["domain"] |
| domain_name_lower = domain_name.lower() |
| |
| agent_field_name = DomainNameFixes.get_fixed_data(domain_name) |
| |
| frontend_method_declaration_lines = [] |
| |
| if "events" in json_domain: |
| for json_event in json_domain["events"]: |
| Generator.process_event(json_event, domain_name, frontend_method_declaration_lines) |
| |
| Generator.frontend_class_field_lines.append(" %s m_%s;\n" % (domain_name, domain_name_lower)) |
| if Generator.frontend_constructor_init_list: |
| Generator.frontend_constructor_init_list.append(" , ") |
| Generator.frontend_constructor_init_list.append("m_%s(inspectorFrontendChannel)\n" % domain_name_lower) |
| Generator.frontend_domain_class_lines.append(Templates.frontend_domain_class.substitute(None, |
| domainClassName=domain_name, |
| domainFieldName=domain_name_lower, |
| frontendDomainMethodDeclarations="".join(flatten_list(frontend_method_declaration_lines)))) |
| |
| agent_interface_name = Capitalizer.lower_camel_case_to_upper(domain_name) + "CommandHandler" |
| Generator.backend_agent_interface_list.append(" class %s {\n" % agent_interface_name) |
| Generator.backend_agent_interface_list.append(" public:\n") |
| if "commands" in json_domain: |
| for json_command in json_domain["commands"]: |
| Generator.process_command(json_command, domain_name, agent_field_name, agent_interface_name) |
| Generator.backend_agent_interface_list.append("\n protected:\n") |
| Generator.backend_agent_interface_list.append(" virtual ~%s() { }\n" % agent_interface_name) |
| Generator.backend_agent_interface_list.append(" };\n\n") |
| |
| Generator.backend_constructor_init_list.append(" , m_%s(0)" % agent_field_name) |
| Generator.backend_virtual_setters_list.append(" virtual void registerAgent(%s* %s) = 0;" % (agent_interface_name, agent_field_name)) |
| 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)) |
| Generator.backend_field_list.append(" %s* m_%s;" % (agent_interface_name, agent_field_name)) |
| |
| @staticmethod |
| def process_event(json_event, domain_name, frontend_method_declaration_lines): |
| if (("handlers" in json_event) and (not ("renderer" in json_event["handlers"]))): |
| return |
| |
| event_name = json_event["name"] |
| |
| ad_hoc_type_output = [] |
| frontend_method_declaration_lines.append(ad_hoc_type_output) |
| ad_hoc_type_writer = Writer(ad_hoc_type_output, " ") |
| |
| decl_parameter_list = [] |
| |
| json_parameters = json_event.get("parameters") |
| Generator.generate_send_method(json_parameters, event_name, domain_name, ad_hoc_type_writer, |
| decl_parameter_list, |
| Generator.EventMethodStructTemplate, |
| Generator.frontend_method_list, Templates.frontend_method, {"eventName": event_name}) |
| |
| frontend_method_declaration_lines.append( |
| " void %s(%s);\n" % (event_name, ", ".join(decl_parameter_list))) |
| |
| class EventMethodStructTemplate: |
| @staticmethod |
| def append_prolog(line_list): |
| line_list.append(" RefPtr<JSONObject> paramsObject = JSONObject::create();\n") |
| |
| @staticmethod |
| def append_epilog(line_list): |
| line_list.append(" jsonMessage->setObject(\"params\", paramsObject);\n") |
| |
| container_name = "paramsObject" |
| |
| @staticmethod |
| def process_command(json_command, domain_name, agent_field_name, agent_interface_name): |
| if (("handlers" in json_command) and (not ("renderer" in json_command["handlers"]))): |
| return |
| |
| json_command_name = json_command["name"] |
| |
| cmd_enum_name = "k%s_%sCmd" % (domain_name, json_command["name"]) |
| |
| Generator.method_name_enum_list.append(" %s," % cmd_enum_name) |
| Generator.method_handler_list.append(" &InspectorBackendDispatcherImpl::%s_%s," % (domain_name, json_command_name)) |
| Generator.backend_method_declaration_list.append(" void %s_%s(long callId, JSONObject* requestMessageObject, JSONArray* protocolErrors);" % (domain_name, json_command_name)) |
| |
| backend_agent_interface_list = [] if "redirect" in json_command else Generator.backend_agent_interface_list |
| |
| ad_hoc_type_output = [] |
| backend_agent_interface_list.append(ad_hoc_type_output) |
| ad_hoc_type_writer = Writer(ad_hoc_type_output, " ") |
| |
| backend_agent_interface_list.append(" virtual void %s(ErrorString*" % json_command_name) |
| |
| method_in_code = "" |
| method_out_code = "" |
| agent_call_param_list = ["&error"] |
| agent_call_params_declaration_list = [" ErrorString error;"] |
| send_response_call_params_list = ["error"] |
| request_message_param = "" |
| normal_response_cook_text = "" |
| error_type_binding = None |
| if "error" in json_command: |
| json_error = json_command["error"] |
| 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 + "::") |
| error_type_model = error_type_binding.get_type_model().get_optional() |
| error_annotated_type = error_type_model.get_command_return_pass_model().get_output_parameter_type() |
| agent_call_param_list.append("%serrorData" % error_type_model.get_command_return_pass_model().get_output_argument_prefix()) |
| backend_agent_interface_list.append(", %s errorData" % error_annotated_type) |
| method_in_code += " %s errorData;\n" % error_type_model.get_command_return_pass_model().get_return_var_type() |
| send_response_call_params_list.append("errorData") |
| |
| if "parameters" in json_command: |
| json_params = json_command["parameters"] |
| request_message_param = " requestMessageObject" |
| |
| if json_params: |
| method_in_code += Templates.param_container_access_code |
| |
| for json_parameter in json_params: |
| json_param_name = json_parameter["name"] |
| param_raw_type = resolve_param_raw_type(json_parameter, domain_name) |
| |
| getter_name = param_raw_type.get_getter_name() |
| |
| optional = json_parameter.get("optional") |
| |
| non_optional_type_model = param_raw_type.get_raw_type_model() |
| |
| if optional: |
| code = (" bool %s_valueFound = false;\n" |
| " %s in_%s = get%s(paramsContainerPtr, \"%s\", &%s_valueFound, protocolErrors);\n" % |
| (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)) |
| param = "%s_valueFound ? &in_%s : 0" % (json_param_name, json_param_name) |
| # FIXME: pass optional refptr-values as PassRefPtr |
| formal_param_type_pattern = "const %s*" |
| else: |
| code = (" %s in_%s = get%s(paramsContainerPtr, \"%s\", 0, protocolErrors);\n" % |
| (non_optional_type_model.get_command_return_pass_model().get_return_var_type(), json_param_name, getter_name, json_param_name)) |
| param = "in_%s" % json_param_name |
| # FIXME: pass not-optional refptr-values as NonNullPassRefPtr |
| if param_raw_type.is_heavy_value(): |
| formal_param_type_pattern = "const %s&" |
| else: |
| formal_param_type_pattern = "%s" |
| |
| method_in_code += code |
| agent_call_param_list.append(param) |
| 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)) |
| |
| if json_command.get("async") == True: |
| callback_name = Capitalizer.lower_camel_case_to_upper(json_command_name) + "Callback" |
| |
| callback_output = [] |
| callback_writer = Writer(callback_output, ad_hoc_type_writer.get_indent()) |
| |
| decl_parameter_list = [] |
| Generator.generate_send_method(json_command.get("returns"), json_command_name, domain_name, ad_hoc_type_writer, |
| decl_parameter_list, |
| Generator.CallbackMethodStructTemplate, |
| Generator.backend_method_implementation_list, Templates.callback_main_methods, |
| {"callbackName": callback_name, "agentName": agent_interface_name}) |
| |
| callback_writer.newline("class " + callback_name + " : public CallbackBase {\n") |
| callback_writer.newline("public:\n") |
| callback_writer.newline(" " + callback_name + "(PassRefPtrWillBeRawPtr<InspectorBackendDispatcherImpl>, int id);\n") |
| callback_writer.newline(" void sendSuccess(" + ", ".join(decl_parameter_list) + ");\n") |
| error_part_writer = callback_writer.insert_writer("") |
| callback_writer.newline("};\n") |
| |
| if error_type_binding: |
| annotated_type = error_type_model.get_input_param_type_text() |
| error_part_writer.newline(" void sendFailure(const ErrorString&, %s);\n" % annotated_type) |
| error_part_writer.newline(" using CallbackBase::sendFailure;\n") |
| |
| assigment_value = error_type_model.get_event_setter_expression_pattern() % "errorData" |
| assigment_value = error_type_binding.reduce_to_raw_type().get_constructor_pattern() % assigment_value |
| |
| Generator.backend_method_implementation_list.append(Templates.callback_failure_method.substitute(None, |
| agentName=agent_interface_name, |
| callbackName=callback_name, |
| parameter=annotated_type + " errorData", |
| argument=assigment_value)) |
| |
| ad_hoc_type_output.append(callback_output) |
| |
| method_out_code += " RefPtrWillBeRawPtr<" + agent_interface_name + "::" + callback_name + "> callback = adoptRefWillBeNoop(new " + agent_interface_name + "::" + callback_name + "(this, callId));\n" |
| agent_call_param_list.append("callback") |
| normal_response_cook_text += " if (!error.length()) \n" |
| normal_response_cook_text += " return;\n" |
| normal_response_cook_text += " callback->disable();\n" |
| backend_agent_interface_list.append(", PassRefPtrWillBeRawPtr<%s> callback" % callback_name) |
| else: |
| if "returns" in json_command: |
| method_out_code += "\n" |
| agent_call_params_declaration_list.append(" RefPtr<JSONObject> result = JSONObject::create();") |
| send_response_call_params_list.append("result") |
| response_cook_list = [] |
| for json_return in json_command["returns"]: |
| |
| json_return_name = json_return["name"] |
| |
| optional = bool(json_return.get("optional")) |
| |
| 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 + "::") |
| |
| raw_type = return_type_binding.reduce_to_raw_type() |
| setter_type = raw_type.get_setter_name() |
| |
| type_model = return_type_binding.get_type_model() |
| if optional: |
| type_model = type_model.get_optional() |
| |
| code = " %s out_%s;\n" % (type_model.get_command_return_pass_model().get_return_var_type(), json_return_name) |
| param = "%sout_%s" % (type_model.get_command_return_pass_model().get_output_argument_prefix(), json_return_name) |
| var_name = "out_%s" % json_return_name |
| setter_argument = type_model.get_command_return_pass_model().get_output_to_raw_expression() % var_name |
| if return_type_binding.get_setter_value_expression_pattern(): |
| setter_argument = return_type_binding.get_setter_value_expression_pattern() % setter_argument |
| |
| cook = " result->set%s(\"%s\", %s);\n" % (setter_type, json_return_name, |
| setter_argument) |
| |
| set_condition_pattern = type_model.get_command_return_pass_model().get_set_return_condition() |
| if set_condition_pattern: |
| cook = (" if (%s)\n " % (set_condition_pattern % var_name)) + cook |
| annotated_type = type_model.get_command_return_pass_model().get_output_parameter_type() |
| |
| param_name = var_name |
| if optional: |
| param_name = "opt_" + param_name |
| |
| backend_agent_interface_list.append(", %s %s" % (annotated_type, param_name)) |
| response_cook_list.append(cook) |
| |
| method_out_code += code |
| agent_call_param_list.append(param) |
| |
| normal_response_cook_text += "".join(response_cook_list) |
| |
| if len(normal_response_cook_text) != 0: |
| normal_response_cook_text = " if (!error.length()) {\n" + normal_response_cook_text + " }" |
| |
| # Redirect to another agent's implementation. |
| agent_field = "m_" + agent_field_name |
| if "redirect" in json_command: |
| agent_field = "m_" + DomainNameFixes.get_fixed_data(json_command.get("redirect")) |
| |
| Generator.backend_method_implementation_list.append(Templates.backend_method.substitute(None, |
| domainName=domain_name, methodName=json_command_name, |
| agentField=agent_field, |
| methodCode="".join([method_in_code, method_out_code]), |
| agentCallParamsDeclaration="\n".join(agent_call_params_declaration_list), |
| agentCallParams=", ".join(agent_call_param_list), |
| requestMessageObject=request_message_param, |
| responseCook=normal_response_cook_text, |
| sendResponseCallParams=", ".join(send_response_call_params_list), |
| commandNameIndex=cmd_enum_name)) |
| declaration_command_name = "%s.%s\\0" % (domain_name, json_command_name) |
| Generator.backend_method_name_declaration_list.append(" \"%s\"" % declaration_command_name) |
| Generator.backend_method_name_declaration_index_list.append(" %d," % Generator.backend_method_name_declaration_current_index) |
| Generator.backend_method_name_declaration_current_index += len(declaration_command_name) - 1 |
| |
| backend_agent_interface_list.append(") = 0;\n") |
| |
| class CallbackMethodStructTemplate: |
| @staticmethod |
| def append_prolog(line_list): |
| pass |
| |
| @staticmethod |
| def append_epilog(line_list): |
| pass |
| |
| container_name = "jsonMessage" |
| |
| # Generates common code for event sending and callback response data sending. |
| @staticmethod |
| def generate_send_method(parameters, event_name, domain_name, ad_hoc_type_writer, decl_parameter_list, |
| method_struct_template, |
| generator_method_list, method_template, template_params): |
| method_line_list = [] |
| if parameters: |
| method_struct_template.append_prolog(method_line_list) |
| for json_parameter in parameters: |
| parameter_name = json_parameter["name"] |
| |
| param_type_binding = Generator.resolve_param_type_and_generate_ad_hoc(json_parameter, event_name, domain_name, ad_hoc_type_writer, "") |
| |
| raw_type = param_type_binding.reduce_to_raw_type() |
| raw_type_binding = RawTypeBinding(raw_type) |
| |
| optional = bool(json_parameter.get("optional")) |
| |
| setter_type = raw_type.get_setter_name() |
| |
| type_model = param_type_binding.get_type_model() |
| raw_type_model = raw_type_binding.get_type_model() |
| if optional: |
| type_model = type_model.get_optional() |
| raw_type_model = raw_type_model.get_optional() |
| |
| annotated_type = type_model.get_input_param_type_text() |
| mode_type_binding = param_type_binding |
| |
| decl_parameter_list.append("%s %s" % (annotated_type, parameter_name)) |
| |
| setter_argument = raw_type_model.get_event_setter_expression_pattern() % parameter_name |
| if mode_type_binding.get_setter_value_expression_pattern(): |
| setter_argument = mode_type_binding.get_setter_value_expression_pattern() % setter_argument |
| |
| setter_code = " %s->set%s(\"%s\", %s);\n" % (method_struct_template.container_name, setter_type, parameter_name, setter_argument) |
| if optional: |
| setter_code = (" if (%s)\n " % parameter_name) + setter_code |
| method_line_list.append(setter_code) |
| |
| method_struct_template.append_epilog(method_line_list) |
| |
| generator_method_list.append(method_template.substitute(None, |
| domainName=domain_name, |
| parameters=", ".join(decl_parameter_list), |
| code="".join(method_line_list), **template_params)) |
| |
| @classmethod |
| def resolve_param_type_and_generate_ad_hoc(cls, json_param, method_name, domain_name, ad_hoc_type_writer, container_relative_name_prefix_param): |
| param_name = json_param["name"] |
| 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) |
| |
| @staticmethod |
| def resolve_type_and_generate_ad_hoc(typable_element, element_name, method_name, domain_name, ad_hoc_type_writer, container_relative_name_prefix_param): |
| ad_hoc_type_list = [] |
| |
| class AdHocTypeContext: |
| container_full_name_prefix = "<not yet defined>" |
| container_relative_name_prefix = container_relative_name_prefix_param |
| |
| @staticmethod |
| def get_type_name_fix(): |
| class NameFix: |
| class_name = Capitalizer.lower_camel_case_to_upper(element_name) |
| |
| @staticmethod |
| def output_comment(writer): |
| writer.newline("// Named after parameter '%s' while generating command/event %s.\n" % (element_name, method_name)) |
| |
| return NameFix |
| |
| @staticmethod |
| def add_type(binding): |
| ad_hoc_type_list.append(binding) |
| |
| type_binding = resolve_param_type(typable_element, domain_name, AdHocTypeContext) |
| |
| class InterfaceForwardListener: |
| @staticmethod |
| def add_type_data(type_data): |
| pass |
| |
| class InterfaceResolveContext: |
| forward_listener = InterfaceForwardListener |
| |
| for type in ad_hoc_type_list: |
| type.resolve_inner(InterfaceResolveContext) |
| |
| class InterfaceGenerateContext: |
| validator_writer = "not supported in InterfaceGenerateContext" |
| cpp_writer = validator_writer |
| |
| for type in ad_hoc_type_list: |
| generator = type.get_code_generator() |
| if generator: |
| generator.generate_type_builder(ad_hoc_type_writer, InterfaceGenerateContext) |
| |
| return type_binding |
| |
| @staticmethod |
| def process_types(type_map): |
| output = Generator.type_builder_fragments |
| |
| class GenerateContext: |
| validator_writer = Writer(Generator.validator_impl_list, "") |
| cpp_writer = Writer(Generator.type_builder_impl_list, "") |
| |
| def generate_all_domains_code(out, type_data_callback): |
| writer = Writer(out, "") |
| for domain_data in type_map.domains(): |
| namespace_declared = [] |
| |
| def namespace_lazy_generator(): |
| if not namespace_declared: |
| writer.newline("namespace ") |
| writer.append(domain_data.name()) |
| writer.append(" {\n") |
| # What is a better way to change value from outer scope? |
| namespace_declared.append(True) |
| return writer |
| |
| for type_data in domain_data.types(): |
| type_data_callback(type_data, namespace_lazy_generator) |
| |
| if namespace_declared: |
| writer.append("} // ") |
| writer.append(domain_data.name()) |
| writer.append("\n\n") |
| |
| def create_type_builder_caller(generate_pass_id): |
| def call_type_builder(type_data, writer_getter): |
| code_generator = type_data.get_binding().get_code_generator() |
| if code_generator and generate_pass_id == code_generator.get_generate_pass_id(): |
| writer = writer_getter() |
| |
| code_generator.generate_type_builder(writer, GenerateContext) |
| return call_type_builder |
| |
| generate_all_domains_code(output, create_type_builder_caller(TypeBuilderPass.MAIN)) |
| |
| Generator.type_builder_forwards.append("// Forward declarations.\n") |
| |
| def generate_forward_callback(type_data, writer_getter): |
| if type_data in global_forward_listener.type_data_set: |
| binding = type_data.get_binding() |
| binding.get_code_generator().generate_forward_declaration(writer_getter()) |
| generate_all_domains_code(Generator.type_builder_forwards, generate_forward_callback) |
| |
| Generator.type_builder_forwards.append("// End of forward declarations.\n\n") |
| |
| Generator.type_builder_forwards.append("// Typedefs.\n") |
| |
| generate_all_domains_code(Generator.type_builder_forwards, create_type_builder_caller(TypeBuilderPass.TYPEDEF)) |
| |
| Generator.type_builder_forwards.append("// End of typedefs.\n\n") |
| |
| |
| def flatten_list(input): |
| res = [] |
| |
| def fill_recursive(l): |
| for item in l: |
| if isinstance(item, list): |
| fill_recursive(item) |
| else: |
| res.append(item) |
| fill_recursive(input) |
| return res |
| |
| def output_file(file_name): |
| return open(file_name, "w") |
| |
| |
| Generator.go() |
| |
| backend_h_file = output_file(output_dirname + "/InspectorBackendDispatcher.h") |
| backend_cpp_file = output_file(output_dirname + "/InspectorBackendDispatcher.cpp") |
| |
| frontend_h_file = output_file(output_dirname + "/InspectorFrontend.h") |
| frontend_cpp_file = output_file(output_dirname + "/InspectorFrontend.cpp") |
| |
| typebuilder_h_file = output_file(output_dirname + "/InspectorTypeBuilder.h") |
| typebuilder_cpp_file = output_file(output_dirname + "/InspectorTypeBuilder.cpp") |
| |
| |
| backend_h_file.write(Templates.backend_h.substitute(None, |
| virtualSetters="\n".join(Generator.backend_virtual_setters_list), |
| agentInterfaces="".join(flatten_list(Generator.backend_agent_interface_list)), |
| methodNamesEnumContent="\n".join(Generator.method_name_enum_list))) |
| |
| backend_cpp_file.write(Templates.backend_cpp.substitute(None, |
| constructorInit="\n".join(Generator.backend_constructor_init_list), |
| setters="\n".join(Generator.backend_setters_list), |
| fieldDeclarations="\n".join(Generator.backend_field_list), |
| methodNameDeclarations="\n".join(Generator.backend_method_name_declaration_list), |
| methodNameDeclarationsIndex="\n".join(Generator.backend_method_name_declaration_index_list), |
| methods="\n".join(Generator.backend_method_implementation_list), |
| methodDeclarations="\n".join(Generator.backend_method_declaration_list), |
| messageHandlers="\n".join(Generator.method_handler_list))) |
| |
| frontend_h_file.write(Templates.frontend_h.substitute(None, |
| fieldDeclarations="".join(Generator.frontend_class_field_lines), |
| domainClassList="".join(Generator.frontend_domain_class_lines))) |
| |
| frontend_cpp_file.write(Templates.frontend_cpp.substitute(None, |
| constructorInit="".join(Generator.frontend_constructor_init_list), |
| methods="\n".join(Generator.frontend_method_list))) |
| |
| typebuilder_h_file.write(Templates.typebuilder_h.substitute(None, |
| typeBuilders="".join(flatten_list(Generator.type_builder_fragments)), |
| forwards="".join(Generator.type_builder_forwards), |
| validatorIfdefName=VALIDATOR_IFDEF_NAME)) |
| |
| typebuilder_cpp_file.write(Templates.typebuilder_cpp.substitute(None, |
| enumConstantValues=EnumConstants.get_enum_constant_code(), |
| implCode="".join(flatten_list(Generator.type_builder_impl_list)), |
| validatorCode="".join(flatten_list(Generator.validator_impl_list)), |
| validatorIfdefName=VALIDATOR_IFDEF_NAME)) |
| |
| backend_h_file.close() |
| backend_cpp_file.close() |
| |
| frontend_h_file.close() |
| frontend_cpp_file.close() |
| |
| typebuilder_h_file.close() |
| typebuilder_cpp_file.close() |