| 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 |