OLD | NEW |
1 # Copyright 2013 The Chromium Authors. All rights reserved. | 1 # Copyright 2013 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """Generates C++ source files from a mojom.Module.""" | 5 """Generates C++ source files from a mojom.Module.""" |
6 | 6 |
7 import mojom.generate.generator as generator | 7 import mojom.generate.generator as generator |
8 import mojom.generate.module as mojom | 8 import mojom.generate.module as mojom |
9 import mojom.generate.pack as pack | 9 import mojom.generate.pack as pack |
10 from mojom.generate.template_expander import UseJinja | 10 from mojom.generate.template_expander import UseJinja |
(...skipping 14 matching lines...) Expand all Loading... |
25 } | 25 } |
26 | 26 |
27 _kind_to_cpp_literal_suffix = { | 27 _kind_to_cpp_literal_suffix = { |
28 mojom.UINT8: "U", | 28 mojom.UINT8: "U", |
29 mojom.UINT16: "U", | 29 mojom.UINT16: "U", |
30 mojom.UINT32: "U", | 30 mojom.UINT32: "U", |
31 mojom.FLOAT: "f", | 31 mojom.FLOAT: "f", |
32 mojom.UINT64: "ULL", | 32 mojom.UINT64: "ULL", |
33 } | 33 } |
34 | 34 |
35 # TODO(rockot): Get rid of these globals. This requires some refactoring of the | |
36 # generator library code so that filters can use the generator as context. | |
37 _current_typemap = {} | |
38 _for_blink = False | |
39 # TODO(rockot, yzshen): The variant handling is kind of a hack currently. Make | |
40 # it right. | |
41 _variant = None | |
42 _export_attribute = None | |
43 | |
44 | 35 |
45 class _NameFormatter(object): | 36 class _NameFormatter(object): |
46 """A formatter for the names of kinds or values.""" | 37 """A formatter for the names of kinds or values.""" |
47 | 38 |
48 def __init__(self, token, variant): | 39 def __init__(self, token, variant): |
49 self._token = token | 40 self._token = token |
50 self._variant = variant | 41 self._variant = variant |
51 | 42 |
52 def Format(self, separator, prefixed=False, internal=False, | 43 def Format(self, separator, prefixed=False, internal=False, |
53 include_variant=False, add_same_module_namespaces=False, | 44 include_variant=False, add_same_module_namespaces=False, |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
123 return add_same_module_namespaces or self._token.imported_from | 114 return add_same_module_namespaces or self._token.imported_from |
124 | 115 |
125 def _GetNamespace(self): | 116 def _GetNamespace(self): |
126 if self._token.imported_from: | 117 if self._token.imported_from: |
127 return NamespaceToArray(self._token.imported_from["namespace"]) | 118 return NamespaceToArray(self._token.imported_from["namespace"]) |
128 elif hasattr(self._token, "module"): | 119 elif hasattr(self._token, "module"): |
129 return NamespaceToArray(self._token.module.namespace) | 120 return NamespaceToArray(self._token.module.namespace) |
130 return [] | 121 return [] |
131 | 122 |
132 | 123 |
133 def ConstantValue(constant): | |
134 return ExpressionToText(constant.value, kind=constant.kind) | |
135 | |
136 # TODO(yzshen): Revisit the default value feature. It was designed prior to | |
137 # custom type mapping. | |
138 def DefaultValue(field): | |
139 if field.default: | |
140 if mojom.IsStructKind(field.kind): | |
141 assert field.default == "default" | |
142 if not IsTypemappedKind(field.kind): | |
143 return "%s::New()" % GetNameForKind(field.kind) | |
144 return ExpressionToText(field.default, kind=field.kind) | |
145 return "" | |
146 | |
147 def NamespaceToArray(namespace): | 124 def NamespaceToArray(namespace): |
148 return namespace.split(".") if namespace else [] | 125 return namespace.split(".") if namespace else [] |
149 | 126 |
150 def GetNameForKind(kind, internal=False, flatten_nested_kind=False, | |
151 add_same_module_namespaces=False): | |
152 return _NameFormatter(kind, _variant).FormatForCpp( | |
153 internal=internal, flatten_nested_kind=flatten_nested_kind, | |
154 add_same_module_namespaces=add_same_module_namespaces) | |
155 | |
156 def GetQualifiedNameForKind(kind, internal=False, flatten_nested_kind=False, | |
157 include_variant=True): | |
158 return _NameFormatter( | |
159 kind, _variant if include_variant else None).FormatForCpp( | |
160 internal=internal, add_same_module_namespaces=True, | |
161 flatten_nested_kind=flatten_nested_kind) | |
162 | |
163 | 127 |
164 def GetWtfHashFnNameForEnum(enum): | 128 def GetWtfHashFnNameForEnum(enum): |
165 return _NameFormatter( | 129 return _NameFormatter( |
166 enum, None).Format("_", internal=True, add_same_module_namespaces=True, | 130 enum, None).Format("_", internal=True, add_same_module_namespaces=True, |
167 flatten_nested_kind=True) + "HashFn" | 131 flatten_nested_kind=True) + "HashFn" |
168 | 132 |
169 | 133 |
170 def GetFullMojomNameForKind(kind): | |
171 return _NameFormatter(kind, _variant).FormatForMojom() | |
172 | |
173 def IsTypemappedKind(kind): | |
174 return hasattr(kind, "name") and \ | |
175 GetFullMojomNameForKind(kind) in _current_typemap | |
176 | |
177 def IsNativeOnlyKind(kind): | 134 def IsNativeOnlyKind(kind): |
178 return (mojom.IsStructKind(kind) or mojom.IsEnumKind(kind)) and \ | 135 return (mojom.IsStructKind(kind) or mojom.IsEnumKind(kind)) and \ |
179 kind.native_only | 136 kind.native_only |
180 | 137 |
181 | 138 |
182 def IsHashableKind(kind): | |
183 """Check if the kind can be hashed. | |
184 | |
185 Args: | |
186 kind: {Kind} The kind to check. | |
187 | |
188 Returns: | |
189 {bool} True if a value of this kind can be hashed. | |
190 """ | |
191 checked = set() | |
192 def Check(kind): | |
193 if kind.spec in checked: | |
194 return True | |
195 checked.add(kind.spec) | |
196 if mojom.IsNullableKind(kind): | |
197 return False | |
198 elif mojom.IsStructKind(kind): | |
199 if (IsTypemappedKind(kind) and | |
200 not _current_typemap[GetFullMojomNameForKind(kind)]["hashable"]): | |
201 return False | |
202 return all(Check(field.kind) for field in kind.fields) | |
203 elif mojom.IsEnumKind(kind): | |
204 return not IsTypemappedKind(kind) or _current_typemap[ | |
205 GetFullMojomNameForKind(kind)]["hashable"] | |
206 elif mojom.IsUnionKind(kind): | |
207 return all(Check(field.kind) for field in kind.fields) | |
208 elif mojom.IsAnyHandleKind(kind): | |
209 return False | |
210 elif mojom.IsAnyInterfaceKind(kind): | |
211 return False | |
212 # TODO(tibell): Arrays and maps could be made hashable. We just don't have a | |
213 # use case yet. | |
214 elif mojom.IsArrayKind(kind): | |
215 return False | |
216 elif mojom.IsMapKind(kind): | |
217 return False | |
218 else: | |
219 return True | |
220 return Check(kind) | |
221 | |
222 | |
223 def AllEnumValues(enum): | 139 def AllEnumValues(enum): |
224 """Return all enum values associated with an enum. | 140 """Return all enum values associated with an enum. |
225 | 141 |
226 Args: | 142 Args: |
227 enum: {mojom.Enum} The enum type. | 143 enum: {mojom.Enum} The enum type. |
228 | 144 |
229 Returns: | 145 Returns: |
230 {Set[int]} The values. | 146 {Set[int]} The values. |
231 """ | 147 """ |
232 return set(field.numeric_value for field in enum.fields) | 148 return set(field.numeric_value for field in enum.fields) |
233 | 149 |
234 | 150 |
235 def GetNativeTypeName(typemapped_kind): | |
236 return _current_typemap[GetFullMojomNameForKind(typemapped_kind)]["typename"] | |
237 | |
238 def GetCppPodType(kind): | 151 def GetCppPodType(kind): |
239 return _kind_to_cpp_type[kind] | 152 return _kind_to_cpp_type[kind] |
240 | 153 |
241 def FormatConstantDeclaration(constant, nested=False): | |
242 if mojom.IsStringKind(constant.kind): | |
243 if nested: | |
244 return "const char %s[]" % constant.name | |
245 return "%sextern const char %s[]" % \ | |
246 ((_export_attribute + " ") if _export_attribute else "", constant.name) | |
247 return "constexpr %s %s = %s" % (GetCppPodType(constant.kind), constant.name, | |
248 ConstantValue(constant)) | |
249 | |
250 def GetCppWrapperType(kind, add_same_module_namespaces=False): | |
251 def _AddOptional(type_name): | |
252 pattern = "WTF::Optional<%s>" if _for_blink else "base::Optional<%s>" | |
253 return pattern % type_name | |
254 | |
255 if IsTypemappedKind(kind): | |
256 type_name = GetNativeTypeName(kind) | |
257 if (mojom.IsNullableKind(kind) and | |
258 not _current_typemap[GetFullMojomNameForKind(kind)][ | |
259 "nullable_is_same_type"]): | |
260 type_name = _AddOptional(type_name) | |
261 return type_name | |
262 if mojom.IsEnumKind(kind): | |
263 return GetNameForKind( | |
264 kind, add_same_module_namespaces=add_same_module_namespaces) | |
265 if mojom.IsStructKind(kind) or mojom.IsUnionKind(kind): | |
266 return "%sPtr" % GetNameForKind( | |
267 kind, add_same_module_namespaces=add_same_module_namespaces) | |
268 if mojom.IsArrayKind(kind): | |
269 pattern = "WTF::Vector<%s>" if _for_blink else "std::vector<%s>" | |
270 if mojom.IsNullableKind(kind): | |
271 pattern = _AddOptional(pattern) | |
272 return pattern % GetCppWrapperType( | |
273 kind.kind, add_same_module_namespaces=add_same_module_namespaces) | |
274 if mojom.IsMapKind(kind): | |
275 pattern = ("WTF::HashMap<%s, %s>" if _for_blink else | |
276 "std::unordered_map<%s, %s>") | |
277 if mojom.IsNullableKind(kind): | |
278 pattern = _AddOptional(pattern) | |
279 return pattern % ( | |
280 GetCppWrapperType( | |
281 kind.key_kind, | |
282 add_same_module_namespaces=add_same_module_namespaces), | |
283 GetCppWrapperType( | |
284 kind.value_kind, | |
285 add_same_module_namespaces=add_same_module_namespaces)) | |
286 if mojom.IsInterfaceKind(kind): | |
287 return "%sPtr" % GetNameForKind( | |
288 kind, add_same_module_namespaces=add_same_module_namespaces) | |
289 if mojom.IsInterfaceRequestKind(kind): | |
290 return "%sRequest" % GetNameForKind( | |
291 kind.kind, add_same_module_namespaces=add_same_module_namespaces) | |
292 if mojom.IsAssociatedInterfaceKind(kind): | |
293 return "%sAssociatedPtrInfo" % GetNameForKind( | |
294 kind.kind, add_same_module_namespaces=add_same_module_namespaces) | |
295 if mojom.IsAssociatedInterfaceRequestKind(kind): | |
296 return "%sAssociatedRequest" % GetNameForKind( | |
297 kind.kind, add_same_module_namespaces=add_same_module_namespaces) | |
298 if mojom.IsStringKind(kind): | |
299 if _for_blink: | |
300 return "WTF::String" | |
301 type_name = "std::string" | |
302 return _AddOptional(type_name) if mojom.IsNullableKind(kind) else type_name | |
303 if mojom.IsGenericHandleKind(kind): | |
304 return "mojo::ScopedHandle" | |
305 if mojom.IsDataPipeConsumerKind(kind): | |
306 return "mojo::ScopedDataPipeConsumerHandle" | |
307 if mojom.IsDataPipeProducerKind(kind): | |
308 return "mojo::ScopedDataPipeProducerHandle" | |
309 if mojom.IsMessagePipeKind(kind): | |
310 return "mojo::ScopedMessagePipeHandle" | |
311 if mojom.IsSharedBufferKind(kind): | |
312 return "mojo::ScopedSharedBufferHandle" | |
313 if not kind in _kind_to_cpp_type: | |
314 raise Exception("Unrecognized kind %s" % kind.spec) | |
315 return _kind_to_cpp_type[kind] | |
316 | |
317 def IsMoveOnlyKind(kind): | |
318 if IsTypemappedKind(kind): | |
319 if mojom.IsEnumKind(kind): | |
320 return False | |
321 return _current_typemap[GetFullMojomNameForKind(kind)]["move_only"] | |
322 if mojom.IsStructKind(kind) or mojom.IsUnionKind(kind): | |
323 return True | |
324 if mojom.IsArrayKind(kind): | |
325 return IsMoveOnlyKind(kind.kind) | |
326 if mojom.IsMapKind(kind): | |
327 return IsMoveOnlyKind(kind.value_kind) | |
328 if mojom.IsAnyHandleOrInterfaceKind(kind): | |
329 return True | |
330 return False | |
331 | |
332 def IsCopyablePassByValue(kind): | |
333 if not IsTypemappedKind(kind): | |
334 return False | |
335 return _current_typemap[GetFullMojomNameForKind(kind)][ | |
336 "copyable_pass_by_value"] | |
337 | |
338 def ShouldPassParamByValue(kind): | |
339 return ((not mojom.IsReferenceKind(kind)) or IsMoveOnlyKind(kind) or | |
340 IsCopyablePassByValue(kind)) | |
341 | |
342 def GetCppWrapperParamType(kind): | |
343 cpp_wrapper_type = GetCppWrapperType(kind) | |
344 return (cpp_wrapper_type if ShouldPassParamByValue(kind) | |
345 else "const %s&" % cpp_wrapper_type) | |
346 | |
347 def GetCppFieldType(kind): | |
348 if mojom.IsStructKind(kind): | |
349 return ("mojo::internal::Pointer<%s>" % | |
350 GetNameForKind(kind, internal=True)) | |
351 if mojom.IsUnionKind(kind): | |
352 return "%s" % GetNameForKind(kind, internal=True) | |
353 if mojom.IsArrayKind(kind): | |
354 return ("mojo::internal::Pointer<mojo::internal::Array_Data<%s>>" % | |
355 GetCppFieldType(kind.kind)) | |
356 if mojom.IsMapKind(kind): | |
357 return ("mojo::internal::Pointer<mojo::internal::Map_Data<%s, %s>>" % | |
358 (GetCppFieldType(kind.key_kind), GetCppFieldType(kind.value_kind))) | |
359 if mojom.IsInterfaceKind(kind): | |
360 return "mojo::internal::Interface_Data" | |
361 if mojom.IsInterfaceRequestKind(kind): | |
362 return "mojo::internal::Handle_Data" | |
363 if mojom.IsAssociatedInterfaceKind(kind): | |
364 return "mojo::internal::AssociatedInterface_Data" | |
365 if mojom.IsAssociatedInterfaceRequestKind(kind): | |
366 return "mojo::internal::AssociatedEndpointHandle_Data" | |
367 if mojom.IsEnumKind(kind): | |
368 return "int32_t" | |
369 if mojom.IsStringKind(kind): | |
370 return "mojo::internal::Pointer<mojo::internal::String_Data>" | |
371 if mojom.IsAnyHandleKind(kind): | |
372 return "mojo::internal::Handle_Data" | |
373 return _kind_to_cpp_type[kind] | |
374 | |
375 def GetCppUnionFieldType(kind): | |
376 if mojom.IsUnionKind(kind): | |
377 return ("mojo::internal::Pointer<%s>" % GetNameForKind(kind, internal=True)) | |
378 return GetCppFieldType(kind) | |
379 | |
380 def GetUnionGetterReturnType(kind): | |
381 if mojom.IsReferenceKind(kind): | |
382 return "%s&" % GetCppWrapperType(kind) | |
383 return GetCppWrapperType(kind) | |
384 | |
385 def GetUnionTraitGetterReturnType(kind): | |
386 """Get field type used in UnionTraits template specialization. | |
387 | |
388 The type may be qualified as UnionTraits specializations live outside the | |
389 namespace where e.g. structs are defined. | |
390 | |
391 Args: | |
392 kind: {Kind} The type of the field. | |
393 | |
394 Returns: | |
395 {str} The C++ type to use for the field. | |
396 """ | |
397 if mojom.IsReferenceKind(kind): | |
398 return "%s&" % GetCppWrapperType(kind, add_same_module_namespaces=True) | |
399 return GetCppWrapperType(kind, add_same_module_namespaces=True) | |
400 | 154 |
401 def GetCppDataViewType(kind, qualified=False): | 155 def GetCppDataViewType(kind, qualified=False): |
402 def _GetName(input_kind): | 156 def _GetName(input_kind): |
403 return _NameFormatter(input_kind, None).FormatForCpp( | 157 return _NameFormatter(input_kind, None).FormatForCpp( |
404 add_same_module_namespaces=qualified, flatten_nested_kind=True) | 158 add_same_module_namespaces=qualified, flatten_nested_kind=True) |
405 | 159 |
406 if mojom.IsEnumKind(kind): | 160 if mojom.IsEnumKind(kind): |
407 return _GetName(kind) | 161 return _GetName(kind) |
408 if mojom.IsStructKind(kind) or mojom.IsUnionKind(kind): | 162 if mojom.IsStructKind(kind) or mojom.IsUnionKind(kind): |
409 return "%sDataView" % _GetName(kind) | 163 return "%sDataView" % _GetName(kind) |
(...skipping 18 matching lines...) Expand all Loading... |
428 if mojom.IsDataPipeConsumerKind(kind): | 182 if mojom.IsDataPipeConsumerKind(kind): |
429 return "mojo::ScopedDataPipeConsumerHandle" | 183 return "mojo::ScopedDataPipeConsumerHandle" |
430 if mojom.IsDataPipeProducerKind(kind): | 184 if mojom.IsDataPipeProducerKind(kind): |
431 return "mojo::ScopedDataPipeProducerHandle" | 185 return "mojo::ScopedDataPipeProducerHandle" |
432 if mojom.IsMessagePipeKind(kind): | 186 if mojom.IsMessagePipeKind(kind): |
433 return "mojo::ScopedMessagePipeHandle" | 187 return "mojo::ScopedMessagePipeHandle" |
434 if mojom.IsSharedBufferKind(kind): | 188 if mojom.IsSharedBufferKind(kind): |
435 return "mojo::ScopedSharedBufferHandle" | 189 return "mojo::ScopedSharedBufferHandle" |
436 return _kind_to_cpp_type[kind] | 190 return _kind_to_cpp_type[kind] |
437 | 191 |
| 192 |
438 def GetUnmappedTypeForSerializer(kind): | 193 def GetUnmappedTypeForSerializer(kind): |
439 return GetCppDataViewType(kind, qualified=True) | 194 return GetCppDataViewType(kind, qualified=True) |
440 | 195 |
441 def TranslateConstants(token, kind): | |
442 if isinstance(token, mojom.NamedValue): | |
443 return GetNameForKind(token, flatten_nested_kind=True) | |
444 | |
445 if isinstance(token, mojom.BuiltinValue): | |
446 if token.value == "double.INFINITY": | |
447 return "std::numeric_limits<double>::infinity()" | |
448 if token.value == "float.INFINITY": | |
449 return "std::numeric_limits<float>::infinity()" | |
450 if token.value == "double.NEGATIVE_INFINITY": | |
451 return "-std::numeric_limits<double>::infinity()" | |
452 if token.value == "float.NEGATIVE_INFINITY": | |
453 return "-std::numeric_limits<float>::infinity()" | |
454 if token.value == "double.NAN": | |
455 return "std::numeric_limits<double>::quiet_NaN()" | |
456 if token.value == "float.NAN": | |
457 return "std::numeric_limits<float>::quiet_NaN()" | |
458 | |
459 if (kind is not None and mojom.IsFloatKind(kind)): | |
460 return token if token.isdigit() else token + "f"; | |
461 | |
462 # Per C++11, 2.14.2, the type of an integer literal is the first of the | |
463 # corresponding list in Table 6 in which its value can be represented. In this | |
464 # case, the list for decimal constants with no suffix is: | |
465 # int, long int, long long int | |
466 # The standard considers a program ill-formed if it contains an integer | |
467 # literal that cannot be represented by any of the allowed types. | |
468 # | |
469 # As it turns out, MSVC doesn't bother trying to fall back to long long int, | |
470 # so the integral constant -2147483648 causes it grief: it decides to | |
471 # represent 2147483648 as an unsigned integer, and then warns that the unary | |
472 # minus operator doesn't make sense on unsigned types. Doh! | |
473 if kind == mojom.INT32 and token == "-2147483648": | |
474 return "(-%d - 1) /* %s */" % ( | |
475 2**31 - 1, "Workaround for MSVC bug; see https://crbug.com/445618") | |
476 | |
477 return "%s%s" % (token, _kind_to_cpp_literal_suffix.get(kind, "")) | |
478 | |
479 def ExpressionToText(value, kind=None): | |
480 return TranslateConstants(value, kind) | |
481 | 196 |
482 def RequiresContextForDataView(kind): | 197 def RequiresContextForDataView(kind): |
483 for field in kind.fields: | 198 for field in kind.fields: |
484 if mojom.IsReferenceKind(field.kind): | 199 if mojom.IsReferenceKind(field.kind): |
485 return True | 200 return True |
486 return False | 201 return False |
487 | 202 |
| 203 |
488 def ShouldInlineStruct(struct): | 204 def ShouldInlineStruct(struct): |
489 # TODO(darin): Base this on the size of the wrapper class. | 205 # TODO(darin): Base this on the size of the wrapper class. |
490 if len(struct.fields) > 4: | 206 if len(struct.fields) > 4: |
491 return False | 207 return False |
492 for field in struct.fields: | 208 for field in struct.fields: |
493 if mojom.IsReferenceKind(field.kind) and not mojom.IsStringKind(field.kind): | 209 if mojom.IsReferenceKind(field.kind) and not mojom.IsStringKind(field.kind): |
494 return False | 210 return False |
495 return True | 211 return True |
496 | 212 |
497 def ContainsMoveOnlyMembers(struct): | |
498 for field in struct.fields: | |
499 if IsMoveOnlyKind(field.kind): | |
500 return True | |
501 return False | |
502 | 213 |
503 def ShouldInlineUnion(union): | 214 def ShouldInlineUnion(union): |
504 return not any( | 215 return not any( |
505 mojom.IsReferenceKind(field.kind) and not mojom.IsStringKind(field.kind) | 216 mojom.IsReferenceKind(field.kind) and not mojom.IsStringKind(field.kind) |
506 for field in union.fields) | 217 for field in union.fields) |
507 | 218 |
508 | 219 |
509 class StructConstructor(object): | 220 class StructConstructor(object): |
510 """Represents a constructor for a generated struct. | 221 """Represents a constructor for a generated struct. |
511 | 222 |
512 Fields: | 223 Fields: |
513 fields: {[Field]} All struct fields in order. | 224 fields: {[Field]} All struct fields in order. |
514 params: {[Field]} The fields that are passed as params. | 225 params: {[Field]} The fields that are passed as params. |
515 """ | 226 """ |
516 | 227 |
517 def __init__(self, fields, params): | 228 def __init__(self, fields, params): |
518 self._fields = fields | 229 self._fields = fields |
519 self._params = set(params) | 230 self._params = set(params) |
520 | 231 |
521 @property | 232 @property |
522 def params(self): | 233 def params(self): |
523 return [field for field in self._fields if field in self._params] | 234 return [field for field in self._fields if field in self._params] |
524 | 235 |
525 @property | 236 @property |
526 def fields(self): | 237 def fields(self): |
527 for field in self._fields: | 238 for field in self._fields: |
528 yield (field, field in self._params) | 239 yield (field, field in self._params) |
529 | 240 |
530 | 241 |
531 def GetStructConstructors(struct): | 242 class Generator(generator.Generator): |
532 """Returns a list of constructors for a struct. | 243 def __init__(self, *args, **kwargs): |
| 244 super(Generator, self).__init__(*args, **kwargs) |
533 | 245 |
534 Params: | 246 def _GetExtraTraitsHeaders(self): |
535 struct: {Struct} The struct to return constructors for. | |
536 | |
537 Returns: | |
538 {[StructConstructor]} A list of StructConstructors that should be generated | |
539 for |struct|. | |
540 """ | |
541 if not mojom.IsStructKind(struct): | |
542 raise TypeError | |
543 # Types that are neither copyable nor movable can't be passed to a struct | |
544 # constructor so only generate a default constructor. | |
545 if any(IsTypemappedKind(field.kind) and _current_typemap[ | |
546 GetFullMojomNameForKind(field.kind)]["non_copyable_non_movable"] | |
547 for field in struct.fields): | |
548 return [StructConstructor(struct.fields, [])] | |
549 | |
550 param_counts = [0] | |
551 for version in struct.versions: | |
552 if param_counts[-1] != version.num_fields: | |
553 param_counts.append(version.num_fields) | |
554 | |
555 ordinal_fields = sorted(struct.fields, key=lambda field: field.ordinal) | |
556 return (StructConstructor(struct.fields, ordinal_fields[:param_count]) | |
557 for param_count in param_counts) | |
558 | |
559 | |
560 def GetContainerValidateParamsCtorArgs(kind): | |
561 if mojom.IsStringKind(kind): | |
562 expected_num_elements = 0 | |
563 element_is_nullable = False | |
564 key_validate_params = "nullptr" | |
565 element_validate_params = "nullptr" | |
566 enum_validate_func = "nullptr" | |
567 elif mojom.IsMapKind(kind): | |
568 expected_num_elements = 0 | |
569 element_is_nullable = False | |
570 key_validate_params = GetNewContainerValidateParams(mojom.Array( | |
571 kind=kind.key_kind)) | |
572 element_validate_params = GetNewContainerValidateParams(mojom.Array( | |
573 kind=kind.value_kind)) | |
574 enum_validate_func = "nullptr" | |
575 else: # mojom.IsArrayKind(kind) | |
576 expected_num_elements = generator.ExpectedArraySize(kind) or 0 | |
577 element_is_nullable = mojom.IsNullableKind(kind.kind) | |
578 key_validate_params = "nullptr" | |
579 element_validate_params = GetNewContainerValidateParams(kind.kind) | |
580 if mojom.IsEnumKind(kind.kind): | |
581 enum_validate_func = ("%s::Validate" % | |
582 GetQualifiedNameForKind(kind.kind, internal=True, | |
583 flatten_nested_kind=True)) | |
584 else: | |
585 enum_validate_func = "nullptr" | |
586 | |
587 if enum_validate_func == "nullptr": | |
588 if key_validate_params == "nullptr": | |
589 return "%d, %s, %s" % (expected_num_elements, | |
590 "true" if element_is_nullable else "false", | |
591 element_validate_params) | |
592 else: | |
593 return "%s, %s" % (key_validate_params, element_validate_params) | |
594 else: | |
595 return "%d, %s" % (expected_num_elements, enum_validate_func) | |
596 | |
597 def GetNewContainerValidateParams(kind): | |
598 if (not mojom.IsArrayKind(kind) and not mojom.IsMapKind(kind) and | |
599 not mojom.IsStringKind(kind)): | |
600 return "nullptr" | |
601 | |
602 return "new mojo::internal::ContainerValidateParams(%s)" % ( | |
603 GetContainerValidateParamsCtorArgs(kind)) | |
604 | |
605 class Generator(generator.Generator): | |
606 | |
607 cpp_filters = { | |
608 "all_enum_values": AllEnumValues, | |
609 "constant_value": ConstantValue, | |
610 "contains_handles_or_interfaces": mojom.ContainsHandlesOrInterfaces, | |
611 "contains_move_only_members": ContainsMoveOnlyMembers, | |
612 "cpp_wrapper_param_type": GetCppWrapperParamType, | |
613 "cpp_data_view_type": GetCppDataViewType, | |
614 "cpp_field_type": GetCppFieldType, | |
615 "cpp_union_field_type": GetCppUnionFieldType, | |
616 "cpp_pod_type": GetCppPodType, | |
617 "cpp_union_getter_return_type": GetUnionGetterReturnType, | |
618 "cpp_union_trait_getter_return_type": GetUnionTraitGetterReturnType, | |
619 "cpp_wrapper_type": GetCppWrapperType, | |
620 "default_value": DefaultValue, | |
621 "expression_to_text": ExpressionToText, | |
622 "format_constant_declaration": FormatConstantDeclaration, | |
623 "get_container_validate_params_ctor_args": | |
624 GetContainerValidateParamsCtorArgs, | |
625 "get_name_for_kind": GetNameForKind, | |
626 "get_pad": pack.GetPad, | |
627 "get_qualified_name_for_kind": GetQualifiedNameForKind, | |
628 "has_callbacks": mojom.HasCallbacks, | |
629 "has_sync_methods": mojom.HasSyncMethods, | |
630 "requires_context_for_data_view": RequiresContextForDataView, | |
631 "should_inline": ShouldInlineStruct, | |
632 "should_inline_union": ShouldInlineUnion, | |
633 "is_array_kind": mojom.IsArrayKind, | |
634 "is_enum_kind": mojom.IsEnumKind, | |
635 "is_integral_kind": mojom.IsIntegralKind, | |
636 "is_native_only_kind": IsNativeOnlyKind, | |
637 "is_any_handle_kind": mojom.IsAnyHandleKind, | |
638 "is_any_interface_kind": mojom.IsAnyInterfaceKind, | |
639 "is_any_handle_or_interface_kind": mojom.IsAnyHandleOrInterfaceKind, | |
640 "is_associated_kind": mojom.IsAssociatedKind, | |
641 "is_hashable": IsHashableKind, | |
642 "is_map_kind": mojom.IsMapKind, | |
643 "is_nullable_kind": mojom.IsNullableKind, | |
644 "is_object_kind": mojom.IsObjectKind, | |
645 "is_reference_kind": mojom.IsReferenceKind, | |
646 "is_string_kind": mojom.IsStringKind, | |
647 "is_struct_kind": mojom.IsStructKind, | |
648 "is_typemapped_kind": IsTypemappedKind, | |
649 "is_union_kind": mojom.IsUnionKind, | |
650 "passes_associated_kinds": mojom.PassesAssociatedKinds, | |
651 "struct_constructors": GetStructConstructors, | |
652 "stylize_method": generator.StudlyCapsToCamel, | |
653 "under_to_camel": generator.UnderToCamel, | |
654 "unmapped_type_for_serializer": GetUnmappedTypeForSerializer, | |
655 "wtf_hash_fn_name_for_enum": GetWtfHashFnNameForEnum, | |
656 } | |
657 | |
658 def GetExtraTraitsHeaders(self): | |
659 extra_headers = set() | 247 extra_headers = set() |
660 for typemap in self._GetAllUsedTypemaps(): | 248 for typemap in self._GetAllUsedTypemaps(): |
661 extra_headers.update(typemap.get("traits_headers", [])) | 249 extra_headers.update(typemap.get("traits_headers", [])) |
662 return sorted(extra_headers) | 250 return sorted(extra_headers) |
663 | 251 |
664 def _GetAllUsedTypemaps(self): | 252 def _GetAllUsedTypemaps(self): |
665 """Returns the typemaps for types needed for serialization in this module. | 253 """Returns the typemaps for types needed for serialization in this module. |
666 | 254 |
667 A type is needed for serialization if it is contained by a struct or union | 255 A type is needed for serialization if it is contained by a struct or union |
668 defined in this module, is a parameter of a message in an interface in | 256 defined in this module, is a parameter of a message in an interface in |
669 this module or is contained within another type needed for serialization. | 257 this module or is contained within another type needed for serialization. |
670 """ | 258 """ |
671 used_typemaps = [] | 259 used_typemaps = [] |
672 seen_types = set() | 260 seen_types = set() |
673 def AddKind(kind): | 261 def AddKind(kind): |
674 if (mojom.IsIntegralKind(kind) or mojom.IsStringKind(kind) or | 262 if (mojom.IsIntegralKind(kind) or mojom.IsStringKind(kind) or |
675 mojom.IsDoubleKind(kind) or mojom.IsFloatKind(kind) or | 263 mojom.IsDoubleKind(kind) or mojom.IsFloatKind(kind) or |
676 mojom.IsAnyHandleKind(kind) or | 264 mojom.IsAnyHandleKind(kind) or |
677 mojom.IsInterfaceKind(kind) or | 265 mojom.IsInterfaceKind(kind) or |
678 mojom.IsInterfaceRequestKind(kind) or | 266 mojom.IsInterfaceRequestKind(kind) or |
679 mojom.IsAssociatedKind(kind)): | 267 mojom.IsAssociatedKind(kind)): |
680 pass | 268 pass |
681 elif mojom.IsArrayKind(kind): | 269 elif mojom.IsArrayKind(kind): |
682 AddKind(kind.kind) | 270 AddKind(kind.kind) |
683 elif mojom.IsMapKind(kind): | 271 elif mojom.IsMapKind(kind): |
684 AddKind(kind.key_kind) | 272 AddKind(kind.key_kind) |
685 AddKind(kind.value_kind) | 273 AddKind(kind.value_kind) |
686 else: | 274 else: |
687 name = GetFullMojomNameForKind(kind) | 275 name = self._GetFullMojomNameForKind(kind) |
688 if name in seen_types: | 276 if name in seen_types: |
689 return | 277 return |
690 seen_types.add(name) | 278 seen_types.add(name) |
691 | 279 |
692 typemap = _current_typemap.get(name, None) | 280 typemap = self.typemap.get(name, None) |
693 if typemap: | 281 if typemap: |
694 used_typemaps.append(typemap) | 282 used_typemaps.append(typemap) |
695 if mojom.IsStructKind(kind) or mojom.IsUnionKind(kind): | 283 if mojom.IsStructKind(kind) or mojom.IsUnionKind(kind): |
696 for field in kind.fields: | 284 for field in kind.fields: |
697 AddKind(field.kind) | 285 AddKind(field.kind) |
698 | 286 |
699 for kind in self.module.structs + self.module.unions: | 287 for kind in self.module.structs + self.module.unions: |
700 for field in kind.fields: | 288 for field in kind.fields: |
701 AddKind(field.kind) | 289 AddKind(field.kind) |
702 | 290 |
703 for interface in self.module.interfaces: | 291 for interface in self.module.interfaces: |
704 for method in interface.methods: | 292 for method in interface.methods: |
705 for parameter in method.parameters + (method.response_parameters or []): | 293 for parameter in method.parameters + (method.response_parameters or []): |
706 AddKind(parameter.kind) | 294 AddKind(parameter.kind) |
707 | 295 |
708 return used_typemaps | 296 return used_typemaps |
709 | 297 |
710 def GetExtraPublicHeaders(self): | 298 def _GetExtraPublicHeaders(self): |
711 all_enums = list(self.module.enums) | 299 all_enums = list(self.module.enums) |
712 for struct in self.module.structs: | 300 for struct in self.module.structs: |
713 all_enums.extend(struct.enums) | 301 all_enums.extend(struct.enums) |
714 for interface in self.module.interfaces: | 302 for interface in self.module.interfaces: |
715 all_enums.extend(interface.enums) | 303 all_enums.extend(interface.enums) |
716 | 304 |
717 types = set(GetFullMojomNameForKind(typename) | 305 types = set(self._GetFullMojomNameForKind(typename) |
718 for typename in | 306 for typename in |
719 self.module.structs + all_enums + self.module.unions) | 307 self.module.structs + all_enums + self.module.unions) |
720 headers = set() | 308 headers = set() |
721 for typename, typemap in self.typemap.iteritems(): | 309 for typename, typemap in self.typemap.iteritems(): |
722 if typename in types: | 310 if typename in types: |
723 headers.update(typemap.get("public_headers", [])) | 311 headers.update(typemap.get("public_headers", [])) |
724 return sorted(headers) | 312 return sorted(headers) |
725 | 313 |
726 def _GetDirectlyUsedKinds(self): | 314 def _GetDirectlyUsedKinds(self): |
727 for struct in self.module.structs + self.module.unions: | 315 for struct in self.module.structs + self.module.unions: |
728 for field in struct.fields: | 316 for field in struct.fields: |
729 yield field.kind | 317 yield field.kind |
730 | 318 |
731 for interface in self.module.interfaces: | 319 for interface in self.module.interfaces: |
732 for method in interface.methods: | 320 for method in interface.methods: |
733 for param in method.parameters + (method.response_parameters or []): | 321 for param in method.parameters + (method.response_parameters or []): |
734 yield param.kind | 322 yield param.kind |
735 | 323 |
736 def GetJinjaExports(self): | 324 def _GetJinjaExports(self): |
737 structs = self.GetStructs() | 325 structs = self.GetStructs() |
738 interfaces = self.GetInterfaces() | 326 interfaces = self.GetInterfaces() |
739 all_enums = list(self.module.enums) | 327 all_enums = list(self.module.enums) |
740 for struct in structs: | 328 for struct in structs: |
741 all_enums.extend(struct.enums) | 329 all_enums.extend(struct.enums) |
742 for interface in interfaces: | 330 for interface in interfaces: |
743 all_enums.extend(interface.enums) | 331 all_enums.extend(interface.enums) |
744 | 332 |
745 return { | 333 return { |
746 "module": self.module, | 334 "module": self.module, |
747 "namespace": self.module.namespace, | 335 "namespace": self.module.namespace, |
748 "namespaces_as_array": NamespaceToArray(self.module.namespace), | 336 "namespaces_as_array": NamespaceToArray(self.module.namespace), |
749 "imports": self.module.imports, | 337 "imports": self.module.imports, |
750 "kinds": self.module.kinds, | 338 "kinds": self.module.kinds, |
751 "enums": self.module.enums, | 339 "enums": self.module.enums, |
752 "all_enums": all_enums, | 340 "all_enums": all_enums, |
753 "structs": structs, | 341 "structs": structs, |
754 "unions": self.GetUnions(), | 342 "unions": self.GetUnions(), |
755 "interfaces": interfaces, | 343 "interfaces": interfaces, |
756 "variant": self.variant, | 344 "variant": self.variant, |
757 "extra_traits_headers": self.GetExtraTraitsHeaders(), | 345 "extra_traits_headers": self._GetExtraTraitsHeaders(), |
758 "extra_public_headers": self.GetExtraPublicHeaders(), | 346 "extra_public_headers": self._GetExtraPublicHeaders(), |
759 "for_blink": self.for_blink, | 347 "for_blink": self.for_blink, |
760 "use_once_callback": self.use_once_callback, | 348 "use_once_callback": self.use_once_callback, |
761 "export_attribute": self.export_attribute, | 349 "export_attribute": self.export_attribute, |
762 "export_header": self.export_header, | 350 "export_header": self.export_header, |
763 } | 351 } |
764 | 352 |
765 @staticmethod | 353 @staticmethod |
766 def GetTemplatePrefix(): | 354 def GetTemplatePrefix(): |
767 return "cpp_templates" | 355 return "cpp_templates" |
768 | 356 |
769 @classmethod | 357 def GetFilters(self): |
770 def GetFilters(cls): | 358 cpp_filters = { |
771 return cls.cpp_filters | 359 "all_enum_values": AllEnumValues, |
| 360 "constant_value": self._ConstantValue, |
| 361 "contains_handles_or_interfaces": mojom.ContainsHandlesOrInterfaces, |
| 362 "contains_move_only_members": self._ContainsMoveOnlyMembers, |
| 363 "cpp_wrapper_param_type": self._GetCppWrapperParamType, |
| 364 "cpp_data_view_type": GetCppDataViewType, |
| 365 "cpp_field_type": self._GetCppFieldType, |
| 366 "cpp_union_field_type": self._GetCppUnionFieldType, |
| 367 "cpp_pod_type": GetCppPodType, |
| 368 "cpp_union_getter_return_type": self._GetUnionGetterReturnType, |
| 369 "cpp_union_trait_getter_return_type": self._GetUnionTraitGetterReturnType, |
| 370 "cpp_wrapper_type": self._GetCppWrapperType, |
| 371 "default_value": self._DefaultValue, |
| 372 "expression_to_text": self._ExpressionToText, |
| 373 "format_constant_declaration": self._FormatConstantDeclaration, |
| 374 "get_container_validate_params_ctor_args": |
| 375 self._GetContainerValidateParamsCtorArgs, |
| 376 "get_name_for_kind": self._GetNameForKind, |
| 377 "get_pad": pack.GetPad, |
| 378 "get_qualified_name_for_kind": self._GetQualifiedNameForKind, |
| 379 "has_callbacks": mojom.HasCallbacks, |
| 380 "has_sync_methods": mojom.HasSyncMethods, |
| 381 "requires_context_for_data_view": RequiresContextForDataView, |
| 382 "should_inline": ShouldInlineStruct, |
| 383 "should_inline_union": ShouldInlineUnion, |
| 384 "is_array_kind": mojom.IsArrayKind, |
| 385 "is_enum_kind": mojom.IsEnumKind, |
| 386 "is_integral_kind": mojom.IsIntegralKind, |
| 387 "is_native_only_kind": IsNativeOnlyKind, |
| 388 "is_any_handle_kind": mojom.IsAnyHandleKind, |
| 389 "is_any_interface_kind": mojom.IsAnyInterfaceKind, |
| 390 "is_any_handle_or_interface_kind": mojom.IsAnyHandleOrInterfaceKind, |
| 391 "is_associated_kind": mojom.IsAssociatedKind, |
| 392 "is_hashable": self._IsHashableKind, |
| 393 "is_map_kind": mojom.IsMapKind, |
| 394 "is_nullable_kind": mojom.IsNullableKind, |
| 395 "is_object_kind": mojom.IsObjectKind, |
| 396 "is_reference_kind": mojom.IsReferenceKind, |
| 397 "is_string_kind": mojom.IsStringKind, |
| 398 "is_struct_kind": mojom.IsStructKind, |
| 399 "is_typemapped_kind": self._IsTypemappedKind, |
| 400 "is_union_kind": mojom.IsUnionKind, |
| 401 "passes_associated_kinds": mojom.PassesAssociatedKinds, |
| 402 "struct_constructors": self._GetStructConstructors, |
| 403 "under_to_camel": generator.UnderToCamel, |
| 404 "unmapped_type_for_serializer": GetUnmappedTypeForSerializer, |
| 405 "wtf_hash_fn_name_for_enum": GetWtfHashFnNameForEnum, |
| 406 } |
| 407 return cpp_filters |
772 | 408 |
773 @UseJinja("module.h.tmpl") | 409 @UseJinja("module.h.tmpl") |
774 def GenerateModuleHeader(self): | 410 def _GenerateModuleHeader(self): |
775 return self.GetJinjaExports() | 411 return self._GetJinjaExports() |
776 | 412 |
777 @UseJinja("module.cc.tmpl") | 413 @UseJinja("module.cc.tmpl") |
778 def GenerateModuleSource(self): | 414 def _GenerateModuleSource(self): |
779 return self.GetJinjaExports() | 415 return self._GetJinjaExports() |
780 | 416 |
781 @UseJinja("module-shared.h.tmpl") | 417 @UseJinja("module-shared.h.tmpl") |
782 def GenerateModuleSharedHeader(self): | 418 def _GenerateModuleSharedHeader(self): |
783 return self.GetJinjaExports() | 419 return self._GetJinjaExports() |
784 | 420 |
785 @UseJinja("module-shared-internal.h.tmpl") | 421 @UseJinja("module-shared-internal.h.tmpl") |
786 def GenerateModuleSharedInternalHeader(self): | 422 def _GenerateModuleSharedInternalHeader(self): |
787 return self.GetJinjaExports() | 423 return self._GetJinjaExports() |
788 | 424 |
789 @UseJinja("module-shared.cc.tmpl") | 425 @UseJinja("module-shared.cc.tmpl") |
790 def GenerateModuleSharedSource(self): | 426 def _GenerateModuleSharedSource(self): |
791 return self.GetJinjaExports() | 427 return self._GetJinjaExports() |
792 | 428 |
793 def GenerateFiles(self, args): | 429 def GenerateFiles(self, args): |
794 if self.generate_non_variant_code: | 430 if self.generate_non_variant_code: |
795 self.Write(self.GenerateModuleSharedHeader(), | 431 self.Write(self._GenerateModuleSharedHeader(), |
796 self.MatchMojomFilePath("%s-shared.h" % self.module.name)) | 432 self.MatchMojomFilePath("%s-shared.h" % self.module.name)) |
797 self.Write( | 433 self.Write( |
798 self.GenerateModuleSharedInternalHeader(), | 434 self._GenerateModuleSharedInternalHeader(), |
799 self.MatchMojomFilePath("%s-shared-internal.h" % self.module.name)) | 435 self.MatchMojomFilePath("%s-shared-internal.h" % self.module.name)) |
800 self.Write(self.GenerateModuleSharedSource(), | 436 self.Write(self._GenerateModuleSharedSource(), |
801 self.MatchMojomFilePath("%s-shared.cc" % self.module.name)) | 437 self.MatchMojomFilePath("%s-shared.cc" % self.module.name)) |
802 else: | 438 else: |
803 global _current_typemap | |
804 _current_typemap = self.typemap | |
805 global _for_blink | |
806 _for_blink = self.for_blink | |
807 global _use_once_callback | |
808 _use_once_callback = self.use_once_callback | |
809 global _variant | |
810 _variant = self.variant | |
811 global _export_attribute | |
812 _export_attribute = self.export_attribute | |
813 suffix = "-%s" % self.variant if self.variant else "" | 439 suffix = "-%s" % self.variant if self.variant else "" |
814 self.Write(self.GenerateModuleHeader(), | 440 self.Write(self._GenerateModuleHeader(), |
815 self.MatchMojomFilePath("%s%s.h" % (self.module.name, suffix))) | 441 self.MatchMojomFilePath("%s%s.h" % (self.module.name, suffix))) |
816 self.Write( | 442 self.Write( |
817 self.GenerateModuleSource(), | 443 self._GenerateModuleSource(), |
818 self.MatchMojomFilePath("%s%s.cc" % (self.module.name, suffix))) | 444 self.MatchMojomFilePath("%s%s.cc" % (self.module.name, suffix))) |
| 445 |
| 446 def _ConstantValue(self, constant): |
| 447 return self._ExpressionToText(constant.value, kind=constant.kind) |
| 448 |
| 449 # TODO(yzshen): Revisit the default value feature. It was designed prior to |
| 450 # custom type mapping. |
| 451 def _DefaultValue(self, field): |
| 452 if field.default: |
| 453 if mojom.IsStructKind(field.kind): |
| 454 assert field.default == "default" |
| 455 if not self._IsTypemappedKind(field.kind): |
| 456 return "%s::New()" % self._GetNameForKind(field.kind) |
| 457 return self._ExpressionToText(field.default, kind=field.kind) |
| 458 return "" |
| 459 |
| 460 def _GetNameForKind(self, kind, internal=False, flatten_nested_kind=False, |
| 461 add_same_module_namespaces=False): |
| 462 return _NameFormatter(kind, self.variant).FormatForCpp( |
| 463 internal=internal, flatten_nested_kind=flatten_nested_kind, |
| 464 add_same_module_namespaces=add_same_module_namespaces) |
| 465 |
| 466 def _GetQualifiedNameForKind(self, kind, internal=False, |
| 467 flatten_nested_kind=False, include_variant=True): |
| 468 return _NameFormatter( |
| 469 kind, self.variant if include_variant else None).FormatForCpp( |
| 470 internal=internal, add_same_module_namespaces=True, |
| 471 flatten_nested_kind=flatten_nested_kind) |
| 472 |
| 473 def _GetFullMojomNameForKind(self, kind): |
| 474 return _NameFormatter(kind, self.variant).FormatForMojom() |
| 475 |
| 476 def _IsTypemappedKind(self, kind): |
| 477 return hasattr(kind, "name") and \ |
| 478 self._GetFullMojomNameForKind(kind) in self.typemap |
| 479 |
| 480 def _IsHashableKind(self, kind): |
| 481 """Check if the kind can be hashed. |
| 482 |
| 483 Args: |
| 484 kind: {Kind} The kind to check. |
| 485 |
| 486 Returns: |
| 487 {bool} True if a value of this kind can be hashed. |
| 488 """ |
| 489 checked = set() |
| 490 def Check(kind): |
| 491 if kind.spec in checked: |
| 492 return True |
| 493 checked.add(kind.spec) |
| 494 if mojom.IsNullableKind(kind): |
| 495 return False |
| 496 elif mojom.IsStructKind(kind): |
| 497 if (self._IsTypemappedKind(kind) and |
| 498 not self.typemap[self._GetFullMojomNameForKind(kind)]["hashable"]): |
| 499 return False |
| 500 return all(Check(field.kind) for field in kind.fields) |
| 501 elif mojom.IsEnumKind(kind): |
| 502 return not self._IsTypemappedKind(kind) or self.typemap[ |
| 503 self._GetFullMojomNameForKind(kind)]["hashable"] |
| 504 elif mojom.IsUnionKind(kind): |
| 505 return all(Check(field.kind) for field in kind.fields) |
| 506 elif mojom.IsAnyHandleKind(kind): |
| 507 return False |
| 508 elif mojom.IsAnyInterfaceKind(kind): |
| 509 return False |
| 510 # TODO(tibell): Arrays and maps could be made hashable. We just don't have |
| 511 # a use case yet. |
| 512 elif mojom.IsArrayKind(kind): |
| 513 return False |
| 514 elif mojom.IsMapKind(kind): |
| 515 return False |
| 516 else: |
| 517 return True |
| 518 return Check(kind) |
| 519 |
| 520 def _GetNativeTypeName(self, typemapped_kind): |
| 521 return self.typemap[self._GetFullMojomNameForKind(typemapped_kind)][ |
| 522 "typename"] |
| 523 |
| 524 def _FormatConstantDeclaration(self, constant, nested=False): |
| 525 if mojom.IsStringKind(constant.kind): |
| 526 if nested: |
| 527 return "const char %s[]" % constant.name |
| 528 return "%sextern const char %s[]" % \ |
| 529 ((self.export_attribute + " ") if self.export_attribute else "", |
| 530 constant.name) |
| 531 return "constexpr %s %s = %s" % ( |
| 532 GetCppPodType(constant.kind), constant.name, |
| 533 self._ConstantValue(constant)) |
| 534 |
| 535 def _GetCppWrapperType(self, kind, add_same_module_namespaces=False): |
| 536 def _AddOptional(type_name): |
| 537 pattern = "WTF::Optional<%s>" if self.for_blink else "base::Optional<%s>" |
| 538 return pattern % type_name |
| 539 |
| 540 if self._IsTypemappedKind(kind): |
| 541 type_name = self._GetNativeTypeName(kind) |
| 542 if (mojom.IsNullableKind(kind) and |
| 543 not self.typemap[self._GetFullMojomNameForKind(kind)][ |
| 544 "nullable_is_same_type"]): |
| 545 type_name = _AddOptional(type_name) |
| 546 return type_name |
| 547 if mojom.IsEnumKind(kind): |
| 548 return self._GetNameForKind( |
| 549 kind, add_same_module_namespaces=add_same_module_namespaces) |
| 550 if mojom.IsStructKind(kind) or mojom.IsUnionKind(kind): |
| 551 return "%sPtr" % self._GetNameForKind( |
| 552 kind, add_same_module_namespaces=add_same_module_namespaces) |
| 553 if mojom.IsArrayKind(kind): |
| 554 pattern = "WTF::Vector<%s>" if self.for_blink else "std::vector<%s>" |
| 555 if mojom.IsNullableKind(kind): |
| 556 pattern = _AddOptional(pattern) |
| 557 return pattern % self._GetCppWrapperType( |
| 558 kind.kind, add_same_module_namespaces=add_same_module_namespaces) |
| 559 if mojom.IsMapKind(kind): |
| 560 pattern = ("WTF::HashMap<%s, %s>" if self.for_blink else |
| 561 "std::unordered_map<%s, %s>") |
| 562 if mojom.IsNullableKind(kind): |
| 563 pattern = _AddOptional(pattern) |
| 564 return pattern % ( |
| 565 self._GetCppWrapperType( |
| 566 kind.key_kind, |
| 567 add_same_module_namespaces=add_same_module_namespaces), |
| 568 self._GetCppWrapperType( |
| 569 kind.value_kind, |
| 570 add_same_module_namespaces=add_same_module_namespaces)) |
| 571 if mojom.IsInterfaceKind(kind): |
| 572 return "%sPtr" % self._GetNameForKind( |
| 573 kind, add_same_module_namespaces=add_same_module_namespaces) |
| 574 if mojom.IsInterfaceRequestKind(kind): |
| 575 return "%sRequest" % self._GetNameForKind( |
| 576 kind.kind, add_same_module_namespaces=add_same_module_namespaces) |
| 577 if mojom.IsAssociatedInterfaceKind(kind): |
| 578 return "%sAssociatedPtrInfo" % self._GetNameForKind( |
| 579 kind.kind, add_same_module_namespaces=add_same_module_namespaces) |
| 580 if mojom.IsAssociatedInterfaceRequestKind(kind): |
| 581 return "%sAssociatedRequest" % self._GetNameForKind( |
| 582 kind.kind, add_same_module_namespaces=add_same_module_namespaces) |
| 583 if mojom.IsStringKind(kind): |
| 584 if self.for_blink: |
| 585 return "WTF::String" |
| 586 type_name = "std::string" |
| 587 return (_AddOptional(type_name) if mojom.IsNullableKind(kind) |
| 588 else type_name) |
| 589 if mojom.IsGenericHandleKind(kind): |
| 590 return "mojo::ScopedHandle" |
| 591 if mojom.IsDataPipeConsumerKind(kind): |
| 592 return "mojo::ScopedDataPipeConsumerHandle" |
| 593 if mojom.IsDataPipeProducerKind(kind): |
| 594 return "mojo::ScopedDataPipeProducerHandle" |
| 595 if mojom.IsMessagePipeKind(kind): |
| 596 return "mojo::ScopedMessagePipeHandle" |
| 597 if mojom.IsSharedBufferKind(kind): |
| 598 return "mojo::ScopedSharedBufferHandle" |
| 599 if not kind in _kind_to_cpp_type: |
| 600 raise Exception("Unrecognized kind %s" % kind.spec) |
| 601 return _kind_to_cpp_type[kind] |
| 602 |
| 603 def _IsMoveOnlyKind(self, kind): |
| 604 if self._IsTypemappedKind(kind): |
| 605 if mojom.IsEnumKind(kind): |
| 606 return False |
| 607 return self.typemap[self._GetFullMojomNameForKind(kind)]["move_only"] |
| 608 if mojom.IsStructKind(kind) or mojom.IsUnionKind(kind): |
| 609 return True |
| 610 if mojom.IsArrayKind(kind): |
| 611 return self._IsMoveOnlyKind(kind.kind) |
| 612 if mojom.IsMapKind(kind): |
| 613 return self._IsMoveOnlyKind(kind.value_kind) |
| 614 if mojom.IsAnyHandleOrInterfaceKind(kind): |
| 615 return True |
| 616 return False |
| 617 |
| 618 def _IsCopyablePassByValue(self, kind): |
| 619 if not self._IsTypemappedKind(kind): |
| 620 return False |
| 621 return self.typemap[self._GetFullMojomNameForKind(kind)][ |
| 622 "copyable_pass_by_value"] |
| 623 |
| 624 def _ShouldPassParamByValue(self, kind): |
| 625 return ((not mojom.IsReferenceKind(kind)) or self._IsMoveOnlyKind(kind) or |
| 626 self._IsCopyablePassByValue(kind)) |
| 627 |
| 628 def _GetCppWrapperParamType(self, kind): |
| 629 cpp_wrapper_type = self._GetCppWrapperType(kind) |
| 630 return (cpp_wrapper_type if self._ShouldPassParamByValue(kind) |
| 631 else "const %s&" % cpp_wrapper_type) |
| 632 |
| 633 def _GetCppFieldType(self, kind): |
| 634 if mojom.IsStructKind(kind): |
| 635 return ("mojo::internal::Pointer<%s>" % |
| 636 self._GetNameForKind(kind, internal=True)) |
| 637 if mojom.IsUnionKind(kind): |
| 638 return "%s" % self._GetNameForKind(kind, internal=True) |
| 639 if mojom.IsArrayKind(kind): |
| 640 return ("mojo::internal::Pointer<mojo::internal::Array_Data<%s>>" % |
| 641 self._GetCppFieldType(kind.kind)) |
| 642 if mojom.IsMapKind(kind): |
| 643 return ("mojo::internal::Pointer<mojo::internal::Map_Data<%s, %s>>" % |
| 644 (self._GetCppFieldType(kind.key_kind), |
| 645 self._GetCppFieldType(kind.value_kind))) |
| 646 if mojom.IsInterfaceKind(kind): |
| 647 return "mojo::internal::Interface_Data" |
| 648 if mojom.IsInterfaceRequestKind(kind): |
| 649 return "mojo::internal::Handle_Data" |
| 650 if mojom.IsAssociatedInterfaceKind(kind): |
| 651 return "mojo::internal::AssociatedInterface_Data" |
| 652 if mojom.IsAssociatedInterfaceRequestKind(kind): |
| 653 return "mojo::internal::AssociatedEndpointHandle_Data" |
| 654 if mojom.IsEnumKind(kind): |
| 655 return "int32_t" |
| 656 if mojom.IsStringKind(kind): |
| 657 return "mojo::internal::Pointer<mojo::internal::String_Data>" |
| 658 if mojom.IsAnyHandleKind(kind): |
| 659 return "mojo::internal::Handle_Data" |
| 660 return _kind_to_cpp_type[kind] |
| 661 |
| 662 def _GetCppUnionFieldType(self, kind): |
| 663 if mojom.IsUnionKind(kind): |
| 664 return ("mojo::internal::Pointer<%s>" % |
| 665 self._GetNameForKind(kind, internal=True)) |
| 666 return self._GetCppFieldType(kind) |
| 667 |
| 668 def _GetUnionGetterReturnType(self, kind): |
| 669 if mojom.IsReferenceKind(kind): |
| 670 return "%s&" % self._GetCppWrapperType(kind) |
| 671 return self._GetCppWrapperType(kind) |
| 672 |
| 673 def _GetUnionTraitGetterReturnType(self, kind): |
| 674 """Get field type used in UnionTraits template specialization. |
| 675 |
| 676 The type may be qualified as UnionTraits specializations live outside the |
| 677 namespace where e.g. structs are defined. |
| 678 |
| 679 Args: |
| 680 kind: {Kind} The type of the field. |
| 681 |
| 682 Returns: |
| 683 {str} The C++ type to use for the field. |
| 684 """ |
| 685 if mojom.IsReferenceKind(kind): |
| 686 return "%s&" % self._GetCppWrapperType(kind, |
| 687 add_same_module_namespaces=True) |
| 688 return self._GetCppWrapperType(kind, add_same_module_namespaces=True) |
| 689 |
| 690 def _TranslateConstants(self, token, kind): |
| 691 if isinstance(token, mojom.NamedValue): |
| 692 return self._GetNameForKind(token, flatten_nested_kind=True) |
| 693 |
| 694 if isinstance(token, mojom.BuiltinValue): |
| 695 if token.value == "double.INFINITY": |
| 696 return "std::numeric_limits<double>::infinity()" |
| 697 if token.value == "float.INFINITY": |
| 698 return "std::numeric_limits<float>::infinity()" |
| 699 if token.value == "double.NEGATIVE_INFINITY": |
| 700 return "-std::numeric_limits<double>::infinity()" |
| 701 if token.value == "float.NEGATIVE_INFINITY": |
| 702 return "-std::numeric_limits<float>::infinity()" |
| 703 if token.value == "double.NAN": |
| 704 return "std::numeric_limits<double>::quiet_NaN()" |
| 705 if token.value == "float.NAN": |
| 706 return "std::numeric_limits<float>::quiet_NaN()" |
| 707 |
| 708 if (kind is not None and mojom.IsFloatKind(kind)): |
| 709 return token if token.isdigit() else token + "f"; |
| 710 |
| 711 # Per C++11, 2.14.2, the type of an integer literal is the first of the |
| 712 # corresponding list in Table 6 in which its value can be represented. In |
| 713 # this case, the list for decimal constants with no suffix is: |
| 714 # int, long int, long long int |
| 715 # The standard considers a program ill-formed if it contains an integer |
| 716 # literal that cannot be represented by any of the allowed types. |
| 717 # |
| 718 # As it turns out, MSVC doesn't bother trying to fall back to long long int, |
| 719 # so the integral constant -2147483648 causes it grief: it decides to |
| 720 # represent 2147483648 as an unsigned integer, and then warns that the unary |
| 721 # minus operator doesn't make sense on unsigned types. Doh! |
| 722 if kind == mojom.INT32 and token == "-2147483648": |
| 723 return "(-%d - 1) /* %s */" % ( |
| 724 2**31 - 1, "Workaround for MSVC bug; see https://crbug.com/445618") |
| 725 |
| 726 return "%s%s" % (token, _kind_to_cpp_literal_suffix.get(kind, "")) |
| 727 |
| 728 def _ExpressionToText(self, value, kind=None): |
| 729 return self._TranslateConstants(value, kind) |
| 730 |
| 731 def _ContainsMoveOnlyMembers(self, struct): |
| 732 for field in struct.fields: |
| 733 if self._IsMoveOnlyKind(field.kind): |
| 734 return True |
| 735 return False |
| 736 |
| 737 def _GetStructConstructors(self, struct): |
| 738 """Returns a list of constructors for a struct. |
| 739 |
| 740 Params: |
| 741 struct: {Struct} The struct to return constructors for. |
| 742 |
| 743 Returns: |
| 744 {[StructConstructor]} A list of StructConstructors that should be |
| 745 generated for |struct|. |
| 746 """ |
| 747 if not mojom.IsStructKind(struct): |
| 748 raise TypeError |
| 749 # Types that are neither copyable nor movable can't be passed to a struct |
| 750 # constructor so only generate a default constructor. |
| 751 if any(self._IsTypemappedKind(field.kind) and self.typemap[ |
| 752 self._GetFullMojomNameForKind(field.kind)]["non_copyable_non_movable"] |
| 753 for field in struct.fields): |
| 754 return [StructConstructor(struct.fields, [])] |
| 755 |
| 756 param_counts = [0] |
| 757 for version in struct.versions: |
| 758 if param_counts[-1] != version.num_fields: |
| 759 param_counts.append(version.num_fields) |
| 760 |
| 761 ordinal_fields = sorted(struct.fields, key=lambda field: field.ordinal) |
| 762 return (StructConstructor(struct.fields, ordinal_fields[:param_count]) |
| 763 for param_count in param_counts) |
| 764 |
| 765 def _GetContainerValidateParamsCtorArgs(self, kind): |
| 766 if mojom.IsStringKind(kind): |
| 767 expected_num_elements = 0 |
| 768 element_is_nullable = False |
| 769 key_validate_params = "nullptr" |
| 770 element_validate_params = "nullptr" |
| 771 enum_validate_func = "nullptr" |
| 772 elif mojom.IsMapKind(kind): |
| 773 expected_num_elements = 0 |
| 774 element_is_nullable = False |
| 775 key_validate_params = self._GetNewContainerValidateParams(mojom.Array( |
| 776 kind=kind.key_kind)) |
| 777 element_validate_params = self._GetNewContainerValidateParams(mojom.Array( |
| 778 kind=kind.value_kind)) |
| 779 enum_validate_func = "nullptr" |
| 780 else: # mojom.IsArrayKind(kind) |
| 781 expected_num_elements = generator.ExpectedArraySize(kind) or 0 |
| 782 element_is_nullable = mojom.IsNullableKind(kind.kind) |
| 783 key_validate_params = "nullptr" |
| 784 element_validate_params = self._GetNewContainerValidateParams(kind.kind) |
| 785 if mojom.IsEnumKind(kind.kind): |
| 786 enum_validate_func = ("%s::Validate" % |
| 787 self._GetQualifiedNameForKind(kind.kind, internal=True, |
| 788 flatten_nested_kind=True)) |
| 789 else: |
| 790 enum_validate_func = "nullptr" |
| 791 |
| 792 if enum_validate_func == "nullptr": |
| 793 if key_validate_params == "nullptr": |
| 794 return "%d, %s, %s" % (expected_num_elements, |
| 795 "true" if element_is_nullable else "false", |
| 796 element_validate_params) |
| 797 else: |
| 798 return "%s, %s" % (key_validate_params, element_validate_params) |
| 799 else: |
| 800 return "%d, %s" % (expected_num_elements, enum_validate_func) |
| 801 |
| 802 def _GetNewContainerValidateParams(self, kind): |
| 803 if (not mojom.IsArrayKind(kind) and not mojom.IsMapKind(kind) and |
| 804 not mojom.IsStringKind(kind)): |
| 805 return "nullptr" |
| 806 |
| 807 return "new mojo::internal::ContainerValidateParams(%s)" % ( |
| 808 self._GetContainerValidateParamsCtorArgs(kind)) |
OLD | NEW |