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