3 # Copyright (c) 2014 Apple Inc. All rights reserved.
4 # Copyright (c) 2014 University of Washington. All rights reserved.
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
9 # 1. Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer.
11 # 2. Redistributions in binary form must reproduce the above copyright
12 # notice, this list of conditions and the following disclaimer in the
13 # documentation and/or other materials provided with the distribution.
15 # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
16 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17 # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
19 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
25 # THE POSSIBILITY OF SUCH DAMAGE.
31 from generator
import ucfirst
32 from models
import PrimitiveType
, ObjectType
, ArrayType
, EnumType
, AliasedType
, Frameworks
34 log
= logging
.getLogger('global')
36 _PRIMITIVE_TO_CPP_NAME_MAP
= {
41 'object': 'Inspector::InspectorObject',
42 'array': 'Inspector::InspectorArray',
43 'any': 'Inspector::InspectorValue'
46 # This class contains extra static methods used for generation, but does
47 # not participate in any inheritance hierarchy. File generators should
48 # extend the generic "Generator" class instead.
51 # Miscellaneous text manipulation routines.
53 def cpp_getter_method_for_type(_type
):
54 if isinstance(_type
, ObjectType
):
56 if isinstance(_type
, ArrayType
):
58 if isinstance(_type
, PrimitiveType
):
59 if _type
.raw_name() is 'integer':
61 elif _type
.raw_name() is 'number':
63 elif _type
.raw_name() is 'any':
66 return 'get' + ucfirst(_type
.raw_name())
67 if isinstance(_type
, AliasedType
):
68 return CppGenerator
.cpp_getter_method_for_type(_type
.aliased_type
)
69 if isinstance(_type
, EnumType
):
70 return CppGenerator
.cpp_getter_method_for_type(_type
.primitive_type
)
73 def cpp_setter_method_for_type(_type
):
74 if isinstance(_type
, ObjectType
):
76 if isinstance(_type
, ArrayType
):
78 if isinstance(_type
, PrimitiveType
):
79 if _type
.raw_name() is 'integer':
81 elif _type
.raw_name() is 'number':
83 elif _type
.raw_name() is 'any':
86 return 'set' + ucfirst(_type
.raw_name())
87 if isinstance(_type
, AliasedType
):
88 return CppGenerator
.cpp_setter_method_for_type(_type
.aliased_type
)
89 if isinstance(_type
, EnumType
):
90 return CppGenerator
.cpp_setter_method_for_type(_type
.primitive_type
)
92 # Generate type representations for various situations.
94 def cpp_protocol_type_for_type(_type
):
95 if isinstance(_type
, ObjectType
) and len(_type
.members
) == 0:
96 return 'Inspector::InspectorObject'
97 if isinstance(_type
, ArrayType
):
98 if _type
.raw_name() is None: # Otherwise, fall through and use typedef'd name.
99 return 'Inspector::Protocol::Array<%s>' % CppGenerator
.cpp_protocol_type_for_type(_type
.element_type
)
100 if isinstance(_type
, (ObjectType
, AliasedType
, EnumType
, ArrayType
)):
101 return 'Inspector::Protocol::%s::%s' % (_type
.type_domain().domain_name
, _type
.raw_name())
102 if isinstance(_type
, PrimitiveType
):
103 return CppGenerator
.cpp_name_for_primitive_type(_type
)
106 def cpp_protocol_type_for_type_member(type_member
, object_declaration
):
107 if isinstance(type_member
.type, EnumType
) and type_member
.type.is_anonymous
:
108 return '::'.join([CppGenerator
.cpp_protocol_type_for_type(object_declaration
.type), ucfirst(type_member
.member_name
)])
110 return CppGenerator
.cpp_protocol_type_for_type(type_member
.type)
113 def cpp_type_for_unchecked_formal_in_parameter(parameter
):
114 _type
= parameter
.type
115 if isinstance(_type
, AliasedType
):
116 _type
= _type
.aliased_type
# Fall through to enum or primitive.
118 if isinstance(_type
, EnumType
):
119 _type
= _type
.primitive_type
# Fall through to primitive.
121 # This handles the 'any' type and objects with defined properties.
122 if isinstance(_type
, ObjectType
) or _type
.qualified_name() is 'object':
123 cpp_name
= 'Inspector::InspectorObject'
124 if parameter
.is_optional
:
125 return 'const %s*' % cpp_name
127 return 'const %s&' % cpp_name
128 if isinstance(_type
, ArrayType
):
129 cpp_name
= 'Inspector::InspectorArray'
130 if parameter
.is_optional
:
131 return 'const %s*' % cpp_name
133 return 'const %s&' % cpp_name
134 if isinstance(_type
, PrimitiveType
):
135 cpp_name
= CppGenerator
.cpp_name_for_primitive_type(_type
)
136 if parameter
.is_optional
:
137 return 'const %s*' % cpp_name
138 elif _type
.raw_name() in ['string']:
139 return 'const %s&' % cpp_name
143 return "unknown_unchecked_formal_in_parameter_type"
146 def cpp_type_for_checked_formal_event_parameter(parameter
):
147 return CppGenerator
.cpp_type_for_type_with_name(parameter
.type, parameter
.parameter_name
, parameter
.is_optional
)
150 def cpp_type_for_type_member(member
):
151 return CppGenerator
.cpp_type_for_type_with_name(member
.type, member
.member_name
, False)
154 def cpp_type_for_type_with_name(_type
, type_name
, is_optional
):
155 if isinstance(_type
, (ArrayType
, ObjectType
)):
156 return 'RefPtr<%s>' % CppGenerator
.cpp_protocol_type_for_type(_type
)
157 if isinstance(_type
, AliasedType
):
158 builder_type
= CppGenerator
.cpp_protocol_type_for_type(_type
)
160 return 'const %s* const' % builder_type
161 elif _type
.aliased_type
.qualified_name() in ['integer', 'number']:
162 return CppGenerator
.cpp_name_for_primitive_type(_type
.aliased_type
)
163 elif _type
.aliased_type
.qualified_name() in ['string']:
164 return 'const %s&' % builder_type
167 if isinstance(_type
, PrimitiveType
):
168 cpp_name
= CppGenerator
.cpp_name_for_primitive_type(_type
)
169 if _type
.qualified_name() in ['object']:
170 return 'RefPtr<Inspector::InspectorObject>'
171 elif _type
.qualified_name() in ['any']:
172 return 'RefPtr<Inspector::InspectorValue>'
174 return 'const %s* const' % cpp_name
175 elif _type
.qualified_name() in ['string']:
176 return 'const %s&' % cpp_name
179 if isinstance(_type
, EnumType
):
180 if _type
.is_anonymous
:
181 enum_type_name
= ucfirst(type_name
)
183 enum_type_name
= 'Inspector::Protocol::%s::%s' % (_type
.type_domain().domain_name
, _type
.raw_name())
186 return '%s*' % enum_type_name
188 return '%s' % enum_type_name
191 def cpp_type_for_formal_out_parameter(parameter
):
192 _type
= parameter
.type
194 if isinstance(_type
, AliasedType
):
195 _type
= _type
.aliased_type
# Fall through.
197 if isinstance(_type
, (ObjectType
, ArrayType
)):
198 return 'RefPtr<%s>&' % CppGenerator
.cpp_protocol_type_for_type(_type
)
199 if isinstance(_type
, PrimitiveType
):
200 cpp_name
= CppGenerator
.cpp_name_for_primitive_type(_type
)
201 if parameter
.is_optional
:
202 return "Inspector::Protocol::OptOutput<%s>*" % cpp_name
204 return '%s*' % cpp_name
205 if isinstance(_type
, EnumType
):
206 if _type
.is_anonymous
:
207 return '%sBackendDispatcherHandler::%s*' % (_type
.type_domain().domain_name
, ucfirst(parameter
.parameter_name
))
209 return 'Inspector::Protocol::%s::%s*' % (_type
.type_domain().domain_name
, _type
.raw_name())
211 raise ValueError("unknown formal out parameter type.")
213 # FIXME: this is only slightly different from out parameters; they could be unified.
215 def cpp_type_for_formal_async_parameter(parameter
):
216 _type
= parameter
.type
217 if isinstance(_type
, AliasedType
):
218 _type
= _type
.aliased_type
# Fall through.
220 if isinstance(_type
, EnumType
):
221 _type
= _type
.primitive_type
# Fall through.
223 if isinstance(_type
, (ObjectType
, ArrayType
)):
224 return 'RefPtr<%s>&&' % CppGenerator
.cpp_protocol_type_for_type(_type
)
225 if isinstance(_type
, PrimitiveType
):
226 cpp_name
= CppGenerator
.cpp_name_for_primitive_type(_type
)
227 if parameter
.is_optional
:
228 return "Inspector::Protocol::OptOutput<%s>*" % cpp_name
229 elif _type
.qualified_name() in ['integer', 'number']:
230 return CppGenerator
.cpp_name_for_primitive_type(_type
)
231 elif _type
.qualified_name() in ['string']:
232 return 'const %s&' % cpp_name
236 raise ValueError("Unknown formal async parameter type.")
238 # In-parameters don't use builder types, because they could be passed
239 # "open types" that are manually constructed out of InspectorObjects.
241 # FIXME: Only parameters that are actually open types should need non-builder parameter types.
243 def cpp_type_for_stack_in_parameter(parameter
):
244 _type
= parameter
.type
245 if isinstance(_type
, AliasedType
):
246 _type
= _type
.aliased_type
# Fall through.
248 if isinstance(_type
, EnumType
):
249 _type
= _type
.primitive_type
# Fall through.
251 if isinstance(_type
, ObjectType
):
252 return "RefPtr<Inspector::InspectorObject>"
253 if isinstance(_type
, ArrayType
):
254 return "RefPtr<Inspector::InspectorArray>"
255 if isinstance(_type
, PrimitiveType
):
256 cpp_name
= CppGenerator
.cpp_name_for_primitive_type(_type
)
257 if _type
.qualified_name() in ['any', 'object']:
258 return "RefPtr<%s>" % CppGenerator
.cpp_name_for_primitive_type(_type
)
259 elif parameter
.is_optional
and _type
.qualified_name() not in ['boolean', 'string', 'integer']:
260 return "Inspector::Protocol::OptOutput<%s>" % cpp_name
265 def cpp_type_for_stack_out_parameter(parameter
):
266 _type
= parameter
.type
267 if isinstance(_type
, (ArrayType
, ObjectType
)):
268 return 'RefPtr<%s>' % CppGenerator
.cpp_protocol_type_for_type(_type
)
269 if isinstance(_type
, AliasedType
):
270 builder_type
= CppGenerator
.cpp_protocol_type_for_type(_type
)
271 if parameter
.is_optional
:
272 return "Inspector::Protocol::OptOutput<%s>" % builder_type
273 return '%s' % builder_type
274 if isinstance(_type
, PrimitiveType
):
275 cpp_name
= CppGenerator
.cpp_name_for_primitive_type(_type
)
276 if parameter
.is_optional
:
277 return "Inspector::Protocol::OptOutput<%s>" % cpp_name
280 if isinstance(_type
, EnumType
):
281 if _type
.is_anonymous
:
282 return '%sBackendDispatcherHandler::%s' % (_type
.type_domain().domain_name
, ucfirst(parameter
.parameter_name
))
284 return 'Inspector::Protocol::%s::%s' % (_type
.type_domain().domain_name
, _type
.raw_name())
287 def cpp_assertion_method_for_type_member(type_member
, object_declaration
):
289 def assertion_method_for_type(_type
):
290 return 'BindingTraits<%s>::assertValueHasExpectedType' % CppGenerator
.cpp_protocol_type_for_type(_type
)
292 if isinstance(type_member
.type, AliasedType
):
293 return assertion_method_for_type(type_member
.type.aliased_type
)
294 if isinstance(type_member
.type, EnumType
) and type_member
.type.is_anonymous
:
295 return 'BindingTraits<%s>::assertValueHasExpectedType' % CppGenerator
.cpp_protocol_type_for_type_member(type_member
, object_declaration
)
297 return assertion_method_for_type(type_member
.type)
300 def cpp_name_for_primitive_type(_type
):
301 return _PRIMITIVE_TO_CPP_NAME_MAP
.get(_type
.raw_name())
303 # Decide whether certain helpers are necessary in a situation.
305 def should_use_wrapper_for_return_type(_type
):
306 return not isinstance(_type
, (ArrayType
, ObjectType
))
309 def should_use_references_for_type(_type
):
310 return isinstance(_type
, (ArrayType
, ObjectType
)) or (isinstance(_type
, (PrimitiveType
)) and _type
.qualified_name() in ["any", "object"])
313 def should_pass_by_copy_for_return_type(_type
):
314 return isinstance(_type
, (ArrayType
, ObjectType
)) or (isinstance(_type
, (PrimitiveType
)) and _type
.qualified_name() == "object")