DevTools: migrate remote debugging protocol generators to jinja2.
BUG=580337
Review URL: https://codereview.chromium.org/1702673002
Cr-Original-Commit-Position: refs/heads/master@{#376929}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: 10924eea919977e800165ab7e10adaa7b495a65f
diff --git a/CodeGenerator.py b/CodeGenerator.py
old mode 100755
new mode 100644
index c8fbfb3..e85a96d
--- a/CodeGenerator.py
+++ b/CodeGenerator.py
@@ -1,32 +1,6 @@
-#!/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.
+# Copyright 2016 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.
import os.path
import sys
@@ -38,20 +12,28 @@
except ImportError:
import simplejson as json
-import CodeGeneratorStrings
+# Path handling for libraries and templates
+# Paths have to be normalized because Jinja uses the exact template path to
+# determine the hash used in the cache filename, and we need a pre-caching step
+# to be concurrency-safe. Use absolute path because __file__ is absolute if
+# module is imported, and relative if executed directly.
+# If paths differ between pre-caching and individual file compilation, the cache
+# is regenerated, which causes a race condition and breaks concurrent build,
+# since some compile processes will try to read the partially written cache.
+module_path, module_filename = os.path.split(os.path.realpath(__file__))
+templates_dir = module_path
+third_party_dir = os.path.normpath(os.path.join(
+ module_path, os.pardir, os.pardir, os.pardir, os.pardir))
-# 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.GeneratorObjectDetails", "Debugger.CollectionEntry", "Debugger.CallFrame", "Debugger.Location"])
+# jinja2 is in chromium's third_party directory.
+# Insert at 1 so at front to override system libraries, and
+# after path[0] == invoking script dir
+sys.path.insert(1, third_party_dir)
+import jinja2
cmdline_parser = optparse.OptionParser()
cmdline_parser.add_option("--output_dir")
+cmdline_parser.add_option("--template_dir")
try:
arg_options, arg_values = cmdline_parser.parse_args()
@@ -68,1999 +50,227 @@
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)
+input_file = open(input_json_filename, "r")
+json_string = input_file.read()
+json_api = json.loads(json_string)
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
+def dash_to_camelcase(word):
+ return ''.join(to_title_case(x) or '-' for x in word.split('-'))
- @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", "IO"])
-
-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
-
-
-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("RefPtr<%s>" % self.class_name, set_condition)
-
- def get_input_param_type_text(self):
- return "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
-
- fixed_type_name.output_comment(writer)
- writer.newline("class PLATFORM_EXPORT %s : public JSONObjectBase {\n" % class_name)
- 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(CodeGeneratorStrings.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(CodeGeneratorStrings.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(CodeGeneratorStrings.class_binding_builder_part_3
- % (class_name, 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(CodeGeneratorStrings.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(" static_assert(sizeof(%s) == sizeof(JSONObjectBase), \"%s should be the same size as JSONObjectBase\");\n" % (class_name, 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)
-
- 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")
-
- 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))
- validator_writer.newline(" ++foundPropertiesCount;\n")
- validator_writer.newline(" }\n")
- validator_writer.newline(" }\n")
-
- 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")
-
- 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 "static_pointer_cast<JSONValue>(%s)"
-
- @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 "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/platform/inspector_protocol/CodeGenerator.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(CodeGeneratorStrings.frontend_domain_class)
- backend_method = string.Template(CodeGeneratorStrings.backend_method)
- frontend_method = string.Template(CodeGeneratorStrings.frontend_method)
- callback_main_methods = string.Template(CodeGeneratorStrings.callback_main_methods)
- frontend_h = string.Template(file_header_ + CodeGeneratorStrings.frontend_h)
- backend_h = string.Template(file_header_ + CodeGeneratorStrings.backend_h)
- backend_cpp = string.Template(file_header_ + CodeGeneratorStrings.backend_cpp)
- frontend_cpp = string.Template(file_header_ + CodeGeneratorStrings.frontend_cpp)
- typebuilder_h = string.Template(file_header_ + CodeGeneratorStrings.typebuilder_h)
- typebuilder_cpp = string.Template(file_header_ + CodeGeneratorStrings.typebuilder_cpp)
- param_container_access_code = CodeGeneratorStrings.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(frontendChannel)\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 PLATFORM_EXPORT %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(" &DispatcherImpl::%s_%s," % (domain_name, json_command_name))
- Generator.backend_method_declaration_list.append(" void %s_%s(int sessionId, int 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 = ""
-
- 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 + "(PassRefPtr<DispatcherImpl>, int sessionId, int id);\n")
- callback_writer.newline(" PLATFORM_EXPORT void sendSuccess(" + ", ".join(decl_parameter_list) + ");\n")
- callback_writer.newline("};\n")
-
- ad_hoc_type_output.append(callback_output)
-
- method_out_code += " RefPtr<" + agent_interface_name + "::" + callback_name + "> callback = adoptRef(new " + agent_interface_name + "::" + callback_name + "(this, sessionId, 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(", PassRefPtr<%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)
- assert Generator.backend_method_name_declaration_current_index < 2 ** 16, "Number too large for unsigned short."
- 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 initialize_jinja_env(cache_dir):
+ jinja_env = jinja2.Environment(
+ loader=jinja2.FileSystemLoader(templates_dir),
+ # Bytecode cache is not concurrency-safe unless pre-cached:
+ # if pre-cached this is read-only, but writing creates a race condition.
+ bytecode_cache=jinja2.FileSystemBytecodeCache(cache_dir),
+ keep_trailing_newline=True, # newline-terminate generated files
+ lstrip_blocks=True, # so can indent control flow tags
+ trim_blocks=True)
+ jinja_env.filters.update({"to_title_case": to_title_case, "dash_to_camelcase": dash_to_camelcase})
+ jinja_env.add_extension('jinja2.ext.loopcontrols')
+ return jinja_env
- 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()
+def patch_full_qualified_refs():
+ def patch_full_qualified_refs_in_domain(json, domain_name):
+ if isinstance(json, list):
+ for item in json:
+ patch_full_qualified_refs_in_domain(item, domain_name)
-backend_h_file = output_file(output_dirname + "/Dispatcher.h")
-backend_cpp_file = output_file(output_dirname + "/Dispatcher.cpp")
+ if not isinstance(json, dict):
+ return
+ for key in json:
+ if key != "$ref":
+ patch_full_qualified_refs_in_domain(json[key], domain_name)
+ continue
+ if json["$ref"].find(".") == -1:
+ json["$ref"] = domain_name + "." + json["$ref"]
-frontend_h_file = output_file(output_dirname + "/Frontend.h")
-frontend_cpp_file = output_file(output_dirname + "/Frontend.cpp")
-
-typebuilder_h_file = output_file(output_dirname + "/TypeBuilder.h")
-typebuilder_cpp_file = output_file(output_dirname + "/TypeBuilder.cpp")
+ for domain in json_api["domains"]:
+ patch_full_qualified_refs_in_domain(domain, domain["domain"])
-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)))
+def create_user_type_definition(domain_name, type):
+ return {
+ "return_type": "PassOwnPtr<protocol::%s::%s>" % (domain_name, type["id"]),
+ "pass_type": "PassOwnPtr<protocol::%s::%s>" % (domain_name, type["id"]),
+ "to_pass_type": "%s.release()",
+ "type": "OwnPtr<protocol::%s::%s>" % (domain_name, type["id"]),
+ "raw_type": "protocol::%s::%s" % (domain_name, type["id"]),
+ "create_type": "adoptPtr(new protocol::%s::%s())" % (domain_name, type["id"]),
+ "optional_type": "OwnPtr<protocol::%s::%s>" % (domain_name, type["id"]),
+ "optional_pass_type": "PassOwnPtr<protocol::%s::%s>" % (domain_name, type["id"]),
+ "from_optional_out": "%s.release()",
+ "json_getter": "FromValue<protocol::%s::%s>::convert(getObject(%%s))" % (domain_name, type["id"]),
+ "json_type": "TypeObject",
+ "nullable": True,
+ }
-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)))
+def create_object_type_definition():
+ return {
+ "return_type": "PassRefPtr<JSONObject>",
+ "pass_type": "PassRefPtr<JSONObject>",
+ "to_pass_type": "%s.release()",
+ "type": "RefPtr<JSONObject>",
+ "raw_type": "RefPtr<JSONObject>",
+ "optional_type": "RefPtr<JSONObject>",
+ "optional_pass_type": "PassRefPtr<JSONObject>",
+ "from_optional_out": "%s.release()",
+ "json_getter": "getObject(%s)",
+ "json_type": "TypeObject",
+ "nullable": True,
+ }
-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))
+def create_any_type_definition():
+ return {
+ "return_type": "PassRefPtr<JSONValue>",
+ "pass_type": "PassRefPtr<JSONValue>",
+ "to_pass_type": "%s.release()",
+ "type": "RefPtr<JSONValue>",
+ "raw_type": "RefPtr<JSONValue>",
+ "optional_type": "RefPtr<JSONValue>",
+ "optional_pass_type": "PassRefPtr<JSONValue>",
+ "from_optional_out": "%s.release()",
+ "json_getter": "getValue(%s)",
+ "nullable": True,
+ }
-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()
+def create_primitive_type_definition(type):
+ if type == "string":
+ return {
+ "return_type": "String",
+ "pass_type": "const String&",
+ "to_pass_type": "%s",
+ "type": "String",
+ "raw_type": "String",
+ "optional_type": "protocol::OptionalValue<String>",
+ "optional_pass_type": "const protocol::OptionalValue<String>&",
+ "from_optional_out": "%s.get()",
+ "json_getter": "getString(%s)",
+ "json_type": "TypeString",
+ "nullable": False,
+ }
-frontend_h_file.close()
-frontend_cpp_file.close()
+ typedefs = {
+ "number": "double",
+ "integer": "int",
+ "boolean": "bool"
+ }
+ jsontypes = {
+ "number": "TypeNumber",
+ "integer": "TypeNumber",
+ "boolean": "TypeBoolean",
+ }
+ return {
+ "return_type": typedefs[type],
+ "pass_type": typedefs[type],
+ "to_pass_type": "%s",
+ "type": typedefs[type],
+ "raw_type": typedefs[type],
+ "optional_type": "protocol::OptionalValue<" + typedefs[type] + ">",
+ "optional_pass_type": "const protocol::OptionalValue<" + typedefs[type] + ">&",
+ "from_optional_out": "%s.get()",
+ "json_getter": "get" + to_title_case(type) + "(%s)",
+ "json_type": jsontypes[type],
+ "nullable": False,
+ }
-typebuilder_h_file.close()
-typebuilder_cpp_file.close()
+type_definitions = {}
+type_definitions["string"] = create_primitive_type_definition("string")
+type_definitions["number"] = create_primitive_type_definition("number")
+type_definitions["integer"] = create_primitive_type_definition("integer")
+type_definitions["boolean"] = create_primitive_type_definition("boolean")
+type_definitions["object"] = create_object_type_definition()
+type_definitions["any"] = create_any_type_definition()
+
+
+def wrap_array_definition(type):
+ return {
+ "return_type": "PassOwnPtr<protocol::Array<%s>>" % type["raw_type"],
+ "pass_type": "PassOwnPtr<protocol::Array<%s>>" % type["raw_type"],
+ "to_pass_type": "%s.release()",
+ "type": "OwnPtr<protocol::Array<%s>>" % type["raw_type"],
+ "raw_type": "protocol::Array<%s>" % type["raw_type"],
+ "create_type": "adoptPtr(new protocol::Array<%s>())" % type["raw_type"],
+ "out_type": "protocol::Array<%s>&" % type["raw_type"],
+ "optional_type": "OwnPtr<protocol::Array<%s>>" % type["raw_type"],
+ "optional_pass_type": "PassOwnPtr<protocol::Array<%s>>" % type["raw_type"],
+ "from_optional_out": "%s.release()",
+ "json_getter": "protocol::Array<%s>::runtimeCast(getArray(%%s))" % type["raw_type"],
+ "json_type": "TypeArray",
+ "nullable": True,
+ }
+
+
+def create_type_definitions():
+ for domain in json_api["domains"]:
+ if not ("types" in domain):
+ continue
+ for type in domain["types"]:
+ if type["type"] == "object":
+ type_definitions[domain["domain"] + "." + type["id"]] = create_user_type_definition(domain["domain"], type)
+ elif type["type"] == "array":
+ items_type = type["items"]["type"]
+ type_definitions[domain["domain"] + "." + type["id"]] = wrap_array_definition(type_definitions[items_type])
+ else:
+ type_definitions[domain["domain"] + "." + type["id"]] = create_primitive_type_definition(type["type"])
+
+patch_full_qualified_refs()
+create_type_definitions()
+
+
+def type_definition(name):
+ return type_definitions[name]
+
+
+def resolve_type(property):
+ if "$ref" in property:
+ return type_definitions[property["$ref"]]
+ if property["type"] == "array":
+ return wrap_array_definition(resolve_type(property["items"]))
+ return type_definitions[property["type"]]
+
+
+def join_arrays(dict, keys):
+ result = []
+ for key in keys:
+ if key in dict:
+ result += dict[key]
+ return result
+
+
+def generate(class_name):
+ template_context = {
+ "class_name": class_name,
+ "api": json_api,
+ "join_arrays": join_arrays,
+ "resolve_type": resolve_type,
+ "type_definition": type_definition
+ }
+ h_template = jinja_env.get_template("/%s_h.template" % class_name)
+ cpp_template = jinja_env.get_template("/%s_cpp.template" % class_name)
+ h_file = output_file(output_dirname + "/" + class_name + ".h")
+ cpp_file = output_file(output_dirname + "/" + class_name + ".cpp")
+ h_file.write(h_template.render(template_context))
+ cpp_file.write(cpp_template.render(template_context))
+ h_file.close()
+ cpp_file.close()
+
+
+jinja_env = initialize_jinja_env(output_dirname)
+generate("Dispatcher")
+generate("Frontend")
+generate("TypeBuilder")
diff --git a/CodeGeneratorStrings.py b/CodeGeneratorStrings.py
deleted file mode 100644
index 0106d43..0000000
--- a/CodeGeneratorStrings.py
+++ /dev/null
@@ -1,912 +0,0 @@
-# Copyright (c) 2013 Google Inc. 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.
-
-# THis file contains string resources for CodeGenerator.
-# Its syntax is a Python syntax subset, suitable for manual parsing.
-
-frontend_domain_class = (
-""" class PLATFORM_EXPORT $domainClassName {
- public:
- static $domainClassName* from(Frontend* frontend) { return &(frontend->m_$domainFieldName) ;}
- $domainClassName(FrontendChannel* frontendChannel) : m_frontendChannel(frontendChannel) { }
-${frontendDomainMethodDeclarations}
- void flush() { m_frontendChannel->flush(); }
- private:
- FrontendChannel* m_frontendChannel;
- };
-
-""")
-
-backend_method = (
-"""void DispatcherImpl::${domainName}_$methodName(int sessionId, int callId, JSONObject*$requestMessageObject, JSONArray* protocolErrors)
-{
- if (!$agentField)
- protocolErrors->pushString("${domainName} handler is not available.");
-$methodCode
- if (protocolErrors->length()) {
- reportProtocolError(sessionId, callId, InvalidParams, String::format(InvalidParamsFormatString, commandName($commandNameIndex)), protocolErrors);
- return;
- }
-$agentCallParamsDeclaration
- $agentField->$methodName($agentCallParams);
-$responseCook
- sendResponse(sessionId, callId, $sendResponseCallParams);
-}
-""")
-
-frontend_method = ("""void Frontend::$domainName::$eventName($parameters)
-{
- RefPtr<JSONObject> jsonMessage = JSONObject::create();
- jsonMessage->setString("method", "$domainName.$eventName");
-$code if (m_frontendChannel)
- m_frontendChannel->sendProtocolNotification(jsonMessage.release());
-}
-""")
-
-callback_main_methods = ("""
-Dispatcher::$agentName::$callbackName::$callbackName(PassRefPtr<DispatcherImpl> backendImpl, int sessionId, int id) : CallbackBase(backendImpl, sessionId, id) {}
-
-void Dispatcher::$agentName::$callbackName::sendSuccess($parameters)
-{
- RefPtr<JSONObject> jsonMessage = JSONObject::create();
-$code sendIfActive(jsonMessage, ErrorString(), PassRefPtr<JSONValue>());
-}
-""")
-
-
-frontend_h = (
-"""#ifndef Frontend_h
-#define Frontend_h
-
-#include "platform/inspector_protocol/TypeBuilder.h"
-
-#include "platform/JSONValues.h"
-#include "platform/PlatformExport.h"
-#include "platform/inspector_protocol/FrontendChannel.h"
-#include "wtf/PassRefPtr.h"
-#include "wtf/text/WTFString.h"
-
-namespace blink {
-namespace protocol {
-
-using ErrorString = String;
-
-class PLATFORM_EXPORT Frontend {
-public:
- Frontend(FrontendChannel*);
- FrontendChannel* channel() { return m_frontendChannel; }
-
-$domainClassList
-private:
- FrontendChannel* m_frontendChannel;
-${fieldDeclarations}};
-
-} // namespace protocol
-} // namespace blink
-#endif // !defined(Frontend_h)
-""")
-
-backend_h = (
-"""#ifndef Dispatcher_h
-#define Dispatcher_h
-
-#include "platform/inspector_protocol/TypeBuilder.h"
-
-#include "platform/PlatformExport.h"
-#include "platform/heap/Handle.h"
-#include "wtf/PassRefPtr.h"
-#include "wtf/RefCounted.h"
-#include "wtf/text/WTFString.h"
-
-namespace blink {
-
-class JSONObject;
-class JSONArray;
-
-namespace protocol {
-
-class FrontendChannel;
-
-using ErrorString = String;
-
-class DispatcherImpl;
-
-class PLATFORM_EXPORT Dispatcher: public RefCounted<Dispatcher> {
-public:
- static PassRefPtr<Dispatcher> create(FrontendChannel* frontendChannel);
- virtual ~Dispatcher() { }
-
- class PLATFORM_EXPORT CallbackBase: public RefCounted<CallbackBase> {
- public:
- CallbackBase(PassRefPtr<DispatcherImpl> backendImpl, int sessionId, int id);
- virtual ~CallbackBase();
- void sendFailure(const ErrorString&);
- bool isActive();
-
- protected:
- void sendIfActive(PassRefPtr<JSONObject> partialMessage, const ErrorString& invocationError, PassRefPtr<JSONValue> errorData);
-
- private:
- void disable() { m_alreadySent = true; }
-
- RefPtr<DispatcherImpl> m_backendImpl;
- int m_sessionId;
- int m_id;
- bool m_alreadySent;
-
- friend class DispatcherImpl;
- };
-
-$agentInterfaces
-$virtualSetters
-
- virtual void clearFrontend() = 0;
-
- enum CommonErrorCode {
- ParseError = 0,
- InvalidRequest,
- MethodNotFound,
- InvalidParams,
- InternalError,
- ServerError,
- LastEntry,
- };
-
- void reportProtocolError(int sessionId, int callId, CommonErrorCode, const String& errorMessage) const;
- virtual void reportProtocolError(int sessionId, int callId, CommonErrorCode, const String& errorMessage, PassRefPtr<JSONValue> data) const = 0;
- virtual void dispatch(int sessionId, const String& message) = 0;
- static bool getCommandName(const String& message, String* result);
-
- enum MethodNames {
-$methodNamesEnumContent
-
- kMethodNamesEnumSize
- };
-
- static const char* commandName(MethodNames);
-
-private:
- static const char commandNames[];
- static const unsigned short commandNamesIndex[];
-};
-
-} // namespace protocol
-} // namespace blink
-
-using blink::protocol::ErrorString;
-
-#endif // !defined(Dispatcher_h)
-
-
-""")
-
-backend_cpp = (
-"""
-
-#include "platform/inspector_protocol/Dispatcher.h"
-
-#include "platform/JSONParser.h"
-#include "platform/JSONValues.h"
-#include "platform/inspector_protocol/FrontendChannel.h"
-#include "wtf/text/CString.h"
-#include "wtf/text/WTFString.h"
-
-namespace blink {
-namespace protocol {
-
-const char Dispatcher::commandNames[] = {
-$methodNameDeclarations
-};
-
-const unsigned short Dispatcher::commandNamesIndex[] = {
-$methodNameDeclarationsIndex
-};
-
-const char* Dispatcher::commandName(MethodNames index) {
- static_assert(static_cast<int>(kMethodNamesEnumSize) == WTF_ARRAY_LENGTH(commandNamesIndex), "MethodNames enum should have the same number of elements as commandNamesIndex");
- return commandNames + commandNamesIndex[index];
-}
-
-class DispatcherImpl : public Dispatcher {
-public:
- DispatcherImpl(FrontendChannel* frontendChannel)
- : m_frontendChannel(frontendChannel)
-$constructorInit
- {
- // Initialize dispatch map.
- const CallHandler handlers[] = {
- $messageHandlers
- };
- for (size_t i = 0; i < kMethodNamesEnumSize; ++i)
- m_dispatchMap.add(commandName(static_cast<MethodNames>(i)), handlers[i]);
-
- // Initialize common errors.
- m_commonErrors.insert(ParseError, -32700);
- m_commonErrors.insert(InvalidRequest, -32600);
- m_commonErrors.insert(MethodNotFound, -32601);
- m_commonErrors.insert(InvalidParams, -32602);
- m_commonErrors.insert(InternalError, -32603);
- m_commonErrors.insert(ServerError, -32000);
- }
-
- virtual void clearFrontend() { m_frontendChannel = 0; }
- virtual void dispatch(int sessionId, const String& message);
- virtual void reportProtocolError(int sessionId, int callId, CommonErrorCode, const String& errorMessage, PassRefPtr<JSONValue> data) const;
- using Dispatcher::reportProtocolError;
-
- void sendResponse(int sessionId, int callId, const ErrorString& invocationError, PassRefPtr<JSONValue> errorData, PassRefPtr<JSONObject> result);
- bool isActive() { return m_frontendChannel; }
-
-$setters
-private:
- using CallHandler = void (DispatcherImpl::*)(int sessionId, int callId, JSONObject* messageObject, JSONArray* protocolErrors);
- using DispatchMap = HashMap<String, CallHandler>;
-
-$methodDeclarations
-
- FrontendChannel* m_frontendChannel;
-$fieldDeclarations
-
- template<typename R, typename V, typename V0>
- static R getPropertyValueImpl(JSONObject* object, const char* name, bool* valueFound, JSONArray* protocolErrors, V0 initial_value, bool (*as_method)(JSONValue*, V*), const char* type_name);
-
- static int getInt(JSONObject* object, const char* name, bool* valueFound, JSONArray* protocolErrors);
- static double getDouble(JSONObject* object, const char* name, bool* valueFound, JSONArray* protocolErrors);
- static String getString(JSONObject* object, const char* name, bool* valueFound, JSONArray* protocolErrors);
- static bool getBoolean(JSONObject* object, const char* name, bool* valueFound, JSONArray* protocolErrors);
- static PassRefPtr<JSONObject> getObject(JSONObject* object, const char* name, bool* valueFound, JSONArray* protocolErrors);
- static PassRefPtr<JSONArray> getArray(JSONObject* object, const char* name, bool* valueFound, JSONArray* protocolErrors);
-
- void sendResponse(int sessionId, int callId, ErrorString invocationError, PassRefPtr<JSONObject> result)
- {
- sendResponse(sessionId, callId, invocationError, RefPtr<JSONValue>(), result);
- }
- void sendResponse(int sessionId, int callId, ErrorString invocationError)
- {
- sendResponse(sessionId, callId, invocationError, RefPtr<JSONValue>(), JSONObject::create());
- }
- static const char InvalidParamsFormatString[];
-
- DispatchMap m_dispatchMap;
- Vector<int> m_commonErrors;
-};
-
-const char DispatcherImpl::InvalidParamsFormatString[] = "Some arguments of method '%s' can't be processed";
-
-$methods
-
-PassRefPtr<Dispatcher> Dispatcher::create(FrontendChannel* frontendChannel)
-{
- return adoptRef(new DispatcherImpl(frontendChannel));
-}
-
-
-void DispatcherImpl::dispatch(int sessionId, const String& message)
-{
- RefPtr<Dispatcher> protect(this);
- int callId = 0;
- RefPtr<JSONValue> parsedMessage = parseJSON(message);
- ASSERT(parsedMessage);
- RefPtr<JSONObject> messageObject = parsedMessage->asObject();
- ASSERT(messageObject);
-
- RefPtr<JSONValue> callIdValue = messageObject->get("id");
- bool success = callIdValue->asNumber(&callId);
- ASSERT_UNUSED(success, success);
-
- RefPtr<JSONValue> methodValue = messageObject->get("method");
- String method;
- success = methodValue && methodValue->asString(&method);
- ASSERT_UNUSED(success, success);
-
- HashMap<String, CallHandler>::iterator it = m_dispatchMap.find(method);
- if (it == m_dispatchMap.end()) {
- reportProtocolError(sessionId, callId, MethodNotFound, "'" + method + "' wasn't found");
- return;
- }
-
- RefPtr<JSONArray> protocolErrors = JSONArray::create();
- ((*this).*it->value)(sessionId, callId, messageObject.get(), protocolErrors.get());
-}
-
-void DispatcherImpl::sendResponse(int sessionId, int callId, const ErrorString& invocationError, PassRefPtr<JSONValue> errorData, PassRefPtr<JSONObject> result)
-{
- if (invocationError.length()) {
- reportProtocolError(sessionId, callId, ServerError, invocationError, errorData);
- return;
- }
-
- RefPtr<JSONObject> responseMessage = JSONObject::create();
- responseMessage->setNumber("id", callId);
- responseMessage->setObject("result", result);
- if (m_frontendChannel)
- m_frontendChannel->sendProtocolResponse(sessionId, callId, responseMessage.release());
-}
-
-void Dispatcher::reportProtocolError(int sessionId, int callId, CommonErrorCode code, const String& errorMessage) const
-{
- reportProtocolError(sessionId, callId, code, errorMessage, PassRefPtr<JSONValue>());
-}
-
-void DispatcherImpl::reportProtocolError(int sessionId, int callId, CommonErrorCode code, const String& errorMessage, PassRefPtr<JSONValue> data) const
-{
- ASSERT(code >=0);
- ASSERT((unsigned)code < m_commonErrors.size());
- ASSERT(m_commonErrors[code]);
- RefPtr<JSONObject> error = JSONObject::create();
- error->setNumber("code", m_commonErrors[code]);
- error->setString("message", errorMessage);
- ASSERT(error);
- if (data)
- error->setValue("data", data);
- RefPtr<JSONObject> message = JSONObject::create();
- message->setObject("error", error);
- message->setNumber("id", callId);
- if (m_frontendChannel)
- m_frontendChannel->sendProtocolResponse(sessionId, callId, message.release());
-}
-
-template<typename R, typename V, typename V0>
-R DispatcherImpl::getPropertyValueImpl(JSONObject* object, const char* name, bool* valueFound, JSONArray* protocolErrors, V0 initial_value, bool (*as_method)(JSONValue*, V*), const char* type_name)
-{
- ASSERT(protocolErrors);
-
- if (valueFound)
- *valueFound = false;
-
- V value = initial_value;
-
- if (!object) {
- if (!valueFound) {
- // Required parameter in missing params container.
- protocolErrors->pushString(String::format("'params' object must contain required parameter '%s' with type '%s'.", name, type_name));
- }
- return value;
- }
-
- JSONObject::const_iterator end = object->end();
- JSONObject::const_iterator valueIterator = object->find(name);
-
- if (valueIterator == end) {
- if (!valueFound)
- protocolErrors->pushString(String::format("Parameter '%s' with type '%s' was not found.", name, type_name));
- return value;
- }
-
- if (!as_method(valueIterator->value.get(), &value))
- protocolErrors->pushString(String::format("Parameter '%s' has wrong type. It must be '%s'.", name, type_name));
- else
- if (valueFound)
- *valueFound = true;
- return value;
-}
-
-struct AsMethodBridges {
- static bool asInt(JSONValue* value, int* output) { return value->asNumber(output); }
- static bool asDouble(JSONValue* value, double* output) { return value->asNumber(output); }
- static bool asString(JSONValue* value, String* output) { return value->asString(output); }
- static bool asBoolean(JSONValue* value, bool* output) { return value->asBoolean(output); }
- static bool asObject(JSONValue* value, RefPtr<JSONObject>* output) { return value->asObject(output); }
- static bool asArray(JSONValue* value, RefPtr<JSONArray>* output) { return value->asArray(output); }
-};
-
-int DispatcherImpl::getInt(JSONObject* object, const char* name, bool* valueFound, JSONArray* protocolErrors)
-{
- return getPropertyValueImpl<int, int, int>(object, name, valueFound, protocolErrors, 0, AsMethodBridges::asInt, "Number");
-}
-
-double DispatcherImpl::getDouble(JSONObject* object, const char* name, bool* valueFound, JSONArray* protocolErrors)
-{
- return getPropertyValueImpl<double, double, double>(object, name, valueFound, protocolErrors, 0, AsMethodBridges::asDouble, "Number");
-}
-
-String DispatcherImpl::getString(JSONObject* object, const char* name, bool* valueFound, JSONArray* protocolErrors)
-{
- return getPropertyValueImpl<String, String, String>(object, name, valueFound, protocolErrors, "", AsMethodBridges::asString, "String");
-}
-
-bool DispatcherImpl::getBoolean(JSONObject* object, const char* name, bool* valueFound, JSONArray* protocolErrors)
-{
- return getPropertyValueImpl<bool, bool, bool>(object, name, valueFound, protocolErrors, false, AsMethodBridges::asBoolean, "Boolean");
-}
-
-PassRefPtr<JSONObject> DispatcherImpl::getObject(JSONObject* object, const char* name, bool* valueFound, JSONArray* protocolErrors)
-{
- return getPropertyValueImpl<PassRefPtr<JSONObject>, RefPtr<JSONObject>, JSONObject*>(object, name, valueFound, protocolErrors, 0, AsMethodBridges::asObject, "Object");
-}
-
-PassRefPtr<JSONArray> DispatcherImpl::getArray(JSONObject* object, const char* name, bool* valueFound, JSONArray* protocolErrors)
-{
- return getPropertyValueImpl<PassRefPtr<JSONArray>, RefPtr<JSONArray>, JSONArray*>(object, name, valueFound, protocolErrors, 0, AsMethodBridges::asArray, "Array");
-}
-
-bool Dispatcher::getCommandName(const String& message, String* result)
-{
- RefPtr<JSONValue> value = parseJSON(message);
- if (!value)
- return false;
-
- RefPtr<JSONObject> object = value->asObject();
- if (!object)
- return false;
-
- if (!object->getString("method", result))
- return false;
-
- return true;
-}
-
-Dispatcher::CallbackBase::CallbackBase(PassRefPtr<DispatcherImpl> backendImpl, int sessionId, int id)
- : m_backendImpl(backendImpl), m_sessionId(sessionId), m_id(id), m_alreadySent(false) {}
-
-Dispatcher::CallbackBase::~CallbackBase() {}
-
-void Dispatcher::CallbackBase::sendFailure(const ErrorString& error)
-{
- ASSERT(error.length());
- sendIfActive(nullptr, error, PassRefPtr<JSONValue>());
-}
-
-bool Dispatcher::CallbackBase::isActive()
-{
- return !m_alreadySent && m_backendImpl->isActive();
-}
-
-void Dispatcher::CallbackBase::sendIfActive(PassRefPtr<JSONObject> partialMessage, const ErrorString& invocationError, PassRefPtr<JSONValue> errorData)
-{
- if (m_alreadySent)
- return;
- m_backendImpl->sendResponse(m_sessionId, m_id, invocationError, errorData, partialMessage);
- m_alreadySent = true;
-}
-
-} // namespace protocol
-} // namespace blink
-
-""")
-
-frontend_cpp = (
-"""
-
-#include "platform/inspector_protocol/Frontend.h"
-
-#include "platform/JSONValues.h"
-#include "platform/inspector_protocol/FrontendChannel.h"
-#include "wtf/text/CString.h"
-#include "wtf/text/WTFString.h"
-
-namespace blink {
-namespace protocol {
-
-Frontend::Frontend(FrontendChannel* frontendChannel)
- : m_frontendChannel(frontendChannel)
- , $constructorInit
-{
-}
-
-$methods
-
-} // namespace protocol
-} // namespace blink
-
-""")
-
-typebuilder_h = (
-"""
-#ifndef TypeBuilder_h
-#define TypeBuilder_h
-
-#include "platform/JSONValues.h"
-#include "platform/PlatformExport.h"
-#include "wtf/Assertions.h"
-#include "wtf/PassRefPtr.h"
-
-namespace blink {
-namespace protocol {
-
-namespace TypeBuilder {
-
-template<typename T>
-class OptOutput {
-public:
- OptOutput() : m_assigned(false) { }
-
- void operator=(T value)
- {
- m_value = value;
- m_assigned = true;
- }
-
- bool isAssigned() { return m_assigned; }
-
- T getValue()
- {
- ASSERT(isAssigned());
- return m_value;
- }
-
-private:
- T m_value;
- bool m_assigned;
-
- WTF_MAKE_NONCOPYABLE(OptOutput);
-};
-
-class RuntimeCastHelper {
-public:
-#if $validatorIfdefName
- template<JSONValue::Type TYPE>
- static void assertType(JSONValue* value)
- {
- ASSERT(value->type() == TYPE);
- }
- static void assertAny(JSONValue*);
- static void assertInt(JSONValue* value);
-#endif
-};
-
-
-// This class provides "Traits" type for the input type T. It is programmed using C++ template specialization
-// technique. By default it simply takes "ItemTraits" type from T, but it doesn't work with the base types.
-template<typename T>
-struct ArrayItemHelper {
- typedef typename T::ItemTraits Traits;
-};
-
-template<typename T>
-class Array : public JSONArrayBase {
-private:
- Array() { }
-
- JSONArray* openAccessors() {
- static_assert(sizeof(JSONArray) == sizeof(Array<T>), "JSONArray should be the same size as Array<T>");
- return static_cast<JSONArray*>(static_cast<JSONArrayBase*>(this));
- }
-
-public:
- void addItem(PassRefPtr<T> value)
- {
- ArrayItemHelper<T>::Traits::pushRefPtr(this->openAccessors(), value);
- }
-
- void addItem(T value)
- {
- ArrayItemHelper<T>::Traits::pushRaw(this->openAccessors(), value);
- }
-
- static PassRefPtr<Array<T>> create()
- {
- return adoptRef(new Array<T>());
- }
-
- static PassRefPtr<Array<T>> runtimeCast(PassRefPtr<JSONValue> value)
- {
- RefPtr<JSONArray> array;
- bool castRes = value->asArray(&array);
- ASSERT_UNUSED(castRes, castRes);
-#if $validatorIfdefName
- assertCorrectValue(array.get());
-#endif // $validatorIfdefName
- static_assert(sizeof(Array<T>) == sizeof(JSONArray), "Array<T> should be the same size as JSONArray");
- return static_cast<Array<T>*>(static_cast<JSONArrayBase*>(array.get()));
- }
-
- void concat(PassRefPtr<Array<T>> array)
- {
- return ArrayItemHelper<T>::Traits::concat(this->openAccessors(), array->openAccessors());
- }
-
-#if $validatorIfdefName
- static void assertCorrectValue(JSONValue* value)
- {
- RefPtr<JSONArray> array;
- bool castRes = value->asArray(&array);
- ASSERT_UNUSED(castRes, castRes);
- for (unsigned i = 0; i < array->length(); i++)
- ArrayItemHelper<T>::Traits::template assertCorrectValue<T>(array->get(i).get());
- }
-
-#endif // $validatorIfdefName
-};
-
-struct StructItemTraits {
- static void pushRefPtr(JSONArray* array, PassRefPtr<JSONValue> value)
- {
- array->pushValue(value);
- }
-
- static void concat(JSONArray* array, JSONArray* anotherArray)
- {
- for (JSONArray::iterator it = anotherArray->begin(); it != anotherArray->end(); ++it)
- array->pushValue(*it);
- }
-
-#if $validatorIfdefName
- template<typename T>
- static void assertCorrectValue(JSONValue* value) {
- T::assertCorrectValue(value);
- }
-#endif // $validatorIfdefName
-};
-
-template<>
-struct ArrayItemHelper<String> {
- struct Traits {
- static void pushRaw(JSONArray* array, const String& value)
- {
- array->pushString(value);
- }
-
-#if $validatorIfdefName
- template<typename T>
- static void assertCorrectValue(JSONValue* value) {
- RuntimeCastHelper::assertType<JSONValue::TypeString>(value);
- }
-#endif // $validatorIfdefName
- };
-};
-
-template<>
-struct ArrayItemHelper<int> {
- struct Traits {
- static void pushRaw(JSONArray* array, int value)
- {
- array->pushInt(value);
- }
-
-#if $validatorIfdefName
- template<typename T>
- static void assertCorrectValue(JSONValue* value) {
- RuntimeCastHelper::assertInt(value);
- }
-#endif // $validatorIfdefName
- };
-};
-
-template<>
-struct ArrayItemHelper<double> {
- struct Traits {
- static void pushRaw(JSONArray* array, double value)
- {
- array->pushNumber(value);
- }
-
-#if $validatorIfdefName
- template<typename T>
- static void assertCorrectValue(JSONValue* value) {
- RuntimeCastHelper::assertType<JSONValue::TypeNumber>(value);
- }
-#endif // $validatorIfdefName
- };
-};
-
-template<>
-struct ArrayItemHelper<bool> {
- struct Traits {
- static void pushRaw(JSONArray* array, bool value)
- {
- array->pushBoolean(value);
- }
-
-#if $validatorIfdefName
- template<typename T>
- static void assertCorrectValue(JSONValue* value) {
- RuntimeCastHelper::assertType<JSONValue::TypeBoolean>(value);
- }
-#endif // $validatorIfdefName
- };
-};
-
-template<>
-struct ArrayItemHelper<JSONValue> {
- struct Traits {
- static void pushRefPtr(JSONArray* array, PassRefPtr<JSONValue> value)
- {
- array->pushValue(value);
- }
-
-#if $validatorIfdefName
- template<typename T>
- static void assertCorrectValue(JSONValue* value) {
- RuntimeCastHelper::assertAny(value);
- }
-#endif // $validatorIfdefName
- };
-};
-
-template<>
-struct ArrayItemHelper<JSONObject> {
- struct Traits {
- static void pushRefPtr(JSONArray* array, PassRefPtr<JSONValue> value)
- {
- array->pushValue(value);
- }
-
-#if $validatorIfdefName
- template<typename T>
- static void assertCorrectValue(JSONValue* value) {
- RuntimeCastHelper::assertType<JSONValue::TypeObject>(value);
- }
-#endif // $validatorIfdefName
- };
-};
-
-template<>
-struct ArrayItemHelper<JSONArray> {
- struct Traits {
- static void pushRefPtr(JSONArray* array, PassRefPtr<JSONArray> value)
- {
- array->pushArray(value);
- }
-
-#if $validatorIfdefName
- template<typename T>
- static void assertCorrectValue(JSONValue* value) {
- RuntimeCastHelper::assertType<JSONValue::TypeArray>(value);
- }
-#endif // $validatorIfdefName
- };
-};
-
-template<typename T>
-struct ArrayItemHelper<protocol::TypeBuilder::Array<T>> {
- struct Traits {
- static void pushRefPtr(JSONArray* array, PassRefPtr<protocol::TypeBuilder::Array<T>> value)
- {
- array->pushValue(value);
- }
-
-#if $validatorIfdefName
- template<typename S>
- static void assertCorrectValue(JSONValue* value) {
- S::assertCorrectValue(value);
- }
-#endif // $validatorIfdefName
- };
-};
-
-${forwards}
-
-PLATFORM_EXPORT String getEnumConstantValue(int code);
-
-${typeBuilders}
-} // namespace TypeBuilder
-
-} // namespace protocol
-} // namespace blink
-
-#endif // !defined(TypeBuilder_h)
-
-""")
-
-typebuilder_cpp = (
-"""
-
-#include "platform/inspector_protocol/TypeBuilder.h"
-#include "wtf/text/CString.h"
-
-namespace blink {
-namespace protocol {
-
-namespace TypeBuilder {
-
-const char* const enum_constant_values[] = {
-$enumConstantValues};
-
-String getEnumConstantValue(int code) {
- return enum_constant_values[code];
-}
-
-} // namespace TypeBuilder
-
-$implCode
-
-#if $validatorIfdefName
-
-void TypeBuilder::RuntimeCastHelper::assertAny(JSONValue*)
-{
- // No-op.
-}
-
-
-void TypeBuilder::RuntimeCastHelper::assertInt(JSONValue* value)
-{
- double v;
- bool castRes = value->asNumber(&v);
- ASSERT_UNUSED(castRes, castRes);
- ASSERT(static_cast<double>(static_cast<int>(v)) == v);
-}
-
-$validatorCode
-
-#endif // $validatorIfdefName
-
-} // namespace protocol
-} // namespace blink
-
-""")
-
-param_container_access_code = """
- RefPtr<JSONObject> paramsContainer = requestMessageObject->getObject("params");
- JSONObject* paramsContainerPtr = paramsContainer.get();
-"""
-
-class_binding_builder_part_1 = (
-""" AllFieldsSet = %s
- };
-
- template<int STATE>
- class Builder {
- private:
- RefPtr<JSONObject> m_result;
-
- template<int STEP> Builder<STATE | STEP>& castState()
- {
- return *reinterpret_cast<Builder<STATE | STEP>*>(this);
- }
-
- Builder(PassRefPtr</*%s*/JSONObject> ptr)
- {
- static_assert(STATE == NoFieldsSet, "builder should not be created in non-init state");
- m_result = ptr;
- }
- friend class %s;
- public:
-""")
-
-class_binding_builder_part_2 = ("""
- Builder<STATE | %s>& set%s(%s value)
- {
- static_assert(!(STATE & %s), "property %s should not be set yet");
- m_result->set%s("%s", %s);
- return castState<%s>();
- }
-""")
-
-class_binding_builder_part_3 = ("""
- operator RefPtr<%s>& ()
- {
- static_assert(STATE == AllFieldsSet, "state should be AllFieldsSet");
- static_assert(sizeof(%s) == sizeof(JSONObject), "%s should be the same size as JSONObject");
- return *reinterpret_cast<RefPtr<%s>*>(&m_result);
- }
-
- PassRefPtr<%s> release()
- {
- return RefPtr<%s>(*this).release();
- }
- };
-
-""")
-
-class_binding_builder_part_4 = (
-""" static Builder<NoFieldsSet> create()
- {
- return Builder<NoFieldsSet>(JSONObject::create());
- }
-""")
diff --git a/Dispatcher_cpp.template b/Dispatcher_cpp.template
new file mode 100644
index 0000000..95538cf
--- /dev/null
+++ b/Dispatcher_cpp.template
@@ -0,0 +1,400 @@
+// This file is generated
+
+// Copyright (c) 2016 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.
+
+#include "platform/inspector_protocol/{{class_name}}.h"
+
+#include "platform/JSONParser.h"
+#include "platform/inspector_protocol/FrontendChannel.h"
+#include "wtf/text/CString.h"
+
+namespace blink {
+namespace protocol {
+
+using protocol::OptionalValue;
+
+class DispatcherImpl : public Dispatcher {
+public:
+ DispatcherImpl(FrontendChannel* frontendChannel)
+ : m_frontendChannel(frontendChannel)
+{% for domain in api.domains %}
+ , m_{{domain.domain | lower}}Agent(0)
+{% endfor %}
+ {
+{% for domain in api.domains %}
+ {% for command in domain.commands %}
+ {% if "redirect" in command %}{% continue %}{% endif %}
+ {% if "handlers" in command and not ("renderer" in command["handlers"]) %}{% continue %}{% endif %}
+ m_dispatchMap.add("{{domain.domain}}.{{command.name}}", &DispatcherImpl::{{domain.domain}}_{{command.name}});
+ {% endfor %}
+{% endfor %}
+
+ // Initialize common errors.
+ m_commonErrors.insert(ParseError, -32700);
+ m_commonErrors.insert(InvalidRequest, -32600);
+ m_commonErrors.insert(MethodNotFound, -32601);
+ m_commonErrors.insert(InvalidParams, -32602);
+ m_commonErrors.insert(InternalError, -32603);
+ m_commonErrors.insert(ServerError, -32000);
+ }
+
+ virtual void clearFrontend() { m_frontendChannel = 0; }
+ virtual void dispatch(int sessionId, const String& message);
+ virtual void reportProtocolError(int sessionId, int callId, CommonErrorCode, const String& errorMessage, PassRefPtr<JSONValue> data) const;
+ using Dispatcher::reportProtocolError;
+
+ void sendResponse(int sessionId, int callId, const ErrorString& invocationError, PassRefPtr<JSONValue> errorData, PassRefPtr<JSONObject> result);
+ bool isActive() { return m_frontendChannel; }
+
+{% for domain in api.domains %}
+ virtual void registerAgent({{domain.domain}}CommandHandler* agent) { ASSERT(!m_{{domain.domain | lower}}Agent); m_{{domain.domain | lower}}Agent = agent; }
+{% endfor %}
+
+private:
+ using CallHandler = void (DispatcherImpl::*)(int sessionId, int callId, JSONObject* messageObject, JSONArray* protocolErrors);
+ using DispatchMap = HashMap<String, CallHandler>;
+
+{% for domain in api.domains %}
+ {% for command in domain.commands %}
+ {% if "redirect" in command %}{% continue %}{% endif %}
+ {% if "handlers" in command and not ("renderer" in command["handlers"]) %}{% continue %}{% endif %}
+ void {{domain.domain}}_{{command.name}}(int sessionId, int callId, JSONObject* requestMessageObject, JSONArray* protocolErrors);
+ {% endfor %}
+{% endfor %}
+
+ FrontendChannel* m_frontendChannel;
+
+{% for domain in api.domains %}
+ {{domain.domain}}CommandHandler* m_{{domain.domain | lower}}Agent;
+{% endfor %}
+
+ template<typename R, typename V, typename V0>
+ static R getPropertyValueImpl(JSONObject* object, const char* name, bool* valueFound, JSONArray* protocolErrors, V0 initial_value, bool (*as_method)(JSONValue*, V*), const char* type_name);
+
+ static OptionalValue<int> getInteger(JSONObject* object, const char* name, bool isOptional, JSONArray* protocolErrors);
+ static OptionalValue<double> getNumber(JSONObject* object, const char* name, bool isOptional, JSONArray* protocolErrors);
+ static OptionalValue<String> getString(JSONObject* object, const char* name, bool isOptional, JSONArray* protocolErrors);
+ static OptionalValue<bool> getBoolean(JSONObject* object, const char* name, bool isOptional, JSONArray* protocolErrors);
+ static PassRefPtr<JSONObject> getObject(JSONObject* object, const char* name, bool isOptional, JSONArray* protocolErrors);
+ static PassRefPtr<JSONArray> getArray(JSONObject* object, const char* name, bool isOptional, JSONArray* protocolErrors);
+
+ void sendResponse(int sessionId, int callId, ErrorString invocationError, PassRefPtr<JSONObject> result)
+ {
+ sendResponse(sessionId, callId, invocationError, RefPtr<JSONValue>(), result);
+ }
+
+ void sendResponse(int sessionId, int callId, ErrorString invocationError)
+ {
+ sendResponse(sessionId, callId, invocationError, RefPtr<JSONValue>(), JSONObject::create());
+ }
+
+ static const char InvalidParamsFormatString[];
+
+ DispatchMap m_dispatchMap;
+ Vector<int> m_commonErrors;
+};
+
+const char DispatcherImpl::InvalidParamsFormatString[] = "Some arguments of method '%s' can't be processed";
+{% for domain in api.domains %}
+ {% for command in domain.commands %}
+ {% if "redirect" in command %}{% continue %}{% endif %}
+ {% if "handlers" in command and not ("renderer" in command["handlers"]) %}{% continue %}{% endif %}
+
+ {% if "async" in command %}
+Dispatcher::{{domain.domain}}CommandHandler::{{command.name | to_title_case}}Callback::{{command.name | to_title_case}}Callback(PassRefPtr<DispatcherImpl> backendImpl, int sessionId, int id) : CallbackBase(backendImpl, sessionId, id) { }
+
+void Dispatcher::{{domain.domain}}CommandHandler::{{command.name | to_title_case}}Callback::sendSuccess(
+ {%- for parameter in command.returns -%}
+ {%- if "optional" in parameter -%}
+ {{resolve_type(parameter).optional_pass_type}} {{parameter.name}}
+ {%- else -%}
+ {{resolve_type(parameter).pass_type}} {{parameter.name}}
+ {%- endif -%}
+ {%- if not loop.last -%}, {% endif -%}
+ {% endfor %})
+{
+ RefPtr<JSONObject> resultObject = JSONObject::create();
+ {% for parameter in command.returns %}
+ {% if "optional" in parameter %}
+ {{resolve_type(parameter).optional_type}} opt_{{parameter.name}} = {{parameter.name}};
+ if (hasValue({{parameter.name}}))
+ resultObject->setValue("{{parameter.name}}", toValue({{resolve_type(parameter).from_optional_out % ("opt_" + parameter.name)}}));
+ {% else %}
+ resultObject->setValue("{{parameter.name}}", toValue({{parameter.name}}));
+ {% endif %}
+ {% endfor %}
+ sendIfActive(resultObject.release(), ErrorString(), PassRefPtr<JSONValue>());
+}
+ {% endif %}
+
+void DispatcherImpl::{{domain.domain}}_{{command.name}}(int sessionId, int callId, JSONObject* requestMessageObject, JSONArray* protocolErrors)
+{
+ if (!m_{{domain.domain | lower}}Agent)
+ protocolErrors->pushString("Inspector handler is not available.");
+
+ if (protocolErrors->length()) {
+ reportProtocolError(sessionId, callId, InvalidParams, String::format(InvalidParamsFormatString, "{{domain.domain}}.{{command.name}}"), protocolErrors);
+ return;
+ }
+
+ {% if "parameters" in command %}
+ // Prepare input parameters.
+ RefPtr<JSONObject> paramsContainer = requestMessageObject->getObject("params");
+ JSONObject* paramsContainerPtr = paramsContainer.get();
+ {% for property in command.parameters %}
+ {{resolve_type(property).optional_type}} in_{{property.name}} = {{resolve_type(property).json_getter % ("paramsContainerPtr, \"" + property.name + "\", " + ("true" if "optional" in property else "false") + ", protocolErrors")}};
+ {% endfor %}
+ {% endif %}
+
+ if (protocolErrors->length()) {
+ reportProtocolError(sessionId, callId, InvalidParams, String::format(InvalidParamsFormatString, "{{domain.domain}}.{{command.name}}"), protocolErrors);
+ return;
+ }
+
+ {% if "async" in command %}
+ RefPtr<{{domain.domain}}CommandHandler::{{command.name | to_title_case}}Callback> callback = adoptRef(new {{domain.domain}}CommandHandler::{{command.name | to_title_case}}Callback(this, sessionId, callId));
+ {% elif "returns" in command %}
+ // Declare output parameters.
+ RefPtr<JSONObject> result = JSONObject::create();
+ {% for property in command.returns %}
+ {% if "optional" in property %}
+ {{resolve_type(property).optional_type}} out_{{property.name}};
+ {% else %}
+ {{resolve_type(property).type}} out_{{property.name}};
+ {% endif %}
+ {% endfor %}
+ {% endif %}
+
+ ErrorString error;
+ m_{{domain.domain | lower}}Agent->{{command.name}}(&error
+ {%- for property in command.parameters -%}
+ {%- if "optional" in property -%}
+ , {{resolve_type(property).to_pass_type % ("in_" + property.name)}}
+ {%- else -%}
+ , {{resolve_type(property).from_optional_out % ("in_" + property.name)}}
+ {%- endif -%}
+ {%- endfor %}
+ {%- if "async" in command -%}
+ , callback.release()
+ {%- elif "returns" in command %}
+ {%- for property in command.returns -%}
+ , &out_{{property.name}}
+ {%- endfor %}
+ {% endif %});
+ {% if "returns" in command and not("async" in command) %}
+ if (!error.length()) {
+ {% for parameter in command.returns %}
+ {% if "optional" in parameter %}
+ if (hasValue(out_{{parameter.name}}))
+ result->setValue("{{parameter.name}}", toValue({{resolve_type(parameter).from_optional_out % ("out_" + parameter.name)}}));
+ {% else %}
+ result->setValue("{{parameter.name}}", toValue(out_{{resolve_type(parameter).to_pass_type % parameter.name}}));
+ {% endif %}
+ {% endfor %}
+ }
+ sendResponse(sessionId, callId, error, result);
+ {% elif not("async" in command) %}
+ sendResponse(sessionId, callId, error);
+ {% endif %}
+}
+ {% endfor %}
+{% endfor %}
+
+PassRefPtr<Dispatcher> Dispatcher::create(FrontendChannel* frontendChannel)
+{
+ return adoptRef(new DispatcherImpl(frontendChannel));
+}
+
+void DispatcherImpl::dispatch(int sessionId, const String& message)
+{
+ RefPtr<Dispatcher> protect(this);
+ int callId = 0;
+ RefPtr<JSONValue> parsedMessage = parseJSON(message);
+ ASSERT(parsedMessage);
+ RefPtr<JSONObject> messageObject = parsedMessage->asObject();
+ ASSERT(messageObject);
+
+ RefPtr<JSONValue> callIdValue = messageObject->get("id");
+ bool success = callIdValue->asNumber(&callId);
+ ASSERT_UNUSED(success, success);
+
+ RefPtr<JSONValue> methodValue = messageObject->get("method");
+ String method;
+ success = methodValue && methodValue->asString(&method);
+ ASSERT_UNUSED(success, success);
+
+ HashMap<String, CallHandler>::iterator it = m_dispatchMap.find(method);
+ if (it == m_dispatchMap.end()) {
+ reportProtocolError(sessionId, callId, MethodNotFound, "'" + method + "' wasn't found");
+ return;
+ }
+
+ RefPtr<JSONArray> protocolErrors = JSONArray::create();
+ ((*this).*it->value)(sessionId, callId, messageObject.get(), protocolErrors.get());
+}
+
+void DispatcherImpl::sendResponse(int sessionId, int callId, const ErrorString& invocationError, PassRefPtr<JSONValue> errorData, PassRefPtr<JSONObject> result)
+{
+ if (invocationError.length()) {
+ reportProtocolError(sessionId, callId, ServerError, invocationError, errorData);
+ return;
+ }
+
+ RefPtr<JSONObject> responseMessage = JSONObject::create();
+ responseMessage->setNumber("id", callId);
+ responseMessage->setObject("result", result);
+ if (m_frontendChannel)
+ m_frontendChannel->sendProtocolResponse(sessionId, callId, responseMessage.release());
+}
+
+void Dispatcher::reportProtocolError(int sessionId, int callId, CommonErrorCode code, const String& errorMessage) const
+{
+ reportProtocolError(sessionId, callId, code, errorMessage, PassRefPtr<JSONValue>());
+}
+
+void DispatcherImpl::reportProtocolError(int sessionId, int callId, CommonErrorCode code, const String& errorMessage, PassRefPtr<JSONValue> data) const
+{
+ ASSERT(code >=0);
+ ASSERT((unsigned)code < m_commonErrors.size());
+ ASSERT(m_commonErrors[code]);
+ RefPtr<JSONObject> error = JSONObject::create();
+ error->setNumber("code", m_commonErrors[code]);
+ error->setString("message", errorMessage);
+ ASSERT(error);
+ if (data)
+ error->setValue("data", data);
+ RefPtr<JSONObject> message = JSONObject::create();
+ message->setObject("error", error);
+ message->setNumber("id", callId);
+ if (m_frontendChannel)
+ m_frontendChannel->sendProtocolResponse(sessionId, callId, message.release());
+}
+
+template<typename R, typename V, typename V0>
+R DispatcherImpl::getPropertyValueImpl(JSONObject* object, const char* name, bool* valueFound, JSONArray* protocolErrors, V0 initial_value, bool (*as_method)(JSONValue*, V*), const char* type_name)
+{
+ ASSERT(protocolErrors);
+
+ if (valueFound)
+ *valueFound = false;
+
+ V value = initial_value;
+
+ if (!object) {
+ if (!valueFound) {
+ // Required parameter in missing params container.
+ protocolErrors->pushString(String::format("'params' object must contain required parameter '%s' with type '%s'.", name, type_name));
+ }
+ return value;
+ }
+
+ JSONObject::const_iterator end = object->end();
+ JSONObject::const_iterator valueIterator = object->find(name);
+
+ if (valueIterator == end) {
+ if (!valueFound)
+ protocolErrors->pushString(String::format("Parameter '%s' with type '%s' was not found.", name, type_name));
+ return value;
+ }
+
+ if (!as_method(valueIterator->value.get(), &value))
+ protocolErrors->pushString(String::format("Parameter '%s' has wrong type. It must be '%s'.", name, type_name));
+ else
+ if (valueFound)
+ *valueFound = true;
+ return value;
+}
+
+struct AsMethodBridges {
+ static bool asInteger(JSONValue* value, int* output) { return value->asNumber(output); }
+ static bool asNumber(JSONValue* value, double* output) { return value->asNumber(output); }
+ static bool asString(JSONValue* value, String* output) { return value->asString(output); }
+ static bool asBoolean(JSONValue* value, bool* output) { return value->asBoolean(output); }
+ static bool asObject(JSONValue* value, RefPtr<JSONObject>* output) { return value->asObject(output); }
+ static bool asArray(JSONValue* value, RefPtr<JSONArray>* output) { return value->asArray(output); }
+};
+
+OptionalValue<int> DispatcherImpl::getInteger(JSONObject* object, const char* name, bool isOptional, JSONArray* protocolErrors)
+{
+ bool valueFound = false;
+ int result = getPropertyValueImpl<int, int, int>(object, name, isOptional ? &valueFound : 0, protocolErrors, 0, AsMethodBridges::asInteger, "Number");
+ return valueFound || !isOptional ? OptionalValue<int>(result) : OptionalValue<int>();
+}
+
+OptionalValue<double> DispatcherImpl::getNumber(JSONObject* object, const char* name, bool isOptional, JSONArray* protocolErrors)
+{
+ bool valueFound = false;
+ double result = getPropertyValueImpl<double, double, double>(object, name, isOptional ? &valueFound : 0, protocolErrors, 0, AsMethodBridges::asNumber, "Number");
+ return valueFound || !isOptional ? OptionalValue<double>(result) : OptionalValue<double>();
+}
+
+OptionalValue<String> DispatcherImpl::getString(JSONObject* object, const char* name, bool isOptional, JSONArray* protocolErrors)
+{
+ bool valueFound = false;
+ String result = getPropertyValueImpl<String, String, String>(object, name, isOptional ? &valueFound : 0, protocolErrors, "", AsMethodBridges::asString, "String");
+ return valueFound || !isOptional ? OptionalValue<String>(result) : OptionalValue<String>();
+}
+
+OptionalValue<bool> DispatcherImpl::getBoolean(JSONObject* object, const char* name, bool isOptional, JSONArray* protocolErrors)
+{
+ bool valueFound = false;
+ bool result = getPropertyValueImpl<bool, bool, bool>(object, name, isOptional ? &valueFound : 0, protocolErrors, false, AsMethodBridges::asBoolean, "Boolean");
+ return valueFound || !isOptional ? OptionalValue<bool>(result) : OptionalValue<bool>();
+}
+
+PassRefPtr<JSONObject> DispatcherImpl::getObject(JSONObject* object, const char* name, bool isOptional, JSONArray* protocolErrors)
+{
+ bool valueFound = false;
+ return getPropertyValueImpl<PassRefPtr<JSONObject>, RefPtr<JSONObject>, JSONObject*>(object, name, isOptional ? &valueFound : 0, protocolErrors, 0, AsMethodBridges::asObject, "Object");
+}
+
+PassRefPtr<JSONArray> DispatcherImpl::getArray(JSONObject* object, const char* name, bool isOptional, JSONArray* protocolErrors)
+{
+ bool valueFound = false;
+ return getPropertyValueImpl<PassRefPtr<JSONArray>, RefPtr<JSONArray>, JSONArray*>(object, name, isOptional ? &valueFound : 0, protocolErrors, 0, AsMethodBridges::asArray, "Array");
+}
+
+bool Dispatcher::getCommandName(const String& message, String* result)
+{
+ RefPtr<JSONValue> value = parseJSON(message);
+ if (!value)
+ return false;
+
+ RefPtr<JSONObject> object = value->asObject();
+ if (!object)
+ return false;
+
+ if (!object->getString("method", result))
+ return false;
+
+ return true;
+}
+
+Dispatcher::CallbackBase::CallbackBase(PassRefPtr<DispatcherImpl> backendImpl, int sessionId, int id)
+ : m_backendImpl(backendImpl), m_sessionId(sessionId), m_id(id), m_alreadySent(false) { }
+
+Dispatcher::CallbackBase::~CallbackBase() { }
+
+void Dispatcher::CallbackBase::sendFailure(const ErrorString& error)
+{
+ ASSERT(error.length());
+ sendIfActive(nullptr, error, PassRefPtr<JSONValue>());
+}
+
+bool Dispatcher::CallbackBase::isActive()
+{
+ return !m_alreadySent && m_backendImpl->isActive();
+}
+
+void Dispatcher::CallbackBase::sendIfActive(PassRefPtr<JSONObject> partialMessage, const ErrorString& invocationError, PassRefPtr<JSONValue> errorData)
+{
+ if (m_alreadySent)
+ return;
+ m_backendImpl->sendResponse(m_sessionId, m_id, invocationError, errorData, partialMessage);
+ m_alreadySent = true;
+}
+
+} // namespace protocol
+} // namespace blink
diff --git a/Dispatcher_h.template b/Dispatcher_h.template
new file mode 100644
index 0000000..e0cc255
--- /dev/null
+++ b/Dispatcher_h.template
@@ -0,0 +1,121 @@
+// This file is generated
+
+// Copyright (c) 2016 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.
+
+#ifndef {{class_name}}_h
+#define {{class_name}}_h
+
+#include "platform/inspector_protocol/TypeBuilder.h"
+
+namespace blink {
+namespace protocol {
+
+class FrontendChannel;
+class DispatcherImpl;
+using ErrorString = String;
+
+class PLATFORM_EXPORT Dispatcher: public RefCounted<Dispatcher> {
+public:
+ static PassRefPtr<Dispatcher> create(FrontendChannel* frontendChannel);
+ virtual ~Dispatcher() { }
+
+ class PLATFORM_EXPORT CallbackBase: public RefCounted<CallbackBase> {
+ public:
+ CallbackBase(PassRefPtr<DispatcherImpl> backendImpl, int sessionId, int id);
+ virtual ~CallbackBase();
+ void sendFailure(const ErrorString&);
+ bool isActive();
+
+ protected:
+ void sendIfActive(PassRefPtr<JSONObject> partialMessage, const ErrorString& invocationError, PassRefPtr<JSONValue> errorData);
+
+ private:
+ void disable() { m_alreadySent = true; }
+
+ RefPtr<DispatcherImpl> m_backendImpl;
+ int m_sessionId;
+ int m_id;
+ bool m_alreadySent;
+
+ friend class DispatcherImpl;
+ };
+
+{% for domain in api.domains %}
+ class PLATFORM_EXPORT {{domain.domain}}CommandHandler {
+ public:
+ {% for command in domain.commands %}
+ {% if "redirect" in command %}{% continue %}{% endif %}
+ {% if ("handlers" in command) and not ("renderer" in command["handlers"]) %}{% continue %}{% endif %}
+ {% if "async" in command %}
+ class PLATFORM_EXPORT {{command.name | to_title_case}}Callback : public CallbackBase {
+ public:
+ {{command.name | to_title_case}}Callback(PassRefPtr<DispatcherImpl>, int sessionId, int id);
+ void sendSuccess(
+ {%- for parameter in command.returns -%}
+ {%- if "optional" in parameter -%}
+ {{resolve_type(parameter).optional_pass_type}} {{parameter.name}}
+ {%- else -%}
+ {{resolve_type(parameter).pass_type}} {{parameter.name}}
+ {%- endif -%}
+ {%- if not loop.last -%}, {% endif -%}
+ {%- endfor -%}
+ );
+ };
+ {% endif %}
+ virtual void {{command.name}}(ErrorString*
+ {%- for parameter in command.parameters -%}
+ {%- if "optional" in parameter -%}
+ , {{resolve_type(parameter).optional_pass_type}} in_{{parameter.name}}
+ {%- else -%}
+ , {{resolve_type(parameter).pass_type}} in_{{parameter.name}}
+ {%- endif -%}
+ {%- endfor -%}
+ {%- if "async" in command -%}
+ , PassRefPtr<{{command.name | to_title_case}}Callback> callback
+ {%- else -%}
+ {%- for parameter in command.returns -%}
+ {%- if "optional" in parameter -%}
+ , {{resolve_type(parameter).optional_type}}* out_{{parameter.name}}
+ {%- else -%}
+ , {{resolve_type(parameter).type}}* out_{{parameter.name}}
+ {%- endif -%}
+ {%- endfor -%}
+ {%- endif -%}
+ ) = 0;
+ {% endfor %}
+
+ protected:
+ virtual ~{{domain.domain}}CommandHandler() { }
+ };
+{% endfor %}
+
+{% for domain in api.domains %}
+ virtual void registerAgent({{domain.domain | to_title_case}}CommandHandler*) = 0;
+{% endfor %}
+
+ virtual void clearFrontend() = 0;
+
+ enum CommonErrorCode {
+ ParseError = 0,
+ InvalidRequest,
+ MethodNotFound,
+ InvalidParams,
+ InternalError,
+ ServerError,
+ LastEntry,
+ };
+
+ void reportProtocolError(int sessionId, int callId, CommonErrorCode, const String& errorMessage) const;
+ virtual void reportProtocolError(int sessionId, int callId, CommonErrorCode, const String& errorMessage, PassRefPtr<JSONValue> data) const = 0;
+ virtual void dispatch(int sessionId, const String& message) = 0;
+ static bool getCommandName(const String& message, String* result);
+};
+
+} // namespace protocol
+} // namespace blink
+
+using blink::protocol::ErrorString;
+
+#endif // !defined({{class_name}}_h)
diff --git a/Frontend_cpp.template b/Frontend_cpp.template
new file mode 100644
index 0000000..f68e040
--- /dev/null
+++ b/Frontend_cpp.template
@@ -0,0 +1,55 @@
+// This file is generated
+
+// Copyright (c) 2016 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.
+
+#include "platform/inspector_protocol/{{class_name}}.h"
+
+#include "wtf/text/CString.h"
+#include "wtf/text/WTFString.h"
+
+namespace blink {
+namespace protocol {
+
+Frontend::Frontend(FrontendChannel* frontendChannel)
+ : m_frontendChannel(frontendChannel)
+{% for domain in api.domains %}
+ , m_{{domain.domain | lower}}(frontendChannel)
+{% endfor %}
+{
+}
+
+{% for domain in api.domains %}
+ {% for event in domain.events %}
+ {% if "handlers" in event and not ("renderer" in event["handlers"]) %}{% continue %}{% endif %}
+void Frontend::{{domain.domain}}::{{event.name}}(
+ {%- for parameter in event.parameters %}
+ {% if "optional" in parameter -%}
+ {{resolve_type(parameter).optional_pass_type}}
+ {%- else -%}
+ {{resolve_type(parameter).pass_type}}
+ {%- endif %} {{parameter.name}}{%- if not loop.last -%}, {% endif -%}
+ {% endfor -%})
+{
+ RefPtr<JSONObject> jsonMessage = JSONObject::create();
+ jsonMessage->setString("method", "{{domain.domain}}.{{event.name}}");
+ RefPtr<JSONObject> paramsObject = JSONObject::create();
+ {% for parameter in event.parameters %}
+ {% if "optional" in parameter %}
+ {{resolve_type(parameter).optional_type}} opt_{{parameter.name}} = {{parameter.name}};
+ if (hasValue(opt_{{parameter.name}}))
+ paramsObject->setValue("{{parameter.name}}", toValue({{resolve_type(parameter).from_optional_out % ("opt_" + parameter.name)}}));
+ {% else %}
+ paramsObject->setValue("{{parameter.name}}", toValue({{parameter.name}}));
+ {% endif %}
+ {% endfor %}
+ jsonMessage->setObject("params", paramsObject);
+ if (m_frontendChannel)
+ m_frontendChannel->sendProtocolNotification(jsonMessage.release());
+}
+ {% endfor %}
+{% endfor %}
+
+} // namespace protocol
+} // namespace blink
diff --git a/Frontend_h.template b/Frontend_h.template
new file mode 100644
index 0000000..d0a630c
--- /dev/null
+++ b/Frontend_h.template
@@ -0,0 +1,64 @@
+// This file is generated
+
+// Copyright (c) 2016 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.
+
+#ifndef {{class_name}}_h
+#define {{class_name}}_h
+
+
+#include "platform/inspector_protocol/FrontendChannel.h"
+#include "platform/inspector_protocol/TypeBuilder.h"
+
+namespace blink {
+namespace protocol {
+
+using ErrorString = String;
+
+class PLATFORM_EXPORT Frontend {
+public:
+ Frontend(FrontendChannel*);
+ FrontendChannel* channel() { return m_frontendChannel; }
+
+{% for domain in api.domains %}
+
+ class PLATFORM_EXPORT {{domain.domain}} {
+ public:
+ static {{domain.domain}}* from(Frontend* frontend) { return &(frontend->m_{{domain.domain | lower}}) ;}
+ {{domain.domain}}(FrontendChannel* frontendChannel) : m_frontendChannel(frontendChannel) { }
+ {% for event in domain.events %}
+ {% if "handlers" in event and not ("renderer" in event["handlers"]) %}{% continue %}{% endif %}
+ void {{event.name}}(
+ {%- for parameter in event.parameters -%}
+ {%- if "optional" in parameter -%}
+ {{resolve_type(parameter).optional_pass_type}}
+ {%- if resolve_type(parameter).nullable -%}
+ {{parameter.name}} = nullptr
+ {%- else -%}
+ {{parameter.name}} = {{resolve_type(parameter).optional_type}}()
+ {%- endif %}
+ {%- else -%}
+ {{resolve_type(parameter).pass_type}} {{parameter.name}}
+ {%- endif -%}{%- if not loop.last -%}, {% endif -%}
+ {%- endfor -%}
+ );
+ {% endfor %}
+
+ void flush() { m_frontendChannel->flush(); }
+ private:
+ FrontendChannel* m_frontendChannel;
+ };
+{% endfor %}
+
+private:
+ FrontendChannel* m_frontendChannel;
+{% for domain in api.domains %}
+ {{domain.domain}} m_{{domain.domain | lower}};
+{% endfor %}
+};
+
+} // namespace protocol
+} // namespace blink
+
+#endif // !defined({{class_name}}_h)
diff --git a/TypeBuilder_cpp.template b/TypeBuilder_cpp.template
new file mode 100644
index 0000000..96db157
--- /dev/null
+++ b/TypeBuilder_cpp.template
@@ -0,0 +1,69 @@
+// This file is generated
+
+// Copyright (c) 2016 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.
+
+#include "platform/inspector_protocol/{{class_name}}.h"
+
+namespace blink {
+namespace protocol {
+
+template<>
+PassRefPtr<JSONValue> toValue(const String& param)
+{
+ return JSONString::create(param);
+}
+
+OptionalValue<String> optional(const String& value)
+{
+ return value.isNull() ? OptionalValue<String>() : OptionalValue<String>(value);
+}
+
+// ------------- Enum values from types.
+{% for domain in api.domains %}
+ {% for type in domain.types %}
+ {% if "enum" in type %}
+
+namespace {{domain.domain}} {
+namespace {{type.id}}Enum {
+ {% for literal in type.enum %}
+const char* {{ literal | dash_to_camelcase}} = "{{literal}}";
+ {% endfor %}
+} // {{type.id}}Enum
+} // {{domain.domain}}
+ {% endif %}
+ {% for property in type.properties %}
+ {% if "enum" in property %}
+namespace {{domain.domain}} {
+ {% for literal in property.enum %}
+const char* {{type.id}}::{{property.name | to_title_case}}Enum::{{ literal | dash_to_camelcase}} = "{{literal}}";
+ {% endfor %}
+} // {{domain.domain}}
+ {% endif %}
+ {% endfor %}
+ {% endfor %}
+{% endfor %}
+
+// ------------- Enum values from params.
+{% for domain in api.domains %}
+ {% for command in join_arrays(domain, ["commands", "events"]) %}
+ {% for param in join_arrays(command, ["parameters", "returns"]) %}
+ {% if "enum" in param %}
+
+namespace {{domain.domain}} {
+namespace {{command.name | to_title_case}} {
+namespace {{param.name | to_title_case}}Enum {
+ {% for literal in param.enum %}
+const char* {{ literal | to_title_case}} = "{{literal}}";
+ {% endfor %}
+} // {{param.name | to_title_case}}Enum
+} // {{command.name | to_title_case }}
+} // {{domain.domain}}
+ {% endif %}
+ {% endfor %}
+ {% endfor %}
+{% endfor %}
+
+} // namespace protocol
+} // namespace blink
diff --git a/TypeBuilder_h.template b/TypeBuilder_h.template
new file mode 100644
index 0000000..7374d9e
--- /dev/null
+++ b/TypeBuilder_h.template
@@ -0,0 +1,463 @@
+// This file is generated
+
+// Copyright (c) 2016 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.
+
+#ifndef {{class_name}}_h
+#define {{class_name}}_h
+
+#include "platform/JSONValues.h"
+#include "platform/PlatformExport.h"
+#include "wtf/Assertions.h"
+#include "wtf/PassOwnPtr.h"
+#include "wtf/PassRefPtr.h"
+#include "wtf/text/WTFString.h"
+
+namespace blink {
+namespace protocol {
+
+template<typename T>
+class OptionalValue {
+public:
+ OptionalValue() : m_hasValue(false) { }
+ OptionalValue(const T& value) : m_hasValue(true), m_value(value) { }
+
+ void operator=(T value)
+ {
+ m_value = value;
+ m_hasValue = true;
+ }
+
+ T get() const
+ {
+ ASSERT(m_hasValue);
+ return m_value;
+ }
+
+ T get(const T& defaultValue) const
+ {
+ return m_hasValue ? m_value : defaultValue;
+ }
+
+ bool hasValue() const
+ {
+ return m_hasValue;
+ }
+
+private:
+ bool m_hasValue;
+ T m_value;
+};
+
+template<typename T>
+OptionalValue<T> optional(const T* value)
+{
+ return value ? OptionalValue<T>(*value) : OptionalValue<T>();
+}
+
+PLATFORM_EXPORT OptionalValue<String> optional(const String& value);
+
+template<typename T>
+OptionalValue<T> optional(const T& value)
+{
+ return OptionalValue<T>(value);
+}
+
+template<typename T> class Array;
+
+template<typename T>
+bool hasValue(const protocol::OptionalValue<T>& t) { return t.hasValue(); }
+
+template<typename T>
+bool hasValue(T* value) { return !!value; }
+
+template<typename T>
+bool hasValue(const OwnPtr<T>& value) { return !!value; }
+
+template<typename T>
+bool hasValue(const PassOwnPtr<T>& value) { return !!value; }
+
+template<typename T>
+bool hasValue(const RefPtr<T>& value) { return !!value; }
+
+template<typename T>
+PassRefPtr<JSONValue> toValue(const T& param)
+{
+ return JSONBasicValue::create(param);
+}
+
+template<>
+PLATFORM_EXPORT PassRefPtr<JSONValue> toValue(const String& param);
+
+template<typename T>
+PassRefPtr<JSONValue> toValue(PassRefPtr<T> param)
+{
+ return param;
+}
+
+template<typename T>
+PassRefPtr<JSONValue> toValue(const PassOwnPtr<protocol::Array<T>> param)
+{
+ return param->asValue();
+}
+
+template<typename T>
+PassRefPtr<JSONValue> toValue(PassOwnPtr<T> param)
+{
+ return param->asValue();
+}
+
+template<typename T>
+struct FromValue
+{
+ static PassOwnPtr<T> convert(RefPtr<JSONValue> value)
+ {
+ if (!value)
+ return nullptr;
+ RefPtr<JSONObject> object;
+ bool success = value->asObject(&object);
+ ASSERT_UNUSED(success, success);
+ return T::runtimeCast(object.release());
+ }
+};
+
+template<>
+struct FromValue<bool>
+{
+ static bool convert(RefPtr<JSONValue> value)
+ {
+ bool result;
+ bool success = value->asBoolean(&result);
+ ASSERT_UNUSED(success, success);
+ return result;
+ }
+};
+
+template<>
+struct FromValue<int>
+{
+ static int convert(RefPtr<JSONValue> value)
+ {
+ int result;
+ bool success = value->asNumber(&result);
+ ASSERT_UNUSED(success, success);
+ return result;
+ }
+};
+
+template<>
+struct FromValue<double>
+{
+ static double convert(RefPtr<JSONValue> value)
+ {
+ double result;
+ bool success = value->asNumber(&result);
+ ASSERT_UNUSED(success, success);
+ return result;
+ }
+};
+
+template<>
+struct FromValue<String>
+{
+ static String convert(RefPtr<JSONValue> value)
+ {
+ String result;
+ bool success = value->asString(&result);
+ ASSERT_UNUSED(success, success);
+ return result;
+ }
+};
+
+template<typename T>
+struct FromValue<RefPtr<T>>
+{
+ static PassRefPtr<T> convert(RefPtr<T> value)
+ {
+ return value.release();
+ }
+};
+
+template<typename T>
+struct FromValue<protocol::Array<T>>
+{
+ static PassOwnPtr<protocol::Array<T>> convert(RefPtr<JSONValue> value)
+ {
+ RefPtr<JSONArray> array = value->asArray();
+ ASSERT_UNUSED(array, array);
+ return protocol::Array<T>::runtimeCast(array);
+ }
+};
+
+template<typename T>
+class ArrayBase {
+public:
+ static PassOwnPtr<Array<T>> create()
+ {
+ OwnPtr<Array<T>> result = adoptPtr(new Array<T>());
+ result->m_array = JSONArray::create();
+ return result.release();
+ }
+
+ static PassOwnPtr<Array<T>> runtimeCast(PassRefPtr<JSONArray> array)
+ {
+ if (!array)
+ return nullptr;
+ OwnPtr<Array<T>> result = adoptPtr(new Array<T>());
+ result->m_array = array;
+ return result.release();
+ }
+
+ void addItem(const T& value)
+ {
+ m_array->pushValue(toValue(value));
+ }
+
+ size_t length() { return m_array->length(); }
+
+ T get(size_t index) { return FromValue<T>::convert(m_array->get(index)); }
+ PassRefPtr<JSONArray> asValue() { return m_array; }
+
+private:
+ RefPtr<JSONArray> m_array;
+};
+
+template<> class Array<String> : public ArrayBase<String> {};
+template<> class Array<int> : public ArrayBase<int> {};
+template<> class Array<double> : public ArrayBase<double> {};
+template<> class Array<bool> : public ArrayBase<bool> {};
+template<typename T> class Array<RefPtr<T>> : public ArrayBase<RefPtr<T>> {};
+
+template<typename T>
+class Array {
+public:
+ static PassOwnPtr<Array<T>> create()
+ {
+ OwnPtr<Array<T>> result = adoptPtr(new Array<T>());
+ result->m_array = JSONArray::create();
+ return result.release();
+ }
+
+ static PassOwnPtr<Array<T>> runtimeCast(PassRefPtr<JSONArray> array)
+ {
+ if (!array)
+ return nullptr;
+ OwnPtr<Array<T>> result = adoptPtr(new Array<T>());
+ result->m_array = array;
+ return result.release();
+ }
+
+ void addItem(PassOwnPtr<T> value)
+ {
+ m_array->pushValue(toValue(value));
+ }
+
+ size_t length() { return m_array->length(); }
+
+ PassOwnPtr<T> get(size_t index) { return FromValue<T>::convert(m_array->get(index)); }
+ PassRefPtr<JSONArray> asValue() { return m_array; }
+
+private:
+ RefPtr<JSONArray> m_array;
+};
+
+{% for domain in api.domains %}
+
+// ------------- Forward declarations and typedefs.
+
+namespace {{domain.domain}} {
+ {% for type in domain.types %}
+ {% if type.type == "object" %}
+// {{type.description}}
+class {{type.id}};
+ {% elif type.type != "array" %}
+// {{type.description}}
+using {{type.id}} = {{resolve_type(type).type}};
+ {% endif %}
+ {% endfor %}
+} // {{domain.domain}}
+{% endfor %}
+
+// ------------- Enum values from types.
+{% for domain in api.domains %}
+ {% for type in domain.types %}
+ {% if "enum" in type %}
+
+namespace {{domain.domain}} {
+namespace {{type.id}}Enum {
+ {% for literal in type.enum %}
+PLATFORM_EXPORT extern const char* {{ literal | dash_to_camelcase}};
+ {% endfor %}
+} // {{type.id}}Enum
+} // {{domain.domain}}
+ {% endif %}
+ {% endfor %}
+{% endfor %}
+
+// ------------- Enum values from params.
+{% for domain in api.domains %}
+ {% for command in join_arrays(domain, ["commands", "events"]) %}
+ {% for param in join_arrays(command, ["parameters", "returns"]) %}
+ {% if "enum" in param %}
+
+namespace {{domain.domain}} {
+namespace {{command.name | to_title_case}} {
+namespace {{param.name | to_title_case}}Enum {
+ {% for literal in param.enum %}
+PLATFORM_EXPORT extern const char* {{ literal | dash_to_camelcase}};
+ {% endfor %}
+} // {{param.name | to_title_case}}Enum
+} // {{command.name | to_title_case }}
+} // {{domain.domain}}
+ {% endif %}
+ {% endfor %}
+ {% endfor %}
+{% endfor %}
+
+// ------------- Type and builder declarations.
+{% for domain in api.domains %}
+
+namespace {{domain.domain}} {
+ {% for type in domain.types %}
+ {% if type.type == "object" %}
+ {% set type_def = type_definition(domain.domain + "." + type.id)%}
+
+// {{type.description}}
+class PLATFORM_EXPORT {{type.id}} {
+public:
+ static PassOwnPtr<{{type.id}}> runtimeCast(PassRefPtr<JSONObject> object)
+ {
+ return adoptPtr(new {{type.id}}(object));
+ }
+
+ {{type.id}}() : m_object(JSONObject::create()) { }
+
+ ~{{type.id}}() { }
+ {% for property in type.properties %}
+
+ {% if "enum" in property %}
+ struct PLATFORM_EXPORT {{property.name | to_title_case}}Enum {
+ {% for literal in property.enum %}
+ static const char* {{ literal | dash_to_camelcase}};
+ {% endfor %}
+ }; // {{property.name | to_title_case}}Enum
+ {% endif %}
+
+ bool has{{property.name | to_title_case}}()
+ {
+ RefPtr<JSONValue> value = m_object->get("{{property.name}}");
+ {% if resolve_type(property).json_type %}
+ return value && value->type() == JSONValue::{{resolve_type(property).json_type}};
+ {% else %}
+ return !!value;
+ {% endif %}
+ }
+
+ {% if property.optional %}
+ {{resolve_type(property).return_type}} get{{property.name | to_title_case}}({{resolve_type(property).return_type}} defaultValue)
+ {
+ RefPtr<JSONValue> value = m_object->get("{{property.name}}");
+ return value ? FromValue<{{resolve_type(property).raw_type}}>::convert(value) : defaultValue;
+ }
+ {% else %}
+ {{resolve_type(property).return_type}} get{{property.name | to_title_case}}()
+ {
+ ASSERT(has{{property.name | to_title_case}}());
+ RefPtr<JSONValue> value = m_object->get("{{property.name}}");
+ return FromValue<{{resolve_type(property).raw_type}}>::convert(value);
+ }
+ {% endif %}
+
+ void set{{property.name | to_title_case}}({{resolve_type(property).pass_type}} value)
+ {
+ {% if property.optional and resolve_type(property).nullable %}
+ if (value)
+ m_object->setValue("{{property.name}}", toValue(value));
+ {% else %}
+ m_object->setValue("{{property.name}}", toValue(value));
+ {% endif %}
+ }
+ {% endfor %}
+
+ PassRefPtr<JSONObject> asValue() { return m_object; }
+
+ PassOwnPtr<{{type.id}}> clone() { return adoptPtr(new {{type.id}}(m_object)); }
+
+ template<int STATE>
+ class {{type.id}}Builder {
+ public:
+ enum {
+ NoFieldsSet = 0,
+ {% set count = 0 %}
+ {% for property in type.properties %}
+ {% if not(property.optional) %}
+ {% set count = count + 1 %}
+ {{property.name | to_title_case}}Set = 1 << {{count}},
+ {% endif %}
+ {% endfor %}
+ AllFieldsSet = (
+ {%- for property in type.properties %}
+ {% if not(property.optional) %}{{property.name | to_title_case}}Set | {%endif %}
+ {% endfor %}0)};
+
+ {% for property in type.properties %}
+
+ {% if property.optional %}
+ {{type.id}}Builder<STATE>& set{{property.name | to_title_case}}({{resolve_type(property).pass_type}} value)
+ {
+ {% if resolve_type(property).nullable%}
+ if (!value)
+ return *this;
+ {% endif %}
+ m_result->set{{property.name | to_title_case}}(value);
+ return *this;
+ }
+ {% else %}
+ {{type.id}}Builder<STATE | {{property.name | to_title_case}}Set>& set{{property.name | to_title_case}}({{resolve_type(property).pass_type}} value)
+ {
+ static_assert(!(STATE & {{property.name | to_title_case}}Set), "property {{property.name}} should not be set yet");
+ m_result->set{{property.name | to_title_case}}(value);
+ return castState<{{property.name | to_title_case}}Set>();
+ }
+ {% endif %}
+ {% endfor %}
+
+ PassOwnPtr<{{type.id}}> build()
+ {
+ static_assert(STATE == AllFieldsSet, "state should be AllFieldsSet");
+ return m_result.release();
+ }
+
+ private:
+ friend class {{type.id}};
+ {{type.id}}Builder() : m_result({{type_def.create_type}}) { }
+
+ template<int STEP> {{type.id}}Builder<STATE | STEP>& castState()
+ {
+ return *reinterpret_cast<{{type.id}}Builder<STATE | STEP>*>(this);
+ }
+
+ {{type_def.type}} m_result;
+ };
+
+ static {{type.id}}Builder<0> create()
+ {
+ return {{type.id}}Builder<0>();
+ }
+
+private:
+ explicit {{type.id}}(PassRefPtr<JSONObject> object) : m_object(object) { }
+ RefPtr<JSONObject> m_object;
+};
+
+ {% endif %}
+ {% endfor %}
+
+} // {{domain.domain}}
+{% endfor %}
+
+} // namespace protocol
+} // namespace blink
+
+#endif // !defined({{class_name}}_h)
diff --git a/protocol.gyp b/protocol.gyp
index c5b8a88..b411c86 100644
--- a/protocol.gyp
+++ b/protocol.gyp
@@ -5,6 +5,11 @@
{
'variables': {
'blink_platform_output_dir': '<(SHARED_INTERMEDIATE_DIR)/blink/platform',
+ 'jinja_module_files': [
+ # jinja2/__init__.py contains version string, so sufficient for package
+ '<(DEPTH)/third_party/jinja2/__init__.py',
+ '<(DEPTH)/third_party/markupsafe/__init__.py', # jinja2 dep
+ ],
},
'targets': [
@@ -19,12 +24,17 @@
{
'action_name': 'generateInspectorProtocolBackendSources',
'inputs': [
+ '<@(jinja_module_files)',
# The python script in action below.
'CodeGenerator.py',
- # The helper script imported by CodeGenerator.py.
- 'CodeGeneratorStrings.py',
- # Input file for the script.
+ # Input files for the script.
'../../devtools/protocol.json',
+ 'Dispatcher_h.template',
+ 'Dispatcher_cpp.template',
+ 'Frontend_h.template',
+ 'Frontend_cpp.template',
+ 'TypeBuilder_h.template',
+ 'TypeBuilder_cpp.template',
],
'outputs': [
'<(blink_platform_output_dir)/inspector_protocol/Dispatcher.cpp',
@@ -34,10 +44,6 @@
'<(blink_platform_output_dir)/inspector_protocol/TypeBuilder.cpp',
'<(blink_platform_output_dir)/inspector_protocol/TypeBuilder.h',
],
- 'variables': {
- 'generator_include_dirs': [
- ],
- },
'action': [
'python',
'CodeGenerator.py',