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 3# found in the LICENSE file. 4 5"""Generates C++ source files from a mojom.Module.""" 6 7import mojom.generate.generator as generator 8import mojom.generate.module as mojom 9import mojom.generate.pack as pack 10from mojom.generate.template_expander import UseJinja 11 12 13_kind_to_cpp_type = { 14 mojom.BOOL: "bool", 15 mojom.INT8: "int8_t", 16 mojom.UINT8: "uint8_t", 17 mojom.INT16: "int16_t", 18 mojom.UINT16: "uint16_t", 19 mojom.INT32: "int32_t", 20 mojom.UINT32: "uint32_t", 21 mojom.FLOAT: "float", 22 mojom.INT64: "int64_t", 23 mojom.UINT64: "uint64_t", 24 mojom.DOUBLE: "double", 25} 26 27_kind_to_cpp_literal_suffix = { 28 mojom.UINT8: "U", 29 mojom.UINT16: "U", 30 mojom.UINT32: "U", 31 mojom.FLOAT: "f", 32 mojom.UINT64: "ULL", 33} 34 35 36class _NameFormatter(object): 37 """A formatter for the names of kinds or values.""" 38 39 def __init__(self, token, variant): 40 self._token = token 41 self._variant = variant 42 43 def Format(self, separator, prefixed=False, internal=False, 44 include_variant=False, omit_namespace_for_module=None, 45 flatten_nested_kind=False): 46 """Formats the name according to the given configuration. 47 48 Args: 49 separator: Separator between different parts of the name. 50 prefixed: Whether a leading separator should be added. 51 internal: Returns the name in the "internal" namespace. 52 include_variant: Whether to include variant as namespace. If |internal| is 53 True, then this flag is ignored and variant is not included. 54 omit_namespace_for_module: If the token is from the specified module, 55 don't add the namespaces of the module to the name. 56 flatten_nested_kind: It is allowed to define enums inside structs and 57 interfaces. If this flag is set to True, this method concatenates the 58 parent kind and the nested kind with '_', instead of treating the 59 parent kind as a scope.""" 60 61 parts = [] 62 if self._ShouldIncludeNamespace(omit_namespace_for_module): 63 if prefixed: 64 parts.append("") 65 parts.extend(self._GetNamespace()) 66 if include_variant and self._variant and not internal: 67 parts.append(self._variant) 68 parts.extend(self._GetName(internal, flatten_nested_kind)) 69 return separator.join(parts) 70 71 def FormatForCpp(self, omit_namespace_for_module=None, internal=False, 72 flatten_nested_kind=False): 73 return self.Format( 74 "::", prefixed=True, 75 omit_namespace_for_module=omit_namespace_for_module, 76 internal=internal, include_variant=True, 77 flatten_nested_kind=flatten_nested_kind) 78 79 def FormatForMojom(self): 80 return self.Format(".") 81 82 def _MapKindName(self, token, internal): 83 if not internal: 84 return token.name 85 if (mojom.IsStructKind(token) or mojom.IsUnionKind(token) or 86 mojom.IsEnumKind(token)): 87 return token.name + "_Data" 88 return token.name 89 90 def _GetName(self, internal, flatten_nested_kind): 91 if isinstance(self._token, mojom.EnumValue): 92 name_parts = _NameFormatter(self._token.enum, self._variant)._GetName( 93 internal, flatten_nested_kind) 94 name_parts.append(self._token.name) 95 return name_parts 96 97 name_parts = [] 98 if internal: 99 name_parts.append("internal") 100 101 if (flatten_nested_kind and mojom.IsEnumKind(self._token) and 102 self._token.parent_kind): 103 name = "%s_%s" % (self._token.parent_kind.name, 104 self._MapKindName(self._token, internal)) 105 name_parts.append(name) 106 return name_parts 107 108 if self._token.parent_kind: 109 name_parts.append(self._MapKindName(self._token.parent_kind, internal)) 110 name_parts.append(self._MapKindName(self._token, internal)) 111 return name_parts 112 113 def _ShouldIncludeNamespace(self, omit_namespace_for_module): 114 return self._token.module and ( 115 not omit_namespace_for_module or 116 self._token.module.path != omit_namespace_for_module.path) 117 118 def _GetNamespace(self): 119 if self._token.module: 120 return NamespaceToArray(self._token.module.namespace) 121 122 123def NamespaceToArray(namespace): 124 return namespace.split(".") if namespace else [] 125 126 127def GetWtfHashFnNameForEnum(enum): 128 return _NameFormatter(enum, None).Format("_", internal=True, 129 flatten_nested_kind=True) + "HashFn" 130 131 132def IsNativeOnlyKind(kind): 133 return (mojom.IsStructKind(kind) or mojom.IsEnumKind(kind)) and \ 134 kind.native_only 135 136 137def UseCustomSerializer(kind): 138 return mojom.IsStructKind(kind) and kind.custom_serializer 139 140 141def AllEnumValues(enum): 142 """Return all enum values associated with an enum. 143 144 Args: 145 enum: {mojom.Enum} The enum type. 146 147 Returns: 148 {Set[int]} The values. 149 """ 150 return set(field.numeric_value for field in enum.fields) 151 152 153def GetCppPodType(kind): 154 return _kind_to_cpp_type[kind] 155 156 157def RequiresContextForDataView(kind): 158 for field in kind.fields: 159 if mojom.IsReferenceKind(field.kind): 160 return True 161 return False 162 163 164def ShouldInlineStruct(struct): 165 # TODO(darin): Base this on the size of the wrapper class. 166 if len(struct.fields) > 4: 167 return False 168 for field in struct.fields: 169 if mojom.IsReferenceKind(field.kind) and not mojom.IsStringKind(field.kind): 170 return False 171 return True 172 173 174def ShouldInlineUnion(union): 175 return not any( 176 mojom.IsReferenceKind(field.kind) and not mojom.IsStringKind(field.kind) 177 for field in union.fields) 178 179 180class StructConstructor(object): 181 """Represents a constructor for a generated struct. 182 183 Fields: 184 fields: {[Field]} All struct fields in order. 185 params: {[Field]} The fields that are passed as params. 186 """ 187 188 def __init__(self, fields, params): 189 self._fields = fields 190 self._params = set(params) 191 192 @property 193 def params(self): 194 return [field for field in self._fields if field in self._params] 195 196 @property 197 def fields(self): 198 for field in self._fields: 199 yield (field, field in self._params) 200 201 202class Generator(generator.Generator): 203 def __init__(self, *args, **kwargs): 204 super(Generator, self).__init__(*args, **kwargs) 205 206 def _GetExtraTraitsHeaders(self): 207 extra_headers = set() 208 for typemap in self._GetAllUsedTypemaps(): 209 extra_headers.update(typemap.get("traits_headers", [])) 210 return sorted(extra_headers) 211 212 def _GetAllUsedTypemaps(self): 213 """Returns the typemaps for types needed for serialization in this module. 214 215 A type is needed for serialization if it is contained by a struct or union 216 defined in this module, is a parameter of a message in an interface in 217 this module or is contained within another type needed for serialization. 218 """ 219 used_typemaps = [] 220 seen_types = set() 221 def AddKind(kind): 222 if (mojom.IsIntegralKind(kind) or mojom.IsStringKind(kind) or 223 mojom.IsDoubleKind(kind) or mojom.IsFloatKind(kind) or 224 mojom.IsAnyHandleKind(kind) or 225 mojom.IsInterfaceKind(kind) or 226 mojom.IsInterfaceRequestKind(kind) or 227 mojom.IsAssociatedKind(kind)): 228 pass 229 elif mojom.IsArrayKind(kind): 230 AddKind(kind.kind) 231 elif mojom.IsMapKind(kind): 232 AddKind(kind.key_kind) 233 AddKind(kind.value_kind) 234 else: 235 name = self._GetFullMojomNameForKind(kind) 236 if name in seen_types: 237 return 238 seen_types.add(name) 239 240 typemap = self.typemap.get(name, None) 241 if typemap: 242 used_typemaps.append(typemap) 243 if mojom.IsStructKind(kind) or mojom.IsUnionKind(kind): 244 for field in kind.fields: 245 AddKind(field.kind) 246 247 for kind in self.module.structs + self.module.unions: 248 for field in kind.fields: 249 AddKind(field.kind) 250 251 for interface in self.module.interfaces: 252 for method in interface.methods: 253 for parameter in method.parameters + (method.response_parameters or []): 254 AddKind(parameter.kind) 255 256 return used_typemaps 257 258 def _GetExtraPublicHeaders(self): 259 headers = set() 260 261 all_enums = list(self.module.enums) 262 for struct in self.module.structs: 263 all_enums.extend(struct.enums) 264 for interface in self.module.interfaces: 265 all_enums.extend(interface.enums) 266 if interface.uuid: 267 headers.add('base/token.h') 268 269 types = set(self._GetFullMojomNameForKind(typename) 270 for typename in 271 self.module.structs + all_enums + self.module.unions) 272 for typename, typemap in self.typemap.items(): 273 if typename in types: 274 headers.update(typemap.get("public_headers", [])) 275 return sorted(headers) 276 277 def _GetDirectlyUsedKinds(self): 278 for struct in self.module.structs + self.module.unions: 279 for field in struct.fields: 280 yield field.kind 281 282 for interface in self.module.interfaces: 283 for method in interface.methods: 284 for param in method.parameters + (method.response_parameters or []): 285 yield param.kind 286 287 def _GetJinjaExports(self): 288 all_enums = list(self.module.enums) 289 for struct in self.module.structs: 290 all_enums.extend(struct.enums) 291 for interface in self.module.interfaces: 292 all_enums.extend(interface.enums) 293 294 return { 295 "all_enums": all_enums, 296 "disallow_interfaces": self.disallow_interfaces, 297 "disallow_native_types": self.disallow_native_types, 298 "enums": self.module.enums, 299 "export_attribute": self.export_attribute, 300 "export_header": self.export_header, 301 "extra_public_headers": self._GetExtraPublicHeaders(), 302 "extra_traits_headers": self._GetExtraTraitsHeaders(), 303 "for_blink": self.for_blink, 304 "imports": self.module.imports, 305 "interfaces": self.module.interfaces, 306 "kinds": self.module.kinds, 307 "module": self.module, 308 "namespace": self.module.namespace, 309 "namespaces_as_array": NamespaceToArray(self.module.namespace), 310 "structs": self.module.structs, 311 "support_lazy_serialization": self.support_lazy_serialization, 312 "unions": self.module.unions, 313 "use_once_callback": self.use_once_callback, 314 "variant": self.variant, 315 } 316 317 @staticmethod 318 def GetTemplatePrefix(): 319 return "cpp_templates" 320 321 def GetFilters(self): 322 cpp_filters = { 323 "all_enum_values": AllEnumValues, 324 "constant_value": self._ConstantValue, 325 "contains_handles_or_interfaces": mojom.ContainsHandlesOrInterfaces, 326 "contains_move_only_members": self._ContainsMoveOnlyMembers, 327 "cpp_data_view_type": self._GetCppDataViewType, 328 "cpp_field_type": self._GetCppFieldType, 329 "cpp_union_field_type": self._GetCppUnionFieldType, 330 "cpp_pod_type": GetCppPodType, 331 "cpp_union_getter_return_type": self._GetUnionGetterReturnType, 332 "cpp_union_trait_getter_return_type": self._GetUnionTraitGetterReturnType, 333 "cpp_wrapper_call_type": self._GetCppWrapperCallType, 334 "cpp_wrapper_param_type": self._GetCppWrapperParamType, 335 "cpp_wrapper_param_type_new": self._GetCppWrapperParamTypeNew, 336 "cpp_wrapper_type": self._GetCppWrapperType, 337 "default_value": self._DefaultValue, 338 "expression_to_text": self._ExpressionToText, 339 "format_constant_declaration": self._FormatConstantDeclaration, 340 "get_container_validate_params_ctor_args": 341 self._GetContainerValidateParamsCtorArgs, 342 "get_name_for_kind": self._GetNameForKind, 343 "get_pad": pack.GetPad, 344 "get_qualified_name_for_kind": self._GetQualifiedNameForKind, 345 "has_callbacks": mojom.HasCallbacks, 346 "has_sync_methods": mojom.HasSyncMethods, 347 "method_supports_lazy_serialization": 348 self._MethodSupportsLazySerialization, 349 "requires_context_for_data_view": RequiresContextForDataView, 350 "should_inline": ShouldInlineStruct, 351 "should_inline_union": ShouldInlineUnion, 352 "is_array_kind": mojom.IsArrayKind, 353 "is_enum_kind": mojom.IsEnumKind, 354 "is_integral_kind": mojom.IsIntegralKind, 355 "is_interface_kind": mojom.IsInterfaceKind, 356 "is_native_only_kind": IsNativeOnlyKind, 357 "is_any_handle_kind": mojom.IsAnyHandleKind, 358 "is_any_interface_kind": mojom.IsAnyInterfaceKind, 359 "is_any_handle_or_interface_kind": mojom.IsAnyHandleOrInterfaceKind, 360 "is_associated_kind": mojom.IsAssociatedKind, 361 "is_hashable": self._IsHashableKind, 362 "is_map_kind": mojom.IsMapKind, 363 "is_nullable_kind": mojom.IsNullableKind, 364 "is_object_kind": mojom.IsObjectKind, 365 "is_reference_kind": mojom.IsReferenceKind, 366 "is_string_kind": mojom.IsStringKind, 367 "is_struct_kind": mojom.IsStructKind, 368 "is_typemapped_kind": self._IsTypemappedKind, 369 "is_union_kind": mojom.IsUnionKind, 370 "passes_associated_kinds": mojom.PassesAssociatedKinds, 371 "struct_constructors": self._GetStructConstructors, 372 "under_to_camel": generator.ToCamel, 373 "unmapped_type_for_serializer": self._GetUnmappedTypeForSerializer, 374 "use_custom_serializer": UseCustomSerializer, 375 "wtf_hash_fn_name_for_enum": GetWtfHashFnNameForEnum, 376 } 377 return cpp_filters 378 379 @UseJinja("module.h.tmpl") 380 def _GenerateModuleHeader(self): 381 return self._GetJinjaExports() 382 383 @UseJinja("module.cc.tmpl") 384 def _GenerateModuleSource(self): 385 return self._GetJinjaExports() 386 387 @UseJinja("module-shared.h.tmpl") 388 def _GenerateModuleSharedHeader(self): 389 return self._GetJinjaExports() 390 391 @UseJinja("module-shared-internal.h.tmpl") 392 def _GenerateModuleSharedInternalHeader(self): 393 return self._GetJinjaExports() 394 395 @UseJinja("module-shared-message-ids.h.tmpl") 396 def _GenerateModuleSharedMessageIdsHeader(self): 397 return self._GetJinjaExports() 398 399 @UseJinja("module-shared.cc.tmpl") 400 def _GenerateModuleSharedSource(self): 401 return self._GetJinjaExports() 402 403 def GenerateFiles(self, args): 404 self.module.Stylize(generator.Stylizer()) 405 406 if self.generate_non_variant_code: 407 if self.generate_message_ids: 408 self.Write(self._GenerateModuleSharedMessageIdsHeader(), 409 "%s-shared-message-ids.h" % self.module.path) 410 else: 411 self.Write(self._GenerateModuleSharedHeader(), 412 "%s-shared.h" % self.module.path) 413 self.Write(self._GenerateModuleSharedInternalHeader(), 414 "%s-shared-internal.h" % self.module.path) 415 self.Write(self._GenerateModuleSharedSource(), 416 "%s-shared.cc" % self.module.path) 417 else: 418 suffix = "-%s" % self.variant if self.variant else "" 419 self.Write(self._GenerateModuleHeader(), 420 "%s%s.h" % (self.module.path, suffix)) 421 self.Write(self._GenerateModuleSource(), 422 "%s%s.cc" % (self.module.path, suffix)) 423 424 def _ConstantValue(self, constant): 425 return self._ExpressionToText(constant.value, kind=constant.kind) 426 427 def _DefaultValue(self, field): 428 if not field.default: 429 return "" 430 431 if mojom.IsStructKind(field.kind): 432 assert field.default == "default" 433 if self._IsTypemappedKind(field.kind): 434 return "" 435 return "%s::New()" % self._GetNameForKind(field.kind) 436 437 expression = self._ExpressionToText(field.default, kind=field.kind) 438 if mojom.IsEnumKind(field.kind) and self._IsTypemappedKind(field.kind): 439 expression = "mojo::internal::ConvertEnumValue<%s, %s>(%s)" % ( 440 self._GetNameForKind(field.kind), self._GetCppWrapperType(field.kind), 441 expression) 442 return expression 443 444 def _GetNameForKind(self, kind, internal=False, flatten_nested_kind=False, 445 add_same_module_namespaces=False): 446 return _NameFormatter(kind, self.variant).FormatForCpp( 447 internal=internal, flatten_nested_kind=flatten_nested_kind, 448 omit_namespace_for_module = (None if add_same_module_namespaces 449 else self.module)) 450 451 def _GetQualifiedNameForKind(self, kind, internal=False, 452 flatten_nested_kind=False, include_variant=True): 453 return _NameFormatter( 454 kind, self.variant if include_variant else None).FormatForCpp( 455 internal=internal, flatten_nested_kind=flatten_nested_kind) 456 457 def _GetFullMojomNameForKind(self, kind): 458 return _NameFormatter(kind, self.variant).FormatForMojom() 459 460 def _IsTypemappedKind(self, kind): 461 return hasattr(kind, "name") and \ 462 self._GetFullMojomNameForKind(kind) in self.typemap 463 464 def _IsHashableKind(self, kind): 465 """Check if the kind can be hashed. 466 467 Args: 468 kind: {Kind} The kind to check. 469 470 Returns: 471 {bool} True if a value of this kind can be hashed. 472 """ 473 checked = set() 474 def Check(kind): 475 if kind.spec in checked: 476 return True 477 checked.add(kind.spec) 478 if mojom.IsNullableKind(kind): 479 return False 480 elif mojom.IsStructKind(kind): 481 if kind.native_only: 482 return False 483 if (self._IsTypemappedKind(kind) and 484 not self.typemap[self._GetFullMojomNameForKind(kind)]["hashable"]): 485 return False 486 return all(Check(field.kind) for field in kind.fields) 487 elif mojom.IsEnumKind(kind): 488 return not self._IsTypemappedKind(kind) or self.typemap[ 489 self._GetFullMojomNameForKind(kind)]["hashable"] 490 elif mojom.IsUnionKind(kind): 491 return all(Check(field.kind) for field in kind.fields) 492 elif mojom.IsAnyHandleKind(kind): 493 return False 494 elif mojom.IsAnyInterfaceKind(kind): 495 return False 496 # TODO(crbug.com/735301): Arrays and maps could be made hashable. We just 497 # don't have a use case yet. 498 elif mojom.IsArrayKind(kind): 499 return False 500 elif mojom.IsMapKind(kind): 501 return False 502 else: 503 return True 504 return Check(kind) 505 506 def _GetNativeTypeName(self, typemapped_kind): 507 return self.typemap[self._GetFullMojomNameForKind(typemapped_kind)][ 508 "typename"] 509 510 def _FormatConstantDeclaration(self, constant, nested=False): 511 if mojom.IsStringKind(constant.kind): 512 if nested: 513 return "const char %s[]" % constant.name 514 return "%sextern const char %s[]" % \ 515 ((self.export_attribute + " ") if self.export_attribute else "", 516 constant.name) 517 return "constexpr %s %s = %s" % ( 518 GetCppPodType(constant.kind), constant.name, 519 self._ConstantValue(constant)) 520 521 def _GetCppWrapperType(self, kind, add_same_module_namespaces=False): 522 def _AddOptional(type_name): 523 return "base::Optional<%s>" % type_name 524 525 if self._IsTypemappedKind(kind): 526 type_name = self._GetNativeTypeName(kind) 527 if (mojom.IsNullableKind(kind) and 528 not self.typemap[self._GetFullMojomNameForKind(kind)][ 529 "nullable_is_same_type"]): 530 type_name = _AddOptional(type_name) 531 return type_name 532 if mojom.IsEnumKind(kind): 533 return self._GetNameForKind( 534 kind, add_same_module_namespaces=add_same_module_namespaces) 535 if mojom.IsStructKind(kind) or mojom.IsUnionKind(kind): 536 return "%sPtr" % self._GetNameForKind( 537 kind, add_same_module_namespaces=add_same_module_namespaces) 538 if mojom.IsArrayKind(kind): 539 pattern = "WTF::Vector<%s>" if self.for_blink else "std::vector<%s>" 540 if mojom.IsNullableKind(kind): 541 pattern = _AddOptional(pattern) 542 return pattern % self._GetCppWrapperType( 543 kind.kind, add_same_module_namespaces=add_same_module_namespaces) 544 if mojom.IsMapKind(kind): 545 pattern = ("WTF::HashMap<%s, %s>" if self.for_blink else 546 "base::flat_map<%s, %s>") 547 if mojom.IsNullableKind(kind): 548 pattern = _AddOptional(pattern) 549 return pattern % ( 550 self._GetCppWrapperType( 551 kind.key_kind, 552 add_same_module_namespaces=add_same_module_namespaces), 553 self._GetCppWrapperType( 554 kind.value_kind, 555 add_same_module_namespaces=add_same_module_namespaces)) 556 if mojom.IsInterfaceKind(kind): 557 return "%sPtrInfo" % self._GetNameForKind( 558 kind, add_same_module_namespaces=add_same_module_namespaces) 559 if mojom.IsInterfaceRequestKind(kind): 560 return "%sRequest" % self._GetNameForKind( 561 kind.kind, add_same_module_namespaces=add_same_module_namespaces) 562 if mojom.IsAssociatedInterfaceKind(kind): 563 return "%sAssociatedPtrInfo" % self._GetNameForKind( 564 kind.kind, add_same_module_namespaces=add_same_module_namespaces) 565 if mojom.IsAssociatedInterfaceRequestKind(kind): 566 return "%sAssociatedRequest" % self._GetNameForKind( 567 kind.kind, add_same_module_namespaces=add_same_module_namespaces) 568 if mojom.IsStringKind(kind): 569 if self.for_blink: 570 return "WTF::String" 571 type_name = "std::string" 572 return (_AddOptional(type_name) if mojom.IsNullableKind(kind) 573 else type_name) 574 if mojom.IsGenericHandleKind(kind): 575 return "mojo::ScopedHandle" 576 if mojom.IsDataPipeConsumerKind(kind): 577 return "mojo::ScopedDataPipeConsumerHandle" 578 if mojom.IsDataPipeProducerKind(kind): 579 return "mojo::ScopedDataPipeProducerHandle" 580 if mojom.IsMessagePipeKind(kind): 581 return "mojo::ScopedMessagePipeHandle" 582 if mojom.IsSharedBufferKind(kind): 583 return "mojo::ScopedSharedBufferHandle" 584 if not kind in _kind_to_cpp_type: 585 raise Exception("Unrecognized kind %s" % kind.spec) 586 return _kind_to_cpp_type[kind] 587 588 def _IsMoveOnlyKind(self, kind): 589 if self._IsTypemappedKind(kind): 590 if mojom.IsEnumKind(kind): 591 return False 592 return self.typemap[self._GetFullMojomNameForKind(kind)]["move_only"] 593 if mojom.IsStructKind(kind) or mojom.IsUnionKind(kind): 594 return True 595 if mojom.IsArrayKind(kind): 596 return self._IsMoveOnlyKind(kind.kind) 597 if mojom.IsMapKind(kind): 598 return (self._IsMoveOnlyKind(kind.value_kind) or 599 self._IsMoveOnlyKind(kind.key_kind)) 600 if mojom.IsAnyHandleOrInterfaceKind(kind): 601 return True 602 return False 603 604 def _IsCopyablePassByValue(self, kind): 605 if not self._IsTypemappedKind(kind): 606 return False 607 return self.typemap[self._GetFullMojomNameForKind(kind)][ 608 "copyable_pass_by_value"] 609 610 def _ShouldPassParamByValue(self, kind): 611 return ((not mojom.IsReferenceKind(kind)) or self._IsMoveOnlyKind(kind) or 612 self._IsCopyablePassByValue(kind)) 613 614 def _GetCppWrapperCallType(self, kind): 615 # TODO: Remove this once interfaces are always passed as PtrInfo. 616 if mojom.IsInterfaceKind(kind): 617 return "%sPtr" % self._GetNameForKind(kind) 618 return self._GetCppWrapperType(kind) 619 620 def _GetCppWrapperParamType(self, kind): 621 # TODO: Remove all usage of this method in favor of 622 # _GetCppWrapperParamTypeNew. This requires all generated code which passes 623 # interface handles to use PtrInfo instead of Ptr. 624 if mojom.IsInterfaceKind(kind): 625 return "%sPtr" % self._GetNameForKind(kind) 626 cpp_wrapper_type = self._GetCppWrapperType(kind) 627 return (cpp_wrapper_type if self._ShouldPassParamByValue(kind) 628 else "const %s&" % cpp_wrapper_type) 629 630 def _GetCppWrapperParamTypeNew(self, kind): 631 cpp_wrapper_type = self._GetCppWrapperType(kind) 632 return (cpp_wrapper_type if self._ShouldPassParamByValue(kind) 633 else "const %s&" % cpp_wrapper_type) 634 635 def _GetCppFieldType(self, kind): 636 if mojom.IsStructKind(kind): 637 return ("mojo::internal::Pointer<%s>" % 638 self._GetNameForKind(kind, internal=True)) 639 if mojom.IsUnionKind(kind): 640 return "%s" % self._GetNameForKind(kind, internal=True) 641 if mojom.IsArrayKind(kind): 642 return ("mojo::internal::Pointer<mojo::internal::Array_Data<%s>>" % 643 self._GetCppFieldType(kind.kind)) 644 if mojom.IsMapKind(kind): 645 return ("mojo::internal::Pointer<mojo::internal::Map_Data<%s, %s>>" % 646 (self._GetCppFieldType(kind.key_kind), 647 self._GetCppFieldType(kind.value_kind))) 648 if mojom.IsInterfaceKind(kind): 649 return "mojo::internal::Interface_Data" 650 if mojom.IsInterfaceRequestKind(kind): 651 return "mojo::internal::Handle_Data" 652 if mojom.IsAssociatedInterfaceKind(kind): 653 return "mojo::internal::AssociatedInterface_Data" 654 if mojom.IsAssociatedInterfaceRequestKind(kind): 655 return "mojo::internal::AssociatedEndpointHandle_Data" 656 if mojom.IsEnumKind(kind): 657 return "int32_t" 658 if mojom.IsStringKind(kind): 659 return "mojo::internal::Pointer<mojo::internal::String_Data>" 660 if mojom.IsAnyHandleKind(kind): 661 return "mojo::internal::Handle_Data" 662 return _kind_to_cpp_type[kind] 663 664 def _GetCppUnionFieldType(self, kind): 665 if mojom.IsUnionKind(kind): 666 return ("mojo::internal::Pointer<%s>" % 667 self._GetNameForKind(kind, internal=True)) 668 return self._GetCppFieldType(kind) 669 670 def _GetUnionGetterReturnType(self, kind): 671 if mojom.IsReferenceKind(kind): 672 return "%s&" % self._GetCppWrapperType(kind) 673 return self._GetCppWrapperType(kind) 674 675 def _GetUnionTraitGetterReturnType(self, kind): 676 """Get field type used in UnionTraits template specialization. 677 678 The type may be qualified as UnionTraits specializations live outside the 679 namespace where e.g. structs are defined. 680 681 Args: 682 kind: {Kind} The type of the field. 683 684 Returns: 685 {str} The C++ type to use for the field. 686 """ 687 if mojom.IsReferenceKind(kind): 688 return "%s&" % self._GetCppWrapperType(kind, 689 add_same_module_namespaces=True) 690 return self._GetCppWrapperType(kind, add_same_module_namespaces=True) 691 692 def _KindMustBeSerialized(self, kind, processed_kinds=None): 693 if not processed_kinds: 694 processed_kinds = set() 695 if kind in processed_kinds: 696 return False 697 698 if (self._IsTypemappedKind(kind) and 699 self.typemap[self._GetFullMojomNameForKind(kind)]["force_serialize"]): 700 return True 701 702 processed_kinds.add(kind) 703 704 if mojom.IsStructKind(kind) or mojom.IsUnionKind(kind): 705 return any(self._KindMustBeSerialized(field.kind, 706 processed_kinds=processed_kinds) 707 for field in kind.fields) 708 709 return False 710 711 def _MethodSupportsLazySerialization(self, method): 712 if not self.support_lazy_serialization: 713 return False 714 715 # TODO(crbug.com/753433): Support lazy serialization for methods which pass 716 # associated handles. 717 if mojom.MethodPassesAssociatedKinds(method): 718 return False 719 720 return not any(self._KindMustBeSerialized(param.kind) for param in 721 method.parameters + (method.response_parameters or [])) 722 723 def _TranslateConstants(self, token, kind): 724 if isinstance(token, mojom.NamedValue): 725 return self._GetNameForKind(token, flatten_nested_kind=True) 726 727 if isinstance(token, mojom.BuiltinValue): 728 if token.value == "double.INFINITY": 729 return "std::numeric_limits<double>::infinity()" 730 if token.value == "float.INFINITY": 731 return "std::numeric_limits<float>::infinity()" 732 if token.value == "double.NEGATIVE_INFINITY": 733 return "-std::numeric_limits<double>::infinity()" 734 if token.value == "float.NEGATIVE_INFINITY": 735 return "-std::numeric_limits<float>::infinity()" 736 if token.value == "double.NAN": 737 return "std::numeric_limits<double>::quiet_NaN()" 738 if token.value == "float.NAN": 739 return "std::numeric_limits<float>::quiet_NaN()" 740 741 if (kind is not None and mojom.IsFloatKind(kind)): 742 return token if token.isdigit() else token + "f"; 743 744 # Per C++11, 2.14.2, the type of an integer literal is the first of the 745 # corresponding list in Table 6 in which its value can be represented. In 746 # this case, the list for decimal constants with no suffix is: 747 # int, long int, long long int 748 # The standard considers a program ill-formed if it contains an integer 749 # literal that cannot be represented by any of the allowed types. 750 # 751 # As it turns out, MSVC doesn't bother trying to fall back to long long int, 752 # so the integral constant -2147483648 causes it grief: it decides to 753 # represent 2147483648 as an unsigned integer, and then warns that the unary 754 # minus operator doesn't make sense on unsigned types. Doh! 755 if kind == mojom.INT32 and token == "-2147483648": 756 return "(-%d - 1) /* %s */" % ( 757 2**31 - 1, "Workaround for MSVC bug; see https://crbug.com/445618") 758 759 return "%s%s" % (token, _kind_to_cpp_literal_suffix.get(kind, "")) 760 761 def _ExpressionToText(self, value, kind=None): 762 return self._TranslateConstants(value, kind) 763 764 def _ContainsMoveOnlyMembers(self, struct): 765 for field in struct.fields: 766 if self._IsMoveOnlyKind(field.kind): 767 return True 768 return False 769 770 def _GetStructConstructors(self, struct): 771 """Returns a list of constructors for a struct. 772 773 Params: 774 struct: {Struct} The struct to return constructors for. 775 776 Returns: 777 {[StructConstructor]} A list of StructConstructors that should be 778 generated for |struct|. 779 """ 780 if not mojom.IsStructKind(struct): 781 raise TypeError 782 # Types that are neither copyable nor movable can't be passed to a struct 783 # constructor so only generate a default constructor. 784 if any(self._IsTypemappedKind(field.kind) and self.typemap[ 785 self._GetFullMojomNameForKind(field.kind)]["non_copyable_non_movable"] 786 for field in struct.fields): 787 return [StructConstructor(struct.fields, [])] 788 789 param_counts = [0] 790 for version in struct.versions: 791 if param_counts[-1] != version.num_fields: 792 param_counts.append(version.num_fields) 793 794 ordinal_fields = sorted(struct.fields, key=lambda field: field.ordinal if field.ordinal != None else -1) 795 return (StructConstructor(struct.fields, ordinal_fields[:param_count]) 796 for param_count in param_counts) 797 798 def _GetContainerValidateParamsCtorArgs(self, kind): 799 if mojom.IsStringKind(kind): 800 expected_num_elements = 0 801 element_is_nullable = False 802 key_validate_params = "nullptr" 803 element_validate_params = "nullptr" 804 enum_validate_func = "nullptr" 805 elif mojom.IsMapKind(kind): 806 expected_num_elements = 0 807 element_is_nullable = False 808 key_validate_params = self._GetNewContainerValidateParams(mojom.Array( 809 kind=kind.key_kind)) 810 element_validate_params = self._GetNewContainerValidateParams(mojom.Array( 811 kind=kind.value_kind)) 812 enum_validate_func = "nullptr" 813 else: # mojom.IsArrayKind(kind) 814 expected_num_elements = generator.ExpectedArraySize(kind) or 0 815 element_is_nullable = mojom.IsNullableKind(kind.kind) 816 key_validate_params = "nullptr" 817 element_validate_params = self._GetNewContainerValidateParams(kind.kind) 818 if mojom.IsEnumKind(kind.kind): 819 enum_validate_func = ("%s::Validate" % 820 self._GetQualifiedNameForKind(kind.kind, internal=True, 821 flatten_nested_kind=True)) 822 else: 823 enum_validate_func = "nullptr" 824 825 if enum_validate_func == "nullptr": 826 if key_validate_params == "nullptr": 827 return "%d, %s, %s" % (expected_num_elements, 828 "true" if element_is_nullable else "false", 829 element_validate_params) 830 else: 831 return "%s, %s" % (key_validate_params, element_validate_params) 832 else: 833 return "%d, %s" % (expected_num_elements, enum_validate_func) 834 835 def _GetNewContainerValidateParams(self, kind): 836 if (not mojom.IsArrayKind(kind) and not mojom.IsMapKind(kind) and 837 not mojom.IsStringKind(kind)): 838 return "nullptr" 839 840 return "new mojo::internal::ContainerValidateParams(%s)" % ( 841 self._GetContainerValidateParamsCtorArgs(kind)) 842 843 def _GetCppDataViewType(self, kind, qualified=False): 844 def _GetName(input_kind): 845 return _NameFormatter(input_kind, None).FormatForCpp( 846 omit_namespace_for_module=(None if qualified else self.module), 847 flatten_nested_kind=True) 848 849 if mojom.IsEnumKind(kind): 850 return _GetName(kind) 851 if mojom.IsStructKind(kind) or mojom.IsUnionKind(kind): 852 return "%sDataView" % _GetName(kind) 853 if mojom.IsArrayKind(kind): 854 return "mojo::ArrayDataView<%s>" % ( 855 self._GetCppDataViewType(kind.kind, qualified)) 856 if mojom.IsMapKind(kind): 857 return ("mojo::MapDataView<%s, %s>" % ( 858 self._GetCppDataViewType(kind.key_kind, qualified), 859 self._GetCppDataViewType(kind.value_kind, qualified))) 860 if mojom.IsStringKind(kind): 861 return "mojo::StringDataView" 862 if mojom.IsInterfaceKind(kind): 863 return "%sPtrDataView" % _GetName(kind) 864 if mojom.IsInterfaceRequestKind(kind): 865 return "%sRequestDataView" % _GetName(kind.kind) 866 if mojom.IsAssociatedInterfaceKind(kind): 867 return "%sAssociatedPtrInfoDataView" % _GetName(kind.kind) 868 if mojom.IsAssociatedInterfaceRequestKind(kind): 869 return "%sAssociatedRequestDataView" % _GetName(kind.kind) 870 if mojom.IsGenericHandleKind(kind): 871 return "mojo::ScopedHandle" 872 if mojom.IsDataPipeConsumerKind(kind): 873 return "mojo::ScopedDataPipeConsumerHandle" 874 if mojom.IsDataPipeProducerKind(kind): 875 return "mojo::ScopedDataPipeProducerHandle" 876 if mojom.IsMessagePipeKind(kind): 877 return "mojo::ScopedMessagePipeHandle" 878 if mojom.IsSharedBufferKind(kind): 879 return "mojo::ScopedSharedBufferHandle" 880 return _kind_to_cpp_type[kind] 881 882 def _GetUnmappedTypeForSerializer(self, kind): 883 return self._GetCppDataViewType(kind, qualified=True) 884