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.iteritems()))) 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.iteritems())) 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 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. 168BOOL = Kind('b') 169INT8 = Kind('i8') 170INT16 = Kind('i16') 171INT32 = Kind('i32') 172INT64 = Kind('i64') 173UINT8 = Kind('u8') 174UINT16 = Kind('u16') 175UINT32 = Kind('u32') 176UINT64 = Kind('u64') 177FLOAT = Kind('f') 178DOUBLE = Kind('d') 179STRING = ReferenceKind('s') 180HANDLE = ReferenceKind('h') 181DCPIPE = ReferenceKind('h:d:c') 182DPPIPE = ReferenceKind('h:d:p') 183MSGPIPE = ReferenceKind('h:m') 184SHAREDBUFFER = ReferenceKind('h:s') 185NULLABLE_STRING = ReferenceKind('?s', True) 186NULLABLE_HANDLE = ReferenceKind('?h', True) 187NULLABLE_DCPIPE = ReferenceKind('?h:d:c', True) 188NULLABLE_DPPIPE = ReferenceKind('?h:d:p', True) 189NULLABLE_MSGPIPE = ReferenceKind('?h:m', True) 190NULLABLE_SHAREDBUFFER = ReferenceKind('?h:s', True) 191 192 193# Collection of all Primitive types 194PRIMITIVES = ( 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 221ATTRIBUTE_MIN_VERSION = 'MinVersion' 222ATTRIBUTE_EXTENSIBLE = 'Extensible' 223ATTRIBUTE_SYNC = 'Sync' 224 225 226class 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 238class BuiltinValue(object): 239 def __init__(self, value): 240 self.value = value 241 242 243class 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 253class 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 269class 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 280class 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 305class StructField(Field): pass 306 307 308class UnionField(Field): pass 309 310 311class 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 376class 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 421class 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 455class 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 493class 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 507class 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 523class 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 545class 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 601class 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 643class 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 658class 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 675class 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 706class 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 765def IsBoolKind(kind): 766 return kind.spec == BOOL.spec 767 768 769def IsFloatKind(kind): 770 return kind.spec == FLOAT.spec 771 772 773def IsDoubleKind(kind): 774 return kind.spec == DOUBLE.spec 775 776 777def 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 789def IsStringKind(kind): 790 return kind.spec == STRING.spec or kind.spec == NULLABLE_STRING.spec 791 792 793def IsGenericHandleKind(kind): 794 return kind.spec == HANDLE.spec or kind.spec == NULLABLE_HANDLE.spec 795 796 797def IsDataPipeConsumerKind(kind): 798 return kind.spec == DCPIPE.spec or kind.spec == NULLABLE_DCPIPE.spec 799 800 801def IsDataPipeProducerKind(kind): 802 return kind.spec == DPPIPE.spec or kind.spec == NULLABLE_DPPIPE.spec 803 804 805def IsMessagePipeKind(kind): 806 return kind.spec == MSGPIPE.spec or kind.spec == NULLABLE_MSGPIPE.spec 807 808 809def IsSharedBufferKind(kind): 810 return (kind.spec == SHAREDBUFFER.spec or 811 kind.spec == NULLABLE_SHAREDBUFFER.spec) 812 813 814def IsStructKind(kind): 815 return isinstance(kind, Struct) 816 817 818def IsUnionKind(kind): 819 return isinstance(kind, Union) 820 821 822def IsArrayKind(kind): 823 return isinstance(kind, Array) 824 825 826def IsInterfaceKind(kind): 827 return isinstance(kind, Interface) 828 829 830def IsAssociatedInterfaceKind(kind): 831 return isinstance(kind, AssociatedInterface) 832 833 834def IsInterfaceRequestKind(kind): 835 return isinstance(kind, InterfaceRequest) 836 837 838def IsAssociatedInterfaceRequestKind(kind): 839 return isinstance(kind, AssociatedInterfaceRequest) 840 841 842def IsEnumKind(kind): 843 return isinstance(kind, Enum) 844 845 846def IsReferenceKind(kind): 847 return isinstance(kind, ReferenceKind) 848 849 850def IsNullableKind(kind): 851 return IsReferenceKind(kind) and kind.is_nullable 852 853 854def IsMapKind(kind): 855 return isinstance(kind, Map) 856 857 858def IsObjectKind(kind): 859 return IsPointerKind(kind) or IsUnionKind(kind) 860 861 862def 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. 868def IsAnyHandleKind(kind): 869 return (IsGenericHandleKind(kind) or 870 IsDataPipeConsumerKind(kind) or 871 IsDataPipeProducerKind(kind) or 872 IsMessagePipeKind(kind) or 873 IsSharedBufferKind(kind)) 874 875 876def IsAnyInterfaceKind(kind): 877 return (IsInterfaceKind(kind) or IsInterfaceRequestKind(kind) or 878 IsAssociatedKind(kind)) 879 880 881def IsAnyHandleOrInterfaceKind(kind): 882 return IsAnyHandleKind(kind) or IsAnyInterfaceKind(kind) 883 884 885def IsAssociatedKind(kind): 886 return (IsAssociatedInterfaceKind(kind) or 887 IsAssociatedInterfaceRequestKind(kind)) 888 889 890def 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. 899def 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 907def _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. 941def MethodPassesAssociatedKinds(method, visited_kinds=None): 942 return _AnyMethodParameterRecursive(method, IsAssociatedKind, 943 visited_kinds=visited_kinds) 944 945 946# Determines whether a method passes interfaces. 947def MethodPassesInterfaces(method): 948 return _AnyMethodParameterRecursive(method, IsInterfaceKind) 949 950 951def HasSyncMethods(interface): 952 for method in interface.methods: 953 if method.sync: 954 return True 955 return False 956 957 958def 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