--- /dev/null
+#!/usr/bin/env python
+#
+# Copyright (c) 2014 Apple Inc. All rights reserved.
+# Copyright (c) 2014 University of Washington. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. 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.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+# THE POSSIBILITY OF SUCH DAMAGE.
+
+import logging
+import os.path
+import re
+
+from generator import ucfirst
+from models import PrimitiveType, ObjectType, ArrayType, EnumType, AliasedType, Frameworks
+
+log = logging.getLogger('global')
+
+_PRIMITIVE_TO_CPP_NAME_MAP = {
+ 'boolean': 'bool',
+ 'integer': 'int',
+ 'number': 'double',
+ 'string': 'String',
+ 'object': 'Inspector::InspectorObject',
+ 'array': 'Inspector::InspectorArray',
+ 'any': 'Inspector::InspectorValue'
+}
+
+# This class contains extra static methods used for generation, but does
+# not participate in any inheritance hierarchy. File generators should
+# extend the generic "Generator" class instead.
+class CppGenerator:
+
+ # Miscellaneous text manipulation routines.
+ @staticmethod
+ def cpp_getter_method_for_type(_type):
+ if isinstance(_type, ObjectType):
+ return 'getObject'
+ if isinstance(_type, ArrayType):
+ return 'getArray'
+ if isinstance(_type, PrimitiveType):
+ if _type.raw_name() is 'integer':
+ return 'getInteger'
+ elif _type.raw_name() is 'number':
+ return 'getDouble'
+ elif _type.raw_name() is 'any':
+ return 'getValue'
+ else:
+ return 'get' + ucfirst(_type.raw_name())
+ if isinstance(_type, AliasedType):
+ return CppGenerator.cpp_getter_method_for_type(_type.aliased_type)
+ if isinstance(_type, EnumType):
+ return CppGenerator.cpp_getter_method_for_type(_type.primitive_type)
+
+ @staticmethod
+ def cpp_setter_method_for_type(_type):
+ if isinstance(_type, ObjectType):
+ return 'setObject'
+ if isinstance(_type, ArrayType):
+ return 'setArray'
+ if isinstance(_type, PrimitiveType):
+ if _type.raw_name() is 'integer':
+ return 'setInteger'
+ elif _type.raw_name() is 'number':
+ return 'setDouble'
+ elif _type.raw_name() is 'any':
+ return 'setValue'
+ else:
+ return 'set' + ucfirst(_type.raw_name())
+ if isinstance(_type, AliasedType):
+ return CppGenerator.cpp_setter_method_for_type(_type.aliased_type)
+ if isinstance(_type, EnumType):
+ return CppGenerator.cpp_setter_method_for_type(_type.primitive_type)
+
+ # Generate type representations for various situations.
+ @staticmethod
+ def cpp_protocol_type_for_type(_type):
+ if isinstance(_type, ObjectType) and len(_type.members) == 0:
+ return 'Inspector::InspectorObject'
+ if isinstance(_type, ArrayType):
+ if _type.raw_name() is None: # Otherwise, fall through and use typedef'd name.
+ return 'Inspector::Protocol::Array<%s>' % CppGenerator.cpp_protocol_type_for_type(_type.element_type)
+ if isinstance(_type, (ObjectType, AliasedType, EnumType, ArrayType)):
+ return 'Inspector::Protocol::%s::%s' % (_type.type_domain().domain_name, _type.raw_name())
+ if isinstance(_type, PrimitiveType):
+ return CppGenerator.cpp_name_for_primitive_type(_type)
+
+ @staticmethod
+ def cpp_protocol_type_for_type_member(type_member, object_declaration):
+ if isinstance(type_member.type, EnumType) and type_member.type.is_anonymous:
+ return '::'.join([CppGenerator.cpp_protocol_type_for_type(object_declaration.type), ucfirst(type_member.member_name)])
+ else:
+ return CppGenerator.cpp_protocol_type_for_type(type_member.type)
+
+ @staticmethod
+ def cpp_type_for_unchecked_formal_in_parameter(parameter):
+ _type = parameter.type
+ if isinstance(_type, AliasedType):
+ _type = _type.aliased_type # Fall through to enum or primitive.
+
+ if isinstance(_type, EnumType):
+ _type = _type.primitive_type # Fall through to primitive.
+
+ # This handles the 'any' type and objects with defined properties.
+ if isinstance(_type, ObjectType) or _type.qualified_name() is 'object':
+ cpp_name = 'Inspector::InspectorObject'
+ if parameter.is_optional:
+ return 'const %s*' % cpp_name
+ else:
+ return 'const %s&' % cpp_name
+ if isinstance(_type, ArrayType):
+ cpp_name = 'Inspector::InspectorArray'
+ if parameter.is_optional:
+ return 'const %s*' % cpp_name
+ else:
+ return 'const %s&' % cpp_name
+ if isinstance(_type, PrimitiveType):
+ cpp_name = CppGenerator.cpp_name_for_primitive_type(_type)
+ if parameter.is_optional:
+ return 'const %s*' % cpp_name
+ elif _type.raw_name() in ['string']:
+ return 'const %s&' % cpp_name
+ else:
+ return cpp_name
+
+ return "unknown_unchecked_formal_in_parameter_type"
+
+ @staticmethod
+ def cpp_type_for_checked_formal_event_parameter(parameter):
+ return CppGenerator.cpp_type_for_type_with_name(parameter.type, parameter.parameter_name, parameter.is_optional)
+
+ @staticmethod
+ def cpp_type_for_type_member(member):
+ return CppGenerator.cpp_type_for_type_with_name(member.type, member.member_name, False)
+
+ @staticmethod
+ def cpp_type_for_type_with_name(_type, type_name, is_optional):
+ if isinstance(_type, (ArrayType, ObjectType)):
+ return 'RefPtr<%s>' % CppGenerator.cpp_protocol_type_for_type(_type)
+ if isinstance(_type, AliasedType):
+ builder_type = CppGenerator.cpp_protocol_type_for_type(_type)
+ if is_optional:
+ return 'const %s* const' % builder_type
+ elif _type.aliased_type.qualified_name() in ['integer', 'number']:
+ return CppGenerator.cpp_name_for_primitive_type(_type.aliased_type)
+ elif _type.aliased_type.qualified_name() in ['string']:
+ return 'const %s&' % builder_type
+ else:
+ return builder_type
+ if isinstance(_type, PrimitiveType):
+ cpp_name = CppGenerator.cpp_name_for_primitive_type(_type)
+ if _type.qualified_name() in ['object']:
+ return 'RefPtr<Inspector::InspectorObject>'
+ elif _type.qualified_name() in ['any']:
+ return 'RefPtr<Inspector::InspectorValue>'
+ elif is_optional:
+ return 'const %s* const' % cpp_name
+ elif _type.qualified_name() in ['string']:
+ return 'const %s&' % cpp_name
+ else:
+ return cpp_name
+ if isinstance(_type, EnumType):
+ if _type.is_anonymous:
+ enum_type_name = ucfirst(type_name)
+ else:
+ enum_type_name = 'Inspector::Protocol::%s::%s' % (_type.type_domain().domain_name, _type.raw_name())
+
+ if is_optional:
+ return '%s*' % enum_type_name
+ else:
+ return '%s' % enum_type_name
+
+ @staticmethod
+ def cpp_type_for_formal_out_parameter(parameter):
+ _type = parameter.type
+
+ if isinstance(_type, AliasedType):
+ _type = _type.aliased_type # Fall through.
+
+ if isinstance(_type, (ObjectType, ArrayType)):
+ return 'RefPtr<%s>&' % CppGenerator.cpp_protocol_type_for_type(_type)
+ if isinstance(_type, PrimitiveType):
+ cpp_name = CppGenerator.cpp_name_for_primitive_type(_type)
+ if parameter.is_optional:
+ return "Inspector::Protocol::OptOutput<%s>*" % cpp_name
+ else:
+ return '%s*' % cpp_name
+ if isinstance(_type, EnumType):
+ if _type.is_anonymous:
+ return '%sBackendDispatcherHandler::%s*' % (_type.type_domain().domain_name, ucfirst(parameter.parameter_name))
+ else:
+ return 'Inspector::Protocol::%s::%s*' % (_type.type_domain().domain_name, _type.raw_name())
+
+ raise ValueError("unknown formal out parameter type.")
+
+ # FIXME: this is only slightly different from out parameters; they could be unified.
+ @staticmethod
+ def cpp_type_for_formal_async_parameter(parameter):
+ _type = parameter.type
+ if isinstance(_type, AliasedType):
+ _type = _type.aliased_type # Fall through.
+
+ if isinstance(_type, EnumType):
+ _type = _type.primitive_type # Fall through.
+
+ if isinstance(_type, (ObjectType, ArrayType)):
+ return 'RefPtr<%s>&&' % CppGenerator.cpp_protocol_type_for_type(_type)
+ if isinstance(_type, PrimitiveType):
+ cpp_name = CppGenerator.cpp_name_for_primitive_type(_type)
+ if parameter.is_optional:
+ return "Inspector::Protocol::OptOutput<%s>*" % cpp_name
+ elif _type.qualified_name() in ['integer', 'number']:
+ return CppGenerator.cpp_name_for_primitive_type(_type)
+ elif _type.qualified_name() in ['string']:
+ return 'const %s&' % cpp_name
+ else:
+ return cpp_name
+
+ raise ValueError("Unknown formal async parameter type.")
+
+ # In-parameters don't use builder types, because they could be passed
+ # "open types" that are manually constructed out of InspectorObjects.
+
+ # FIXME: Only parameters that are actually open types should need non-builder parameter types.
+ @staticmethod
+ def cpp_type_for_stack_in_parameter(parameter):
+ _type = parameter.type
+ if isinstance(_type, AliasedType):
+ _type = _type.aliased_type # Fall through.
+
+ if isinstance(_type, EnumType):
+ _type = _type.primitive_type # Fall through.
+
+ if isinstance(_type, ObjectType):
+ return "RefPtr<Inspector::InspectorObject>"
+ if isinstance(_type, ArrayType):
+ return "RefPtr<Inspector::InspectorArray>"
+ if isinstance(_type, PrimitiveType):
+ cpp_name = CppGenerator.cpp_name_for_primitive_type(_type)
+ if _type.qualified_name() in ['any', 'object']:
+ return "RefPtr<%s>" % CppGenerator.cpp_name_for_primitive_type(_type)
+ elif parameter.is_optional and _type.qualified_name() not in ['boolean', 'string', 'integer']:
+ return "Inspector::Protocol::OptOutput<%s>" % cpp_name
+ else:
+ return cpp_name
+
+ @staticmethod
+ def cpp_type_for_stack_out_parameter(parameter):
+ _type = parameter.type
+ if isinstance(_type, (ArrayType, ObjectType)):
+ return 'RefPtr<%s>' % CppGenerator.cpp_protocol_type_for_type(_type)
+ if isinstance(_type, AliasedType):
+ builder_type = CppGenerator.cpp_protocol_type_for_type(_type)
+ if parameter.is_optional:
+ return "Inspector::Protocol::OptOutput<%s>" % builder_type
+ return '%s' % builder_type
+ if isinstance(_type, PrimitiveType):
+ cpp_name = CppGenerator.cpp_name_for_primitive_type(_type)
+ if parameter.is_optional:
+ return "Inspector::Protocol::OptOutput<%s>" % cpp_name
+ else:
+ return cpp_name
+ if isinstance(_type, EnumType):
+ if _type.is_anonymous:
+ return '%sBackendDispatcherHandler::%s' % (_type.type_domain().domain_name, ucfirst(parameter.parameter_name))
+ else:
+ return 'Inspector::Protocol::%s::%s' % (_type.type_domain().domain_name, _type.raw_name())
+
+ @staticmethod
+ def cpp_assertion_method_for_type_member(type_member, object_declaration):
+
+ def assertion_method_for_type(_type):
+ return 'BindingTraits<%s>::assertValueHasExpectedType' % CppGenerator.cpp_protocol_type_for_type(_type)
+
+ if isinstance(type_member.type, AliasedType):
+ return assertion_method_for_type(type_member.type.aliased_type)
+ if isinstance(type_member.type, EnumType) and type_member.type.is_anonymous:
+ return 'BindingTraits<%s>::assertValueHasExpectedType' % CppGenerator.cpp_protocol_type_for_type_member(type_member, object_declaration)
+
+ return assertion_method_for_type(type_member.type)
+
+ @staticmethod
+ def cpp_name_for_primitive_type(_type):
+ return _PRIMITIVE_TO_CPP_NAME_MAP.get(_type.raw_name())
+
+ # Decide whether certain helpers are necessary in a situation.
+ @staticmethod
+ def should_use_wrapper_for_return_type(_type):
+ return not isinstance(_type, (ArrayType, ObjectType))
+
+ @staticmethod
+ def should_use_references_for_type(_type):
+ return isinstance(_type, (ArrayType, ObjectType)) or (isinstance(_type, (PrimitiveType)) and _type.qualified_name() in ["any", "object"])
+
+ @staticmethod
+ def should_pass_by_copy_for_return_type(_type):
+ return isinstance(_type, (ArrayType, ObjectType)) or (isinstance(_type, (PrimitiveType)) and _type.qualified_name() == "object")