Home | History | Annotate | Download | only in generate
      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 # This module's classes provide an interface to mojo modules. Modules are
      6 # collections of interfaces and structs to be used by mojo ipc clients and
      7 # servers.
      8 #
      9 # A simple interface would be created this way:
     10 # module = mojom.generate.module.Module('Foo')
     11 # interface = module.AddInterface('Bar')
     12 # method = interface.AddMethod('Tat', 0)
     13 # method.AddParameter('baz', 0, mojom.INT32)
     14 
     15 # We use our own version of __repr__ when displaying the AST, as the
     16 # AST currently doesn't capture which nodes are reference (e.g. to
     17 # types) and which nodes are definitions. This allows us to e.g. print
     18 # the definition of a struct when it's defined inside a module, but
     19 # only print its name when it's referenced in e.g. a method parameter.
     20 def Repr(obj, as_ref=True):
     21   """A version of __repr__ that can distinguish references.
     22 
     23   Sometimes we like to print an object's full representation
     24   (e.g. with its fields) and sometimes we just want to reference an
     25   object that was printed in full elsewhere. This function allows us
     26   to make that distinction.
     27 
     28   Args:
     29     obj: The object whose string representation we compute.
     30     as_ref: If True, use the short reference representation.
     31 
     32   Returns:
     33     A str representation of |obj|.
     34   """
     35   if hasattr(obj, 'Repr'):
     36     return obj.Repr(as_ref=as_ref)
     37   # Since we cannot implement Repr for existing container types, we
     38   # handle them here.
     39   elif isinstance(obj, list):
     40     if not obj:
     41       return '[]'
     42     else:
     43       return ('[\n%s\n]' % (',\n'.join('    %s' % Repr(elem, as_ref).replace(
     44           '\n', '\n    ') for elem in obj)))
     45   elif isinstance(obj, dict):
     46     if not obj:
     47       return '{}'
     48     else:
     49       return ('{\n%s\n}' % (',\n'.join('    %s: %s' % (
     50           Repr(key, as_ref).replace('\n', '\n    '),
     51           Repr(val, as_ref).replace('\n', '\n    '))
     52           for key, val in obj.iteritems())))
     53   else:
     54     return repr(obj)
     55 
     56 
     57 def GenericRepr(obj, names):
     58   """Compute generic Repr for |obj| based on the attributes in |names|.
     59 
     60   Args:
     61     obj: The object to compute a Repr for.
     62     names: A dict from attribute names to include, to booleans
     63         specifying whether those attributes should be shown as
     64         references or not.
     65 
     66   Returns:
     67     A str representation of |obj|.
     68   """
     69   def ReprIndent(name, as_ref):
     70     return '    %s=%s' % (name, Repr(getattr(obj, name), as_ref).replace(
     71         '\n', '\n    '))
     72 
     73   return '%s(\n%s\n)' % (
     74       obj.__class__.__name__,
     75       ',\n'.join(ReprIndent(name, as_ref)
     76                  for (name, as_ref) in names.iteritems()))
     77 
     78 
     79 class Kind(object):
     80   """Kind represents a type (e.g. int8, string).
     81 
     82   Attributes:
     83     spec: A string uniquely identifying the type. May be None.
     84     module: {Module} The defining module. Set to None for built-in types.
     85     parent_kind: The enclosing type. For example, an enum defined
     86         inside an interface has that interface as its parent. May be None.
     87   """
     88   def __init__(self, spec=None, module=None):
     89     self.spec = spec
     90     self.module = module
     91     self.parent_kind = None
     92 
     93   def Repr(self, as_ref=True):
     94     return '<%s spec=%r>' % (self.__class__.__name__, self.spec)
     95 
     96   def __repr__(self):
     97     # Gives us a decent __repr__ for all kinds.
     98     return self.Repr()
     99 
    100 
    101 class ReferenceKind(Kind):
    102   """ReferenceKind represents pointer and handle types.
    103 
    104   A type is nullable if null (for pointer types) or invalid handle (for handle
    105   types) is a legal value for the type.
    106 
    107   Attributes:
    108     is_nullable: True if the type is nullable.
    109   """
    110   def __init__(self, spec=None, is_nullable=False, module=None):
    111     assert spec is None or is_nullable == spec.startswith('?')
    112     Kind.__init__(self, spec, module)
    113     self.is_nullable = is_nullable
    114     self.shared_definition = {}
    115 
    116   def Repr(self, as_ref=True):
    117     return '<%s spec=%r is_nullable=%r>' % (self.__class__.__name__, self.spec,
    118                                             self.is_nullable)
    119 
    120   def MakeNullableKind(self):
    121     assert not self.is_nullable
    122 
    123     if self == STRING:
    124       return NULLABLE_STRING
    125     if self == HANDLE:
    126       return NULLABLE_HANDLE
    127     if self == DCPIPE:
    128       return NULLABLE_DCPIPE
    129     if self == DPPIPE:
    130       return NULLABLE_DPPIPE
    131     if self == MSGPIPE:
    132       return NULLABLE_MSGPIPE
    133     if self == SHAREDBUFFER:
    134       return NULLABLE_SHAREDBUFFER
    135 
    136     nullable_kind = type(self)()
    137     nullable_kind.shared_definition = self.shared_definition
    138     if self.spec is not None:
    139       nullable_kind.spec = '?' + self.spec
    140     nullable_kind.is_nullable = True
    141     nullable_kind.parent_kind = self.parent_kind
    142     nullable_kind.module = self.module
    143 
    144     return nullable_kind
    145 
    146   @classmethod
    147   def AddSharedProperty(cls, name):
    148     """Adds a property |name| to |cls|, which accesses the corresponding item in
    149        |shared_definition|.
    150 
    151        The reason of adding such indirection is to enable sharing definition
    152        between a reference kind and its nullable variation. For example:
    153          a = Struct('test_struct_1')
    154          b = a.MakeNullableKind()
    155          a.name = 'test_struct_2'
    156          print b.name  # Outputs 'test_struct_2'.
    157     """
    158     def Get(self):
    159       return self.shared_definition[name]
    160 
    161     def Set(self, value):
    162       self.shared_definition[name] = value
    163 
    164     setattr(cls, name, property(Get, Set))
    165 
    166 
    167 # Initialize the set of primitive types. These can be accessed by clients.
    168 BOOL                  = Kind('b')
    169 INT8                  = Kind('i8')
    170 INT16                 = Kind('i16')
    171 INT32                 = Kind('i32')
    172 INT64                 = Kind('i64')
    173 UINT8                 = Kind('u8')
    174 UINT16                = Kind('u16')
    175 UINT32                = Kind('u32')
    176 UINT64                = Kind('u64')
    177 FLOAT                 = Kind('f')
    178 DOUBLE                = Kind('d')
    179 STRING                = ReferenceKind('s')
    180 HANDLE                = ReferenceKind('h')
    181 DCPIPE                = ReferenceKind('h:d:c')
    182 DPPIPE                = ReferenceKind('h:d:p')
    183 MSGPIPE               = ReferenceKind('h:m')
    184 SHAREDBUFFER          = ReferenceKind('h:s')
    185 NULLABLE_STRING       = ReferenceKind('?s', True)
    186 NULLABLE_HANDLE       = ReferenceKind('?h', True)
    187 NULLABLE_DCPIPE       = ReferenceKind('?h:d:c', True)
    188 NULLABLE_DPPIPE       = ReferenceKind('?h:d:p', True)
    189 NULLABLE_MSGPIPE      = ReferenceKind('?h:m', True)
    190 NULLABLE_SHAREDBUFFER = ReferenceKind('?h:s', True)
    191 
    192 
    193 # Collection of all Primitive types
    194 PRIMITIVES = (
    195   BOOL,
    196   INT8,
    197   INT16,
    198   INT32,
    199   INT64,
    200   UINT8,
    201   UINT16,
    202   UINT32,
    203   UINT64,
    204   FLOAT,
    205   DOUBLE,
    206   STRING,
    207   HANDLE,
    208   DCPIPE,
    209   DPPIPE,
    210   MSGPIPE,
    211   SHAREDBUFFER,
    212   NULLABLE_STRING,
    213   NULLABLE_HANDLE,
    214   NULLABLE_DCPIPE,
    215   NULLABLE_DPPIPE,
    216   NULLABLE_MSGPIPE,
    217   NULLABLE_SHAREDBUFFER
    218 )
    219 
    220 
    221 ATTRIBUTE_MIN_VERSION = 'MinVersion'
    222 ATTRIBUTE_EXTENSIBLE = 'Extensible'
    223 ATTRIBUTE_SYNC = 'Sync'
    224 
    225 
    226 class NamedValue(object):
    227   def __init__(self, module, parent_kind, mojom_name):
    228     self.module = module
    229     self.parent_kind = parent_kind
    230     self.mojom_name = mojom_name
    231 
    232   def GetSpec(self):
    233     return (self.module.mojom_namespace + '.' +
    234         (self.parent_kind and (self.parent_kind.mojom_name + '.') or "") +
    235         self.mojom_name)
    236 
    237 
    238 class BuiltinValue(object):
    239   def __init__(self, value):
    240     self.value = value
    241 
    242 
    243 class ConstantValue(NamedValue):
    244   def __init__(self, module, parent_kind, constant):
    245     NamedValue.__init__(self, module, parent_kind, constant.mojom_name)
    246     self.constant = constant
    247 
    248   @property
    249   def name(self):
    250     return self.constant.name
    251 
    252 
    253 class EnumValue(NamedValue):
    254   def __init__(self, module, enum, field):
    255     NamedValue.__init__(self, module, enum.parent_kind, field.mojom_name)
    256     self.field = field
    257     self.enum = enum
    258 
    259   def GetSpec(self):
    260     return (self.module.mojom_namespace + '.' +
    261         (self.parent_kind and (self.parent_kind.mojom_name + '.') or "") +
    262         self.enum.mojom_name + '.' + self.mojom_name)
    263 
    264   @property
    265   def name(self):
    266     return self.field.name
    267 
    268 
    269 class Constant(object):
    270   def __init__(self, mojom_name=None, kind=None, value=None, parent_kind=None):
    271     self.mojom_name = mojom_name
    272     self.kind = kind
    273     self.value = value
    274     self.parent_kind = parent_kind
    275 
    276   def Stylize(self, stylizer):
    277     self.name = stylizer.StylizeConstant(self.mojom_name)
    278 
    279 
    280 class Field(object):
    281   def __init__(self, mojom_name=None, kind=None, ordinal=None, default=None,
    282                attributes=None):
    283     if self.__class__.__name__ == 'Field':
    284       raise Exception()
    285     self.mojom_name = mojom_name
    286     self.kind = kind
    287     self.ordinal = ordinal
    288     self.default = default
    289     self.attributes = attributes
    290 
    291   def Repr(self, as_ref=True):
    292     # Fields are only referenced by objects which define them and thus
    293     # they are always displayed as non-references.
    294     return GenericRepr(self, {'mojom_name': False, 'kind': True})
    295 
    296   def Stylize(self, stylizer):
    297     self.name = stylizer.StylizeField(self.mojom_name)
    298 
    299   @property
    300   def min_version(self):
    301     return self.attributes.get(ATTRIBUTE_MIN_VERSION) \
    302         if self.attributes else None
    303 
    304 
    305 class StructField(Field): pass
    306 
    307 
    308 class UnionField(Field): pass
    309 
    310 
    311 class Struct(ReferenceKind):
    312   """A struct with typed fields.
    313 
    314   Attributes:
    315     mojom_name: {str} The name of the struct type as defined in mojom.
    316     name: {str} The stylized name.
    317     native_only: {bool} Does the struct have a body (i.e. any fields) or is it
    318         purely a native struct.
    319     custom_serializer: {bool} Should we generate a serializer for the struct or
    320         will one be provided by non-generated code.
    321     fields: {List[StructField]} The members of the struct.
    322     enums: {List[Enum]} The enums defined in the struct scope.
    323     constants: {List[Constant]} The constants defined in the struct scope.
    324     attributes: {dict} Additional information about the struct, such as
    325         if it's a native struct.
    326   """
    327 
    328   ReferenceKind.AddSharedProperty('mojom_name')
    329   ReferenceKind.AddSharedProperty('name')
    330   ReferenceKind.AddSharedProperty('native_only')
    331   ReferenceKind.AddSharedProperty('custom_serializer')
    332   ReferenceKind.AddSharedProperty('fields')
    333   ReferenceKind.AddSharedProperty('enums')
    334   ReferenceKind.AddSharedProperty('constants')
    335   ReferenceKind.AddSharedProperty('attributes')
    336 
    337   def __init__(self, mojom_name=None, module=None, attributes=None):
    338     if mojom_name is not None:
    339       spec = 'x:' + mojom_name
    340     else:
    341       spec = None
    342     ReferenceKind.__init__(self, spec, False, module)
    343     self.mojom_name = mojom_name
    344     self.native_only = False
    345     self.custom_serializer = False
    346     self.fields = []
    347     self.enums = []
    348     self.constants = []
    349     self.attributes = attributes
    350 
    351   def Repr(self, as_ref=True):
    352     if as_ref:
    353       return '<%s mojom_name=%r module=%s>' % (
    354           self.__class__.__name__, self.mojom_name,
    355           Repr(self.module, as_ref=True))
    356     else:
    357       return GenericRepr(self,
    358           {'mojom_name': False, 'fields': False, 'module': True})
    359 
    360   def AddField(self, mojom_name, kind, ordinal=None, default=None,
    361                attributes=None):
    362     field = StructField(mojom_name, kind, ordinal, default, attributes)
    363     self.fields.append(field)
    364     return field
    365 
    366   def Stylize(self, stylizer):
    367     self.name = stylizer.StylizeStruct(self.mojom_name)
    368     for field in self.fields:
    369       field.Stylize(stylizer)
    370     for enum in self.enums:
    371       enum.Stylize(stylizer)
    372     for constant in self.constants:
    373       constant.Stylize(stylizer)
    374 
    375 
    376 class Union(ReferenceKind):
    377   """A union of several kinds.
    378 
    379   Attributes:
    380     mojom_name: {str} The name of the union type as defined in mojom.
    381     name: {str} The stylized name.
    382     fields: {List[UnionField]} The members of the union.
    383     attributes: {dict} Additional information about the union, such as
    384         which Java class name to use to represent it in the generated
    385         bindings.
    386   """
    387   ReferenceKind.AddSharedProperty('mojom_name')
    388   ReferenceKind.AddSharedProperty('name')
    389   ReferenceKind.AddSharedProperty('fields')
    390   ReferenceKind.AddSharedProperty('attributes')
    391 
    392   def __init__(self, mojom_name=None, module=None, attributes=None):
    393     if mojom_name is not None:
    394       spec = 'x:' + mojom_name
    395     else:
    396       spec = None
    397     ReferenceKind.__init__(self, spec, False, module)
    398     self.mojom_name = mojom_name
    399     self.fields = []
    400     self.attributes = attributes
    401 
    402   def Repr(self, as_ref=True):
    403     if as_ref:
    404       return '<%s spec=%r is_nullable=%r fields=%s>' % (
    405           self.__class__.__name__, self.spec, self.is_nullable,
    406           Repr(self.fields))
    407     else:
    408       return GenericRepr(self, {'fields': True, 'is_nullable': False})
    409 
    410   def AddField(self, mojom_name, kind, ordinal=None, attributes=None):
    411     field = UnionField(mojom_name, kind, ordinal, None, attributes)
    412     self.fields.append(field)
    413     return field
    414 
    415   def Stylize(self, stylizer):
    416     self.name = stylizer.StylizeUnion(self.mojom_name)
    417     for field in self.fields:
    418       field.Stylize(stylizer)
    419 
    420 
    421 class Array(ReferenceKind):
    422   """An array.
    423 
    424   Attributes:
    425     kind: {Kind} The type of the elements. May be None.
    426     length: The number of elements. None if unknown.
    427   """
    428 
    429   ReferenceKind.AddSharedProperty('kind')
    430   ReferenceKind.AddSharedProperty('length')
    431 
    432   def __init__(self, kind=None, length=None):
    433     if kind is not None:
    434       if length is not None:
    435         spec = 'a%d:%s' % (length, kind.spec)
    436       else:
    437         spec = 'a:%s' % kind.spec
    438 
    439       ReferenceKind.__init__(self, spec)
    440     else:
    441       ReferenceKind.__init__(self)
    442     self.kind = kind
    443     self.length = length
    444 
    445   def Repr(self, as_ref=True):
    446     if as_ref:
    447       return '<%s spec=%r is_nullable=%r kind=%s length=%r>' % (
    448           self.__class__.__name__, self.spec, self.is_nullable, Repr(self.kind),
    449           self.length)
    450     else:
    451       return GenericRepr(self, {'kind': True, 'length': False,
    452                                 'is_nullable': False})
    453 
    454 
    455 class Map(ReferenceKind):
    456   """A map.
    457 
    458   Attributes:
    459     key_kind: {Kind} The type of the keys. May be None.
    460     value_kind: {Kind} The type of the elements. May be None.
    461   """
    462   ReferenceKind.AddSharedProperty('key_kind')
    463   ReferenceKind.AddSharedProperty('value_kind')
    464 
    465   def __init__(self, key_kind=None, value_kind=None):
    466     if (key_kind is not None and value_kind is not None):
    467       ReferenceKind.__init__(self,
    468                              'm[' + key_kind.spec + '][' + value_kind.spec +
    469                              ']')
    470       if IsNullableKind(key_kind):
    471         raise Exception("Nullable kinds cannot be keys in maps.")
    472       if IsAnyHandleKind(key_kind):
    473         raise Exception("Handles cannot be keys in maps.")
    474       if IsAnyInterfaceKind(key_kind):
    475         raise Exception("Interfaces cannot be keys in maps.")
    476       if IsArrayKind(key_kind):
    477         raise Exception("Arrays cannot be keys in maps.")
    478     else:
    479       ReferenceKind.__init__(self)
    480 
    481     self.key_kind = key_kind
    482     self.value_kind = value_kind
    483 
    484   def Repr(self, as_ref=True):
    485     if as_ref:
    486       return '<%s spec=%r is_nullable=%r key_kind=%s value_kind=%s>' % (
    487           self.__class__.__name__, self.spec, self.is_nullable,
    488           Repr(self.key_kind), Repr(self.value_kind))
    489     else:
    490       return GenericRepr(self, {'key_kind': True, 'value_kind': True})
    491 
    492 
    493 class InterfaceRequest(ReferenceKind):
    494   ReferenceKind.AddSharedProperty('kind')
    495 
    496   def __init__(self, kind=None):
    497     if kind is not None:
    498       if not isinstance(kind, Interface):
    499         raise Exception(
    500             "Interface request requires %r to be an interface." % kind.spec)
    501       ReferenceKind.__init__(self, 'r:' + kind.spec)
    502     else:
    503       ReferenceKind.__init__(self)
    504     self.kind = kind
    505 
    506 
    507 class AssociatedInterfaceRequest(ReferenceKind):
    508   ReferenceKind.AddSharedProperty('kind')
    509 
    510   def __init__(self, kind=None):
    511     if kind is not None:
    512       if not isinstance(kind, InterfaceRequest):
    513         raise Exception(
    514             "Associated interface request requires %r to be an interface "
    515             "request." % kind.spec)
    516       assert not kind.is_nullable
    517       ReferenceKind.__init__(self, 'asso:' + kind.spec)
    518     else:
    519       ReferenceKind.__init__(self)
    520     self.kind = kind.kind if kind is not None else None
    521 
    522 
    523 class Parameter(object):
    524   def __init__(self, mojom_name=None, kind=None, ordinal=None, default=None,
    525                attributes=None):
    526     self.mojom_name = mojom_name
    527     self.ordinal = ordinal
    528     self.kind = kind
    529     self.default = default
    530     self.attributes = attributes
    531 
    532   def Repr(self, as_ref=True):
    533     return '<%s mojom_name=%r kind=%s>' % (
    534         self.__class__.__name__, self.mojom_name, self.kind.Repr(as_ref=True))
    535 
    536   def Stylize(self, stylizer):
    537     self.name = stylizer.StylizeParameter(self.mojom_name)
    538 
    539   @property
    540   def min_version(self):
    541     return self.attributes.get(ATTRIBUTE_MIN_VERSION) \
    542         if self.attributes else None
    543 
    544 
    545 class Method(object):
    546   def __init__(self, interface, mojom_name, ordinal=None, attributes=None):
    547     self.interface = interface
    548     self.mojom_name = mojom_name
    549     self.ordinal = ordinal
    550     self.parameters = []
    551     self.param_struct = None
    552     self.response_parameters = None
    553     self.response_param_struct = None
    554     self.attributes = attributes
    555 
    556   def Repr(self, as_ref=True):
    557     if as_ref:
    558       return '<%s mojom_name=%r>' % (self.__class__.__name__, self.mojom_name)
    559     else:
    560       return GenericRepr(self, {'mojom_name': False, 'parameters': True,
    561                                 'response_parameters': True})
    562 
    563   def AddParameter(self, mojom_name, kind, ordinal=None, default=None,
    564                    attributes=None):
    565     parameter = Parameter(mojom_name, kind, ordinal, default, attributes)
    566     self.parameters.append(parameter)
    567     return parameter
    568 
    569   def AddResponseParameter(self, mojom_name, kind, ordinal=None, default=None,
    570                            attributes=None):
    571     if self.response_parameters == None:
    572       self.response_parameters = []
    573     parameter = Parameter(mojom_name, kind, ordinal, default, attributes)
    574     self.response_parameters.append(parameter)
    575     return parameter
    576 
    577   def Stylize(self, stylizer):
    578     self.name = stylizer.StylizeMethod(self.mojom_name)
    579     for param in self.parameters:
    580       param.Stylize(stylizer)
    581     if self.response_parameters is not None:
    582       for param in self.response_parameters:
    583         param.Stylize(stylizer)
    584 
    585     if self.param_struct:
    586       self.param_struct.Stylize(stylizer)
    587     if self.response_param_struct:
    588       self.response_param_struct.Stylize(stylizer)
    589 
    590   @property
    591   def min_version(self):
    592     return self.attributes.get(ATTRIBUTE_MIN_VERSION) \
    593         if self.attributes else None
    594 
    595   @property
    596   def sync(self):
    597     return self.attributes.get(ATTRIBUTE_SYNC) \
    598         if self.attributes else None
    599 
    600 
    601 class Interface(ReferenceKind):
    602   ReferenceKind.AddSharedProperty('mojom_name')
    603   ReferenceKind.AddSharedProperty('name')
    604   ReferenceKind.AddSharedProperty('methods')
    605   ReferenceKind.AddSharedProperty('enums')
    606   ReferenceKind.AddSharedProperty('constants')
    607   ReferenceKind.AddSharedProperty('attributes')
    608 
    609   def __init__(self, mojom_name=None, module=None, attributes=None):
    610     if mojom_name is not None:
    611       spec = 'x:' + mojom_name
    612     else:
    613       spec = None
    614     ReferenceKind.__init__(self, spec, False, module)
    615     self.mojom_name = mojom_name
    616     self.methods = []
    617     self.enums = []
    618     self.constants = []
    619     self.attributes = attributes
    620 
    621   def Repr(self, as_ref=True):
    622     if as_ref:
    623       return '<%s mojom_name=%r>' % (self.__class__.__name__, self.mojom_name)
    624     else:
    625       return GenericRepr(self, {'mojom_name': False, 'attributes': False,
    626                                 'methods': False})
    627 
    628   def AddMethod(self, mojom_name, ordinal=None, attributes=None):
    629     method = Method(self, mojom_name, ordinal, attributes)
    630     self.methods.append(method)
    631     return method
    632 
    633   def Stylize(self, stylizer):
    634     self.name = stylizer.StylizeInterface(self.mojom_name)
    635     for method in self.methods:
    636       method.Stylize(stylizer)
    637     for enum in self.enums:
    638       enum.Stylize(stylizer)
    639     for constant in self.constants:
    640       constant.Stylize(stylizer)
    641 
    642 
    643 class AssociatedInterface(ReferenceKind):
    644   ReferenceKind.AddSharedProperty('kind')
    645 
    646   def __init__(self, kind=None):
    647     if kind is not None:
    648       if not isinstance(kind, Interface):
    649         raise Exception(
    650             "Associated interface requires %r to be an interface." % kind.spec)
    651       assert not kind.is_nullable
    652       ReferenceKind.__init__(self, 'asso:' + kind.spec)
    653     else:
    654       ReferenceKind.__init__(self)
    655     self.kind = kind
    656 
    657 
    658 class EnumField(object):
    659   def __init__(self, mojom_name=None, value=None, attributes=None,
    660                numeric_value=None):
    661     self.mojom_name = mojom_name
    662     self.value = value
    663     self.attributes = attributes
    664     self.numeric_value = numeric_value
    665 
    666   def Stylize(self, stylizer):
    667     self.name = stylizer.StylizeEnumField(self.mojom_name)
    668 
    669   @property
    670   def min_version(self):
    671     return self.attributes.get(ATTRIBUTE_MIN_VERSION) \
    672         if self.attributes else None
    673 
    674 
    675 class Enum(Kind):
    676   def __init__(self, mojom_name=None, module=None, attributes=None):
    677     self.mojom_name = mojom_name
    678     self.native_only = False
    679     if mojom_name is not None:
    680       spec = 'x:' + mojom_name
    681     else:
    682       spec = None
    683     Kind.__init__(self, spec, module)
    684     self.fields = []
    685     self.attributes = attributes
    686     self.min_value = None
    687     self.max_value = None
    688 
    689   def Repr(self, as_ref=True):
    690     if as_ref:
    691       return '<%s mojom_name=%r>' % (self.__class__.__name__, self.mojom_name)
    692     else:
    693       return GenericRepr(self, {'mojom_name': False, 'fields': False})
    694 
    695   def Stylize(self, stylizer):
    696     self.name = stylizer.StylizeEnum(self.mojom_name)
    697     for field in self.fields:
    698       field.Stylize(stylizer)
    699 
    700   @property
    701   def extensible(self):
    702     return self.attributes.get(ATTRIBUTE_EXTENSIBLE, False) \
    703         if self.attributes else False
    704 
    705 
    706 class Module(object):
    707   def __init__(self, path=None, mojom_namespace=None,
    708                attributes=None):
    709     self.path = path
    710     self.mojom_namespace = mojom_namespace
    711     self.structs = []
    712     self.unions = []
    713     self.interfaces = []
    714     self.enums = []
    715     self.constants = []
    716     self.kinds = {}
    717     self.attributes = attributes
    718     self.imports = []
    719 
    720   def __repr__(self):
    721     # Gives us a decent __repr__ for modules.
    722     return self.Repr()
    723 
    724   def Repr(self, as_ref=True):
    725     if as_ref:
    726       return '<%s path=%r mojom_namespace=%r>' % (
    727           self.__class__.__name__, self.path, self.mojom_namespace)
    728     else:
    729       return GenericRepr(self, {'path': False, 'mojom_namespace': False,
    730                                 'attributes': False, 'structs': False,
    731                                 'interfaces': False, 'unions': False})
    732 
    733   def AddInterface(self, mojom_name, attributes=None):
    734     interface = Interface(mojom_name, self, attributes)
    735     self.interfaces.append(interface)
    736     return interface
    737 
    738   def AddStruct(self, mojom_name, attributes=None):
    739     struct = Struct(mojom_name, self, attributes)
    740     self.structs.append(struct)
    741     return struct
    742 
    743   def AddUnion(self, mojom_name, attributes=None):
    744     union = Union(mojom_name, self, attributes)
    745     self.unions.append(union)
    746     return union
    747 
    748   def Stylize(self, stylizer):
    749     self.namespace = stylizer.StylizeModule(self.mojom_namespace)
    750     for struct in self.structs:
    751       struct.Stylize(stylizer)
    752     for union in self.unions:
    753       union.Stylize(stylizer)
    754     for interface in self.interfaces:
    755       interface.Stylize(stylizer)
    756     for enum in self.enums:
    757       enum.Stylize(stylizer)
    758     for constant in self.constants:
    759       constant.Stylize(stylizer)
    760 
    761     for imported_module in self.imports:
    762       imported_module.Stylize(stylizer)
    763 
    764 
    765 def IsBoolKind(kind):
    766   return kind.spec == BOOL.spec
    767 
    768 
    769 def IsFloatKind(kind):
    770   return kind.spec == FLOAT.spec
    771 
    772 
    773 def IsDoubleKind(kind):
    774   return kind.spec == DOUBLE.spec
    775 
    776 
    777 def IsIntegralKind(kind):
    778   return (kind.spec == BOOL.spec or
    779           kind.spec == INT8.spec or
    780           kind.spec == INT16.spec or
    781           kind.spec == INT32.spec or
    782           kind.spec == INT64.spec or
    783           kind.spec == UINT8.spec or
    784           kind.spec == UINT16.spec or
    785           kind.spec == UINT32.spec or
    786           kind.spec == UINT64.spec)
    787 
    788 
    789 def IsStringKind(kind):
    790   return kind.spec == STRING.spec or kind.spec == NULLABLE_STRING.spec
    791 
    792 
    793 def IsGenericHandleKind(kind):
    794   return kind.spec == HANDLE.spec or kind.spec == NULLABLE_HANDLE.spec
    795 
    796 
    797 def IsDataPipeConsumerKind(kind):
    798   return kind.spec == DCPIPE.spec or kind.spec == NULLABLE_DCPIPE.spec
    799 
    800 
    801 def IsDataPipeProducerKind(kind):
    802   return kind.spec == DPPIPE.spec or kind.spec == NULLABLE_DPPIPE.spec
    803 
    804 
    805 def IsMessagePipeKind(kind):
    806   return kind.spec == MSGPIPE.spec or kind.spec == NULLABLE_MSGPIPE.spec
    807 
    808 
    809 def IsSharedBufferKind(kind):
    810   return (kind.spec == SHAREDBUFFER.spec or
    811           kind.spec == NULLABLE_SHAREDBUFFER.spec)
    812 
    813 
    814 def IsStructKind(kind):
    815   return isinstance(kind, Struct)
    816 
    817 
    818 def IsUnionKind(kind):
    819   return isinstance(kind, Union)
    820 
    821 
    822 def IsArrayKind(kind):
    823   return isinstance(kind, Array)
    824 
    825 
    826 def IsInterfaceKind(kind):
    827   return isinstance(kind, Interface)
    828 
    829 
    830 def IsAssociatedInterfaceKind(kind):
    831   return isinstance(kind, AssociatedInterface)
    832 
    833 
    834 def IsInterfaceRequestKind(kind):
    835   return isinstance(kind, InterfaceRequest)
    836 
    837 
    838 def IsAssociatedInterfaceRequestKind(kind):
    839   return isinstance(kind, AssociatedInterfaceRequest)
    840 
    841 
    842 def IsEnumKind(kind):
    843   return isinstance(kind, Enum)
    844 
    845 
    846 def IsReferenceKind(kind):
    847   return isinstance(kind, ReferenceKind)
    848 
    849 
    850 def IsNullableKind(kind):
    851   return IsReferenceKind(kind) and kind.is_nullable
    852 
    853 
    854 def IsMapKind(kind):
    855   return isinstance(kind, Map)
    856 
    857 
    858 def IsObjectKind(kind):
    859   return IsPointerKind(kind) or IsUnionKind(kind)
    860 
    861 
    862 def IsPointerKind(kind):
    863   return (IsStructKind(kind) or IsArrayKind(kind) or IsStringKind(kind) or
    864           IsMapKind(kind))
    865 
    866 
    867 # Please note that it doesn't include any interface kind.
    868 def IsAnyHandleKind(kind):
    869   return (IsGenericHandleKind(kind) or
    870           IsDataPipeConsumerKind(kind) or
    871           IsDataPipeProducerKind(kind) or
    872           IsMessagePipeKind(kind) or
    873           IsSharedBufferKind(kind))
    874 
    875 
    876 def IsAnyInterfaceKind(kind):
    877   return (IsInterfaceKind(kind) or IsInterfaceRequestKind(kind) or
    878           IsAssociatedKind(kind))
    879 
    880 
    881 def IsAnyHandleOrInterfaceKind(kind):
    882   return IsAnyHandleKind(kind) or IsAnyInterfaceKind(kind)
    883 
    884 
    885 def IsAssociatedKind(kind):
    886   return (IsAssociatedInterfaceKind(kind) or
    887           IsAssociatedInterfaceRequestKind(kind))
    888 
    889 
    890 def HasCallbacks(interface):
    891   for method in interface.methods:
    892     if method.response_parameters != None:
    893       return True
    894   return False
    895 
    896 
    897 # Finds out whether an interface passes associated interfaces and associated
    898 # interface requests.
    899 def PassesAssociatedKinds(interface):
    900   visited_kinds = set()
    901   for method in interface.methods:
    902     if MethodPassesAssociatedKinds(method, visited_kinds):
    903       return True
    904   return False
    905 
    906 
    907 def _AnyMethodParameterRecursive(method, predicate, visited_kinds=None):
    908   def _HasProperty(kind):
    909     if kind in visited_kinds:
    910       # No need to examine the kind again.
    911       return False
    912     visited_kinds.add(kind)
    913     if predicate(kind):
    914       return True
    915     if IsArrayKind(kind):
    916       return _HasProperty(kind.kind)
    917     if IsStructKind(kind) or IsUnionKind(kind):
    918       for field in kind.fields:
    919         if _HasProperty(field.kind):
    920           return True
    921     if IsMapKind(kind):
    922       if  _HasProperty(kind.key_kind) or _HasProperty(kind.value_kind):
    923         return True
    924     return False
    925 
    926   if visited_kinds is None:
    927     visited_kinds = set()
    928 
    929   for param in method.parameters:
    930     if _HasProperty(param.kind):
    931       return True
    932   if method.response_parameters != None:
    933     for param in method.response_parameters:
    934       if _HasProperty(param.kind):
    935         return True
    936   return False
    937 
    938 
    939 # Finds out whether a method passes associated interfaces and associated
    940 # interface requests.
    941 def MethodPassesAssociatedKinds(method, visited_kinds=None):
    942   return _AnyMethodParameterRecursive(method, IsAssociatedKind,
    943                                       visited_kinds=visited_kinds)
    944 
    945 
    946 # Determines whether a method passes interfaces.
    947 def MethodPassesInterfaces(method):
    948   return _AnyMethodParameterRecursive(method, IsInterfaceKind)
    949 
    950 
    951 def HasSyncMethods(interface):
    952   for method in interface.methods:
    953     if method.sync:
    954       return True
    955   return False
    956 
    957 
    958 def ContainsHandlesOrInterfaces(kind):
    959   """Check if the kind contains any handles.
    960 
    961   This check is recursive so it checks all struct fields, containers elements,
    962   etc.
    963 
    964   Args:
    965     struct: {Kind} The kind to check.
    966 
    967   Returns:
    968     {bool}: True if the kind contains handles.
    969   """
    970   # We remember the types we already checked to avoid infinite recursion when
    971   # checking recursive (or mutually recursive) types:
    972   checked = set()
    973   def Check(kind):
    974     if kind.spec in checked:
    975       return False
    976     checked.add(kind.spec)
    977     if IsStructKind(kind):
    978       return any(Check(field.kind) for field in kind.fields)
    979     elif IsUnionKind(kind):
    980       return any(Check(field.kind) for field in kind.fields)
    981     elif IsAnyHandleKind(kind):
    982       return True
    983     elif IsAnyInterfaceKind(kind):
    984       return True
    985     elif IsArrayKind(kind):
    986       return Check(kind.kind)
    987     elif IsMapKind(kind):
    988       return Check(kind.key_kind) or Check(kind.value_kind)
    989     else:
    990       return False
    991   return Check(kind)
    992