def TranslateConstants(token, kind): if isinstance(token, mojom.NamedValue): # Both variable and enum constants are constructed like: # Namespace::Struct::CONSTANT_NAME # For enums, CONSTANT_NAME is ENUM_NAME_ENUM_VALUE. name = [] if token.imported_from: name.extend(NamespaceToArray(token.namespace)) if token.parent_kind: name.append(token.parent_kind.name) if isinstance(token, mojom.EnumValue): name.append( "%s_%s" % (generator.CamelCaseToAllCaps(token.enum.name), token.name)) else: name.append(token.name) return "::".join(name) if isinstance(token, mojom.BuiltinValue): if token.value == "double.INFINITY" or token.value == "float.INFINITY": return "INFINITY" if token.value == "double.NEGATIVE_INFINITY" or \ token.value == "float.NEGATIVE_INFINITY": return "-INFINITY" if token.value == "double.NAN" or token.value == "float.NAN": return "NAN" if (kind is not None and mojom.IsFloatKind(kind)): return token if token.isdigit() else token + "f" return '%s%s' % (token, _kind_to_cpp_literal_suffix.get(kind, ''))
def TranslateConstants(token, kind): if isinstance(token, mojom.NamedValue): return _NameFormatter(token, _variant).FormatForCpp() if isinstance(token, mojom.BuiltinValue): if token.value == "double.INFINITY" or token.value == "float.INFINITY": return "INFINITY" if token.value == "double.NEGATIVE_INFINITY" or \ token.value == "float.NEGATIVE_INFINITY": return "-INFINITY" if token.value == "double.NAN" or token.value == "float.NAN": return "NAN" if (kind is not None and mojom.IsFloatKind(kind)): return token if token.isdigit() else token + "f" # Per C++11, 2.14.2, the type of an integer literal is the first of the # corresponding list in Table 6 in which its value can be represented. In this # case, the list for decimal constants with no suffix is: # int, long int, long long int # The standard considers a program ill-formed if it contains an integer # literal that cannot be represented by any of the allowed types. # # As it turns out, MSVC doesn't bother trying to fall back to long long int, # so the integral constant -2147483648 causes it grief: it decides to # represent 2147483648 as an unsigned integer, and then warns that the unary # minus operator doesn't make sense on unsigned types. Doh! if kind == mojom.INT32 and token == "-2147483648": return "(-%d - 1) /* %s */" % ( 2**31 - 1, "Workaround for MSVC bug; see https://crbug.com/445618") return "%s%s" % (token, _kind_to_cpp_literal_suffix.get(kind, ""))
def AddKind(kind): if (mojom.IsIntegralKind(kind) or mojom.IsStringKind(kind) or mojom.IsDoubleKind(kind) or mojom.IsFloatKind(kind) or mojom.IsAnyHandleKind(kind) or mojom.IsInterfaceKind(kind) or mojom.IsInterfaceRequestKind(kind) or mojom.IsAssociatedKind(kind) or mojom.IsPendingRemoteKind(kind) or mojom.IsPendingReceiverKind(kind)): pass elif mojom.IsArrayKind(kind): AddKind(kind.kind) elif mojom.IsMapKind(kind): AddKind(kind.key_kind) AddKind(kind.value_kind) else: name = self._GetFullMojomNameForKind(kind) if name in seen_types: return seen_types.add(name) typemap = self.typemap.get(name, None) if typemap: used_typemaps.append(typemap) if mojom.IsStructKind(kind) or mojom.IsUnionKind(kind): for field in kind.fields: AddKind(field.kind)
def AddKind(kind): if (mojom.IsIntegralKind(kind) or mojom.IsStringKind(kind) or mojom.IsDoubleKind(kind) or mojom.IsFloatKind(kind)): pass elif (mojom.IsAnyHandleKind(kind)): self.needs_mojolpm_proto = True elif mojom.IsArrayKind(kind): AddKind(kind.kind) elif mojom.IsMapKind(kind): AddKind(kind.key_kind) AddKind(kind.value_kind) elif (mojom.IsStructKind(kind) or mojom.IsUnionKind(kind) or mojom.IsEnumKind(kind) or mojom.IsInterfaceKind(kind)): name = self._GetFullMojomNameForKind(kind) if name in seen_types: return seen_types.add(name) if kind.module in all_imports: seen_imports.add(kind.module) elif (mojom.IsInterfaceRequestKind(kind) or mojom.IsAssociatedInterfaceKind(kind) or mojom.IsAssociatedInterfaceRequestKind(kind) or mojom.IsPendingRemoteKind(kind) or mojom.IsPendingReceiverKind(kind) or mojom.IsPendingAssociatedRemoteKind(kind) or mojom.IsPendingAssociatedReceiverKind(kind)): AddKind(kind.kind)
def _IsStringableKind(self, kind): # Indicates whether a kind of suitable to stringify and use as an Object # property name. This is checked for map key types to allow most kinds of # mojom maps to be represented as either a Map or an Object. return (mojom.IsIntegralKind(kind) or mojom.IsFloatKind(kind) or mojom.IsDoubleKind(kind) or mojom.IsStringKind(kind) or mojom.IsEnumKind(kind))
def IsBasicKind(kind): return (mojom.IsIntegralKind(kind) or mojom.IsStringKind(kind) or mojom.IsDoubleKind(kind) or mojom.IsFloatKind(kind) or mojom.IsAnyHandleKind(kind) or mojom.IsInterfaceKind(kind) or mojom.IsInterfaceRequestKind(kind) or mojom.IsAssociatedKind(kind))
def _WriteInputParamForTracing(self, kind, mojo_prefix, parameter_name, value): """Generates lines of C++ to log parameter |parameter_name| into TracedValue |value|. Args: kind: {Kind} The kind of the parameter (corresponds to its C++ type). mojo_prefix: {string} The prefix of the auto-generated parameter. parameter_name: {string} The mojom parameter name to be logged (auto-generated C++ parameter name is |mojo_prefix+parameter_name|). value: {string} The C++ TracedValue* variable name to be logged into. Yields: {string} C++ lines of code that trace |parameter_name| into |value|. """ cpp_parameter_name = mojo_prefix + parameter_name value_name_cppname = (value, parameter_name, cpp_parameter_name) # TODO(crbug.com/1103623): Support more involved types. if mojom.IsEnumKind(kind): # TODO(crbug.com/1103623): Pretty-print enums. yield '%s->SetInteger("%s", static_cast<int>(%s));' % value_name_cppname return if mojom.IsStringKind(kind): if self.for_blink: # WTF::String is nullable on its own. yield '%s->SetString("%s", %s.Utf8());' % value_name_cppname return if mojom.IsNullableKind(kind): # base::Optional<std::string> yield 'if (%s.has_value()) {' % cpp_parameter_name yield ' %s->SetString("%s", %s.value());' % value_name_cppname yield '} else {' yield ' %s->SetString("%s", "base::nullopt");' % ( value, parameter_name) yield '}' return else: yield '%s->SetString("%s", %s);' % value_name_cppname return if kind == mojom.BOOL: yield '%s->SetBoolean("%s", %s);' % value_name_cppname return # TODO(crbug.com/1103623): Make TracedValue support int64_t, then move to # mojom.IsIntegralKind. if kind in [ mojom.INT8, mojom.UINT8, mojom.INT16, mojom.UINT16, mojom.INT32 ]: # Parameter is representable as 32bit int. yield '%s->SetInteger("%s", %s);' % value_name_cppname return if kind in [mojom.UINT32, mojom.INT64, mojom.UINT64]: yield '%s->SetString("%s", std::to_string(%s));' % value_name_cppname return if mojom.IsFloatKind(kind) or mojom.IsDoubleKind(kind): yield '%s->SetDouble("%s", %s);' % value_name_cppname return yield '%s->SetString("%s", "<value of type %s>");' % ( value, parameter_name, self._GetCppWrapperParamType(kind))
def _IsStringableKind(self, kind): # Indicates whether a kind of suitable to stringify and use as an Object # property name. This is checked for map key types to allow most kinds of # mojom maps to be represented as either a Map or an Object. if kind == mojom.INT64 or kind == mojom.UINT64: # JS BigInts are not stringable and cannot be used as Object property # names. return False return (mojom.IsIntegralKind(kind) or mojom.IsFloatKind(kind) or mojom.IsDoubleKind(kind) or mojom.IsStringKind(kind) or mojom.IsEnumKind(kind))
def TranslateConstants(token, kind): if isinstance(token, mojom.NamedValue): # Both variable and enum constants are constructed like: # Namespace::Struct::CONSTANT_NAME # For enums, CONSTANT_NAME is ENUM_NAME_ENUM_VALUE. name = [] if token.imported_from: name.extend(NamespaceToArray(token.namespace)) if token.parent_kind: name.append(token.parent_kind.name) if isinstance(token, mojom.EnumValue): name.append( "%s_%s" % (generator.CamelCaseToAllCaps(token.enum.name), token.name)) else: name.append(token.name) return "::".join(name) if isinstance(token, mojom.BuiltinValue): if token.value == "double.INFINITY" or token.value == "float.INFINITY": return "INFINITY" if token.value == "double.NEGATIVE_INFINITY" or \ token.value == "float.NEGATIVE_INFINITY": return "-INFINITY" if token.value == "double.NAN" or token.value == "float.NAN": return "NAN" if (kind is not None and mojom.IsFloatKind(kind)): return token if token.isdigit() else token + "f" # Per C++11, 2.14.2, the type of an integer literal is the first of the # corresponding list in Table 6 in which its value can be represented. In this # case, the list for decimal constants with no suffix is: # int, long int, long long int # The standard considers a program ill-formed if it contains an integer # literal that cannot be represented by any of the allowed types. # # As it turns out, MSVC doesn't bother trying to fall back to long long int, # so the integral constant -2147483648 causes it grief: it decides to # represent 2147483648 as an unsigned integer, and then warns that the unary # minus operator doesn't make sense on unsigned types. Doh! if kind == mojom.INT32 and token == "-2147483648": return "(-%d - 1) /* %s */" % ( 2**31 - 1, "Workaround for MSVC bug; see https://crbug.com/445618") return "%s%s" % (token, _kind_to_cpp_literal_suffix.get(kind, ""))
def _TranslateConstants(self, token, kind): if isinstance(token, mojom.NamedValue): return self._GetNameForKind(token, flatten_nested_kind=True) if isinstance(token, mojom.BuiltinValue): if token.value == "double.INFINITY": return "std::numeric_limits<double>::infinity()" if token.value == "float.INFINITY": return "std::numeric_limits<float>::infinity()" if token.value == "double.NEGATIVE_INFINITY": return "-std::numeric_limits<double>::infinity()" if token.value == "float.NEGATIVE_INFINITY": return "-std::numeric_limits<float>::infinity()" if token.value == "double.NAN": return "std::numeric_limits<double>::quiet_NaN()" if token.value == "float.NAN": return "std::numeric_limits<float>::quiet_NaN()" if (kind is not None and mojom.IsFloatKind(kind)): return token if token.isdigit() else token + "f" return "%s%s" % (token, _kind_to_cpp_literal_suffix.get(kind, ""))
def _WriteInputParamForTracingImpl(generator, kind, cpp_parameter_name, output_context): """Generates lines of C++ to log a parameter into TracedValue |output_context.value|. Use |output_context.name| if |output_context| is of inhereted type from _OutputContext. Args: kind: {Kind} The kind of the parameter (corresponds to its C++ type). cpp_parameter_name: {string} The actual C++ variable name corresponding to the mojom parameter |parameter_name|. Can be a valid C++ expression (e.g., dereferenced variable |"(*var)"|). output_context: {_OutputContext} Represents the TracedValue* variable to be written into. Possibly also holds the mojo parameter name corresponding to |cpp_parameter_name|. Yields: {string} C++ lines of code that trace a |cpp_parameter_name| into |output_context.value|. """ def _WrapIfNullable(inner_lines): """Check if kind is nullable if so yield code to check whether it has value. Args: inner_lines: {function} Function taking single argument and returning iterable. If kind is nullable, yield from this method with |cpp_parameter_name+'.value()'| otherwise yield with the parameter |cpp_parameter_name|. Args from the surrounding method: kind cpp_parameter_name output_context.AddSingleValue """ if mojom.IsNullableKind(kind): yield 'if (%s.has_value()) {' % cpp_parameter_name for line in inner_lines(cpp_parameter_name + '.value()'): yield ' ' + line yield '} else {' yield ' ' + output_context.AddSingleValue('String', '"base::nullopt"') yield '}' else: # |yield from| is introduced in Python3.3. for line in inner_lines(cpp_parameter_name): yield line # TODO(crbug.com/1103623): Support more involved types. if mojom.IsEnumKind(kind): if generator._IsTypemappedKind(kind) or IsNativeOnlyKind(kind): yield output_context.AddSingleValue( 'Integer', 'static_cast<int>(%s)' % cpp_parameter_name) else: yield output_context.AddSingleValue( 'String', 'base::trace_event::ValueToString(%s)' % cpp_parameter_name) return if mojom.IsStringKind(kind): if generator.for_blink: # WTF::String is nullable on its own. yield output_context.AddSingleValue('String', '%s.Utf8()' % cpp_parameter_name) return # The type might be base::Optional<std::string> or std::string. for line in _WrapIfNullable(lambda cpp_parameter_name: [ output_context.AddSingleValue('String', cpp_parameter_name) ]): yield line return if kind == mojom.BOOL: yield output_context.AddSingleValue('Boolean', cpp_parameter_name) return # TODO(crbug.com/1103623): Make TracedValue support int64_t, then move to # mojom.IsIntegralKind. if kind in [mojom.INT8, mojom.UINT8, mojom.INT16, mojom.UINT16, mojom.INT32]: # Parameter is representable as 32bit int. yield output_context.AddSingleValue('Integer', cpp_parameter_name) return if kind in [mojom.UINT32, mojom.INT64, mojom.UINT64]: yield output_context.AddSingleValue( 'String', 'base::NumberToString(%s)' % cpp_parameter_name) return if mojom.IsFloatKind(kind) or mojom.IsDoubleKind(kind): yield output_context.AddSingleValue('Double', cpp_parameter_name) return if (mojom.IsStructKind(kind) and not generator._IsTypemappedKind(kind) and not IsNativeOnlyKind(kind)): yield 'if (%s.is_null()) {' % cpp_parameter_name yield ' ' + output_context.AddSingleValue('String', '"nullptr"') yield '} else {' yield ' ' + output_context.BeginContainer('Dictionary') yield ' ' + output_context.AsValueInto(cpp_parameter_name) yield ' ' + output_context.EndContainer('Dictionary') yield '}' return if mojom.IsArrayKind(kind): iterator_name = 'item' loop_body = _WriteInputParamForTracingImpl(generator=generator, kind=kind.kind, cpp_parameter_name=iterator_name, output_context=_ArrayItem( output_context.value)) loop_generator = lambda cpp_parameter_name: output_context.TraceContainer( container_type='Array', iterator_name=iterator_name, container_name=cpp_parameter_name, loop_body=loop_body) # Array might be a nullable kind. for line in _WrapIfNullable(loop_generator): yield line return def _TraceEventToString(cpp_parameter_name=cpp_parameter_name, kind=kind): return 'base::trace_event::ValueToString(%s, "<value of type %s>")' % ( cpp_parameter_name, generator._GetCppWrapperParamType(kind)) if mojom.IsMapKind(kind): iterator_name = 'item' if generator.for_blink: # WTF::HashMap<,> key_access = '.key' value_access = '.value' else: # base::flat_map<,> key_access = '.first' value_access = '.second' loop_body = _WriteInputParamForTracingImpl( generator=generator, kind=kind.value_kind, cpp_parameter_name=iterator_name + value_access, output_context=_DictionaryItemWithCopiedKey( value=output_context.value, name=_TraceEventToString(cpp_parameter_name=iterator_name + key_access, kind=kind.key_kind))) loop_generator = lambda cpp_parameter_name: output_context.TraceContainer( container_type="Dictionary", iterator_name=iterator_name, container_name=cpp_parameter_name, loop_body=loop_body) # Dictionary might be a nullable kind. for line in _WrapIfNullable(loop_generator): yield line return if (mojom.IsInterfaceRequestKind(kind) or mojom.IsAssociatedInterfaceRequestKind(kind)): yield output_context.AddSingleValue('Boolean', cpp_parameter_name + '.is_pending()') return if (mojom.IsAnyHandleOrInterfaceKind(kind) and not mojom.IsInterfaceKind(kind)): yield output_context.AddSingleValue('Boolean', cpp_parameter_name + '.is_valid()') return """ The case |mojom.IsInterfaceKind(kind)| is not covered. |mojom.IsInterfaceKind(kind) == True| for the following types: |mojo::InterfacePtrInfo|, |mojo::InterfacePtr|. There is |mojo::InterfacePtrInfo::is_valid|, but not |mojo::InterfacePtrInfo::is_bound|. There is |mojo::InterfacePtr::is_bound|, but not |mojo::InterfacePtr::is_valid|. Both |mojo::InterfacePtrInfo| and |mojo::InterfacePtr| are deprecated. """ yield output_context.AddSingleValue('String', _TraceEventToString())
def TranslateConstants(token, kind): if isinstance(token, mojom.NamedValue): # Both variable and enum constants are constructed like: # Namespace::Struct::CONSTANT_NAME # For enums, CONSTANT_NAME is ENUM_NAME_ENUM_VALUE. name = [] if token.imported_from: name.extend(NamespaceToArray(token.namespace)) if token.parent_kind: name.append(token.parent_kind.name) if IsEnumToken(token): name.extend([token.enum.name, token.name]) else: name.append(token.name) ret = "::".join(name) # Explicitly disallow cases where we are translating an enum token for a # non-enum (but defined) kind. if IsEnumToken( token) and kind is not None and not mojom.IsEnumKind(kind): raise Exception( "Assignment of enum value '%s' to type %s is disallowed" % (ret, _kind_to_cpp_type.get(kind, "<unknown>"))) # Explicitly disallow a non-enum token for an enum kind, we need an explicit # cast. if not IsEnumToken(token) and mojom.IsEnumKind(kind): raise Exception( "Assignment of non-enum value '%s' to enum-type %s is disallowed" % (ret, GetNameForKind(kind))) return ret if isinstance(token, mojom.BuiltinValue): if token.value == "double.INFINITY" or token.value == "float.INFINITY": return "INFINITY" if token.value == "double.NEGATIVE_INFINITY" or \ token.value == "float.NEGATIVE_INFINITY": return "-INFINITY" if token.value == "double.NAN" or token.value == "float.NAN": return "NAN" if (kind is not None and mojom.IsFloatKind(kind)): return token if token.isdigit() else token + "f" # Per C++11, 2.14.2, the type of an integer literal is the first of the # corresponding list in Table 6 in which its value can be represented. In this # case, the list for decimal constants with no suffix is: # int, long int, long long int # The standard considers a program ill-formed if it contains an integer # literal that cannot be represented by any of the allowed types. # # As it turns out, MSVC doesn't bother trying to fall back to long long int, # so the integral constant -2147483648 causes it grief: it decides to # represent 2147483648 as an unsigned integer, and then warns that the unary # minus operator doesn't make sense on unsigned types. Doh! if kind == mojom.INT32 and token == "-2147483648": return "(-%d - 1) /* %s */" % ( 2**31 - 1, "Workaround for MSVC bug; see https://crbug.com/445618") ret = "%s%s" % (token, _kind_to_cpp_literal_suffix.get(kind, "")) # Literal tokens may not be assigned to enum variable. By definition, the # only valid tokens for the RHS of an assignment to an enum named values # (specifically, members of the enumeration). if mojom.IsEnumKind(kind): raise Exception( "Assignment of literal '%s' to enum-type %s is disallowed" % (ret, GetNameForKind(kind))) return ret
def _IsObjCNumberKind(self, kind): return (mojom.IsIntegralKind(kind) or mojom.IsDoubleKind(kind) or mojom.IsFloatKind(kind))