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