1# SPDX-FileCopyrightText: 2020 GNOME Foundation 2# SPDX-License-Identifier: Apache-2.0 OR GPL-3.0-or-later 3 4import typing as T 5 6from .. import log 7 8 9class Doc: 10 """A documentation node, pointing to the source code""" 11 def __init__(self, content: str, filename: str, line: int, version: str = None, stability: str = None): 12 self.content = content 13 self.filename = filename 14 self.line = line 15 self.version = version 16 self.stability = stability 17 18 def __str__(self): 19 return self.content 20 21 22class SourcePosition: 23 """A location inside the source code""" 24 def __init__(self, filename: str, line: int): 25 self.filename = filename 26 self.line = line 27 28 def __str__(self): 29 return f'{self.filename}:{self.line}' 30 31 32class Attribute: 33 """A user-defined annotation""" 34 def __init__(self, name: str, value: T.Optional[str]): 35 self.name = name 36 self.value = value 37 38 39class CInclude: 40 """A C include header""" 41 def __init__(self, name: str): 42 self.name = name 43 44 45class Include: 46 """A GIR include""" 47 def __init__(self, name: str, version: str = None): 48 self.name = name 49 self.version = version 50 51 def __str__(self): 52 if self.version is not None: 53 return f"{self.name}-{self.version}" 54 return f"{self.name}" 55 56 def girfile(self) -> str: 57 if self.version is not None: 58 return f"{self.name}-{self.version}.gir" 59 return f"{self.name}.gir" 60 61 62class Package: 63 """Pkg-config containing the library""" 64 def __init__(self, name: str): 65 self.name = name 66 67 68class Info: 69 """Base information for most types""" 70 def __init__(self, introspectable: bool = True, deprecated: T.Optional[str] = None, 71 deprecated_version: T.Optional[str] = None, version: str = None, 72 stability: str = None): 73 self.introspectable = introspectable 74 self.deprecated_msg = deprecated 75 self.deprecated_version = deprecated_version 76 self.version = version 77 self.stability = stability 78 self.attributes: T.Mapping[str, T.Optional[str]] = {} 79 self.doc: T.Optional[Doc] = None 80 self.source_position: T.Optional[SourcePosition] = None 81 82 def add_attribute(self, name: str, value: T.Optional[str] = None) -> None: 83 self.attributes[name] = value 84 85 86class GIRElement: 87 """Base type for elements inside the GIR""" 88 def __init__(self, name: T.Optional[str] = None, namespace: T.Optional[str] = None): 89 self.name = name 90 self.namespace = namespace 91 if self.namespace is not None: 92 if self.name is not None and '.' in self.name: 93 self.namespace = self.name.split('.')[0] 94 self.info = Info() 95 96 def set_introspectable(self, introspectable: bool) -> None: 97 """Set whether the symbol is introspectable""" 98 self.info.introspectable = introspectable 99 100 @property 101 def introspectable(self): 102 return self.info.introspectable 103 104 def set_version(self, version: str) -> None: 105 """Set the version of the symbol""" 106 self.info.version = version 107 108 def set_stability(self, stability: str) -> None: 109 """Set the stability of the symbol""" 110 self.info.stability = stability 111 112 @property 113 def stability(self): 114 return self.info.stability 115 116 def set_doc(self, doc: Doc) -> None: 117 """Set the documentation for the element""" 118 self.info.doc = doc 119 120 @property 121 def doc(self): 122 return self.info.doc 123 124 def set_source_position(self, pos: SourcePosition) -> None: 125 """Set the position in the source code for the element""" 126 self.info.source_position = pos 127 128 @property 129 def source_position(self) -> T.Optional[T.Tuple[str, int]]: 130 if self.info.source_position is None: 131 return None 132 return self.info.source_position.filename, self.info.source_position.line 133 134 def set_deprecated(self, doc: T.Optional[str] = None, since_version: T.Optional[str] = None) -> None: 135 """Set the deprecation annotations for the element""" 136 self.info.deprecated_msg = doc 137 self.info.deprecated_version = since_version 138 139 def set_attributes(self, attrs: T.Mapping[str, T.Optional[str]]) -> None: 140 """Add an annotation to the symbol""" 141 for name, value in attrs.items(): 142 self.info.add_attribute(name, value) 143 144 @property 145 def attributes(self) -> T.Mapping[str, T.Optional[str]]: 146 return self.info.attributes 147 148 @property 149 def available_since(self) -> T.Optional[str]: 150 return self.info.version 151 152 @property 153 def deprecated_since(self) -> T.Optional[T.Tuple[str, str]]: 154 if not self.info.deprecated_msg: 155 return None 156 version = self.info.deprecated_version 157 message = self.info.deprecated_msg 158 if message is None: 159 message = "Please do not use it in newly written code" 160 return (version, message) 161 162 163class Type(GIRElement): 164 """Base class for all Type nodes""" 165 def __init__(self, name: str, ctype: T.Optional[str] = None, namespace: T.Optional[str] = None): 166 super().__init__(name=name, namespace=namespace) 167 self.ctype = ctype 168 169 def __eq__(self, other): 170 if isinstance(other, Type): 171 if self.namespace is not None: 172 return self.namespace == other.namespace and self.name == self.name 173 elif self.ctype is not None: 174 return self.name == other.name and self.ctype == other.ctype 175 else: 176 return self.name == other.name 177 elif isinstance(other, str): 178 return self.name == other 179 else: 180 return False 181 182 def __cmp__(self, other): 183 if self.ctype is not None: 184 return self.name == other.name and self.ctype == other.ctype 185 return self.name == other.name 186 187 def __repr__(self): 188 return f"Type({self.fqtn}, {self.ctype})" 189 190 @property 191 def resolved(self): 192 return self.ctype is not None 193 194 @property 195 def base_ctype(self): 196 if self.ctype is None: 197 return None 198 return self.ctype.replace('*', '') 199 200 @property 201 def fqtn(self): 202 if '.' in self.name: 203 return self.name 204 elif self.namespace is not None: 205 return f"{self.namespace}.{self.name}" 206 else: 207 return None 208 209 210class ArrayType(GIRElement): 211 """Base class for Array nodes""" 212 def __init__(self, name: str, value_type: Type, ctype: str = None, zero_terminated: bool = False, 213 fixed_size: int = -1, length: int = -1): 214 super().__init__(name) 215 self.ctype = ctype 216 self.zero_terminated = zero_terminated 217 self.fixed_size = fixed_size 218 self.length = length 219 self.value_type = value_type 220 221 222class ListType(GIRElement): 223 """Type class for List nodes""" 224 def __init__(self, name: str, value_type: Type, ctype: str = None): 225 super().__init__(name) 226 self.ctype = ctype 227 self.value_type = value_type 228 229 230class MapType(GIRElement): 231 """Type class for Map nodes""" 232 def __init__(self, name: str, key_type: Type, value_type: Type, ctype: str = None): 233 super().__init__(name) 234 self.ctype = ctype 235 self.key_type = key_type 236 self.value_type = value_type 237 238 239class GType: 240 """Base class for GType information""" 241 def __init__(self, type_name: str, get_type: str, type_struct: T.Optional[str] = None): 242 self.type_name = type_name 243 self.get_type = get_type 244 self.type_struct = type_struct 245 246 247class VoidType(Type): 248 def __init__(self): 249 super().__init__(name='none', ctype='void') 250 251 def __str__(self): 252 return "void" 253 254 255class VarArgs(Type): 256 def __init__(self): 257 super().__init__(name='none', ctype='') 258 259 def __str__(self): 260 return "..." 261 262 263class Alias(Type): 264 """Alias to a Type""" 265 def __init__(self, name: str, namespace: str, ctype: str, target: Type): 266 super().__init__(name=name, ctype=ctype, namespace=namespace) 267 self.target = target 268 269 270class Constant(Type): 271 """A constant""" 272 def __init__(self, name: str, namespace: str, ctype: str, target: Type, value: str): 273 super().__init__(name=name, ctype=ctype, namespace=namespace) 274 self.target = target 275 self.value = value 276 277 278class Parameter(GIRElement): 279 """A callable parameter""" 280 def __init__(self, name: str, direction: str, transfer: str, target: Type = None, caller_allocates: bool = False, 281 optional: bool = False, nullable: bool = False, closure: int = -1, destroy: int = -1, 282 scope: str = None): 283 super().__init__(name) 284 self.direction = direction 285 self.transfer = transfer 286 self.caller_allocates = caller_allocates 287 self.optional = optional 288 self.nullable = nullable 289 self.scope = scope 290 self.closure = closure 291 self.destroy = destroy 292 if target is None: 293 self.target: Type = VoidType() 294 else: 295 self.target = target 296 297 298class ReturnValue(GIRElement): 299 """A callable's return value""" 300 def __init__(self, transfer: str, target: Type, nullable: bool = False, closure: int = -1, destroy: int = -1, scope: str = None): 301 super().__init__() 302 self.transfer = transfer 303 self.nullable = nullable 304 self.scope = scope 305 self.closure = closure 306 self.destroy = destroy 307 if target is None: 308 self.target: Type = VoidType() 309 else: 310 self.target = target 311 312 313class Callable(GIRElement): 314 """A callable symbol: function, method, function-macro, ...""" 315 def __init__(self, name: str, namespace: T.Optional[str], identifier: T.Optional[str], throws: bool = False): 316 super().__init__(name=name, namespace=namespace) 317 self.identifier = identifier 318 self.parameters: T.List[Parameter] = [] 319 self.return_value: T.Optional[ReturnValue] = None 320 self.throws: bool = throws 321 self.moved_to: T.Optional[str] = None 322 self.shadows: T.Optional[str] = None 323 self.shadowed_by: T.Optional[str] = None 324 325 def add_parameter(self, param: Parameter) -> None: 326 self.parameters.append(param) 327 328 def set_parameters(self, params: T.List[Parameter]) -> None: 329 self.parameters.extend(params) 330 331 def set_return_value(self, res: ReturnValue) -> None: 332 self.return_value = res 333 334 def set_shadows(self, func: str) -> None: 335 self.shadows = func 336 337 def set_shadowed_by(self, func: str) -> None: 338 self.shadowed_by = func 339 340 def set_moved_to(self, func: str) -> None: 341 self.moved_to = func 342 343 def __contains__(self, param): 344 if isinstance(param, str): 345 for p in self.parameters: 346 if p.name == param: 347 return True 348 elif isinstance(param, Parameter): 349 return param in self.parameters 350 elif isinstance(param, ReturnValue): 351 return param == self.return_value 352 return False 353 354 355class FunctionMacro(Callable): 356 def __init__(self, name: str, namespace: T.Optional[str], identifier: str): 357 super().__init__(name, namespace, identifier) 358 359 360class Function(Callable): 361 def __init__(self, name: str, namespace: T.Optional[str], identifier: str, throws: bool = False): 362 super().__init__(name, namespace, identifier, throws) 363 364 365class Method(Callable): 366 def __init__(self, name: str, identifier: str, instance_param: Parameter, throws: bool = False): 367 super().__init__(name, None, identifier, throws) 368 self.instance_param = instance_param 369 370 def __contains__(self, param): 371 if isinstance(param, Parameter) and param == self.instance_param: 372 return True 373 return super().__contains__(self, param) 374 375 376class VirtualMethod(Callable): 377 def __init__(self, name: str, identifier: str, invoker: str, instance_param: Parameter, throws: bool = False): 378 super().__init__(name, None, identifier, throws) 379 self.instance_param = instance_param 380 self.invoker = invoker 381 382 def __contains__(self, param): 383 if isinstance(param, Parameter) and param == self.instance_param: 384 return True 385 return super().__contains__(self, param) 386 387 388class Callback(Callable): 389 def __init__(self, name: str, namespace: str, ctype: T.Optional[str], throws: bool = False): 390 super().__init__(name=name, namespace=namespace, identifier=None, throws=throws) 391 self.ctype = ctype 392 393 394class Member(GIRElement): 395 """A member in an enumeration, error domain, or bitfield""" 396 def __init__(self, name: str, value: str, identifier: str, nick: str): 397 super().__init__(name) 398 self.value = value 399 self.identifier = identifier 400 self.nick = nick 401 402 403class Enumeration(Type): 404 """An enumeration type""" 405 def __init__(self, name: str, namespace: str, ctype: str, gtype: T.Optional[GType]): 406 super().__init__(name=name, ctype=ctype, namespace=namespace) 407 self.gtype = gtype 408 self.members: T.List[Member] = [] 409 self.functions: T.List[Function] = [] 410 411 def add_member(self, member: Member) -> None: 412 self.members.append(member) 413 414 def add_function(self, function: Function) -> None: 415 self.functions.append(function) 416 417 def set_members(self, members: T.List[Member]) -> None: 418 self.members.extend(members) 419 420 def set_functions(self, functions: T.List[Function]) -> None: 421 self.functions.extend(functions) 422 423 def __contains__(self, member): 424 if isinstance(member, Member): 425 return member in self.members 426 return False 427 428 def __iter__(self): 429 for member in self.members: 430 yield member 431 432 433class BitField(Enumeration): 434 """An enumeration type of bit masks""" 435 def __init__(self, name: str, namespace: str, ctype: str, gtype: T.Optional[GType]): 436 super().__init__(name, namespace, ctype, gtype) 437 438 439class ErrorDomain(Enumeration): 440 """An error domain for GError""" 441 def __init__(self, name: str, namespace: str, ctype: str, gtype: T.Optional[GType], domain: str): 442 super().__init__(name, namespace, ctype, gtype) 443 self.domain = domain 444 445 446class Property(GIRElement): 447 def __init__(self, name: str, transfer: str, target: Type, writable: bool = True, readable: bool = True, construct: bool = False, 448 construct_only: bool = False): 449 super().__init__(name) 450 self.transfer = transfer 451 self.writable = writable 452 self.readable = readable 453 self.construct = construct 454 self.construct_only = construct_only 455 self.target = target 456 457 458class Signal(GIRElement): 459 def __init__(self, name: str, detailed: bool, when: str, action: bool = False, no_hooks: bool = False, no_recurse: bool = False): 460 super().__init__(name) 461 self.detailed = detailed 462 self.when = when 463 self.action = action 464 self.no_hooks = no_hooks 465 self.no_recurse = no_recurse 466 self.parameters: T.List[Parameter] = [] 467 self.return_value: T.Optional[ReturnValue] = None 468 469 def set_parameters(self, params: T.List[Parameter]) -> None: 470 self.parameters.extend(params) 471 472 def set_return_value(self, res: ReturnValue) -> None: 473 self.return_value = res 474 475 476class Field(GIRElement): 477 """A field in a struct or union""" 478 def __init__(self, name: str, target: Type, writable: bool, readable: bool, private: bool = False, bits: int = 0): 479 super().__init__(name) 480 self.target = target 481 self.writable = writable 482 self.readable = readable 483 self.private = private 484 self.bits = bits 485 486 487class Interface(Type): 488 def __init__(self, name: str, namespace: str, ctype: str, symbol_prefix: str, gtype: GType): 489 super().__init__(name=name, ctype=ctype, namespace=namespace) 490 self.symbol_prefix = symbol_prefix 491 self.gtype = gtype 492 self.methods: T.List[Method] = [] 493 self.virtual_methods: T.List[VirtualMethod] = [] 494 self.properties: T.Mapping[str, Property] = {} 495 self.signals: T.Mapping[str, Signal] = {} 496 self.functions: T.List[Function] = [] 497 self.fields: T.List[Field] = [] 498 self.prerequisite: T.Optional[str] = None 499 500 @property 501 def type_struct(self) -> T.Optional[str]: 502 if self.gtype is not None: 503 return self.gtype.type_struct 504 return self.ctype 505 506 @property 507 def type_func(self) -> str: 508 return self.gtype.get_type 509 510 def set_methods(self, methods: T.List[Method]) -> None: 511 self.methods.extend(methods) 512 513 def set_virtual_methods(self, methods: T.List[VirtualMethod]) -> None: 514 self.virtual_methods.extend(methods) 515 516 def set_properties(self, properties: T.List[Property]) -> None: 517 for p in properties: 518 self.properties[p.name] = p 519 520 def set_signals(self, signals: T.List[Signal]) -> None: 521 for s in signals: 522 self.signals[s.name] = s 523 524 def set_functions(self, functions: T.List[Function]) -> None: 525 self.functions.extend(functions) 526 527 def set_fields(self, fields: T.List[Field]) -> None: 528 self.fields.extend(fields) 529 530 def set_prerequisite(self, prerequisite: str) -> None: 531 self.prerequisite = prerequisite 532 533 534class Class(Type): 535 def __init__(self, name: str, namespace: str, ctype: str, symbol_prefix: str, 536 gtype: GType, parent: T.Optional[Type] = None, 537 abstract: bool = False, fundamental: bool = False, 538 ref_func: T.Optional[str] = None, unref_func: T.Optional[str] = None): 539 super().__init__(name=name, ctype=ctype, namespace=namespace) 540 self.symbol_prefix = symbol_prefix 541 self.parent = parent 542 self.abstract = abstract 543 self.fundamental = fundamental 544 self.ref_func = ref_func 545 self.unref_func = unref_func 546 self.gtype = gtype 547 self.ancestors: T.List[Type] = [] 548 self.implements: T.List[Type] = [] 549 self.constructors: T.List[Function] = [] 550 self.methods: T.List[Method] = [] 551 self.virtual_methods: T.List[VirtualMethod] = [] 552 self.properties: T.Mapping[str, Property] = {} 553 self.signals: T.Mapping[str, Signal] = {} 554 self.functions: T.List[Function] = [] 555 self.fields: T.List[Field] = [] 556 self.callbacks: T.List[Callback] = [] 557 558 @property 559 def type_struct(self) -> T.Optional[str]: 560 if self.gtype is not None: 561 return self.gtype.type_struct 562 return None 563 564 @property 565 def type_func(self) -> T.Optional[str]: 566 if self.gtype is not None: 567 return self.gtype.get_type 568 return self.ctype 569 570 def set_constructors(self, ctors: T.List[Function]) -> None: 571 self.constructors.extend(ctors) 572 573 def set_methods(self, methods: T.List[Method]) -> None: 574 self.methods.extend(methods) 575 576 def set_virtual_methods(self, methods: T.List[VirtualMethod]) -> None: 577 self.virtual_methods.extend(methods) 578 579 def set_properties(self, properties: T.List[Property]) -> None: 580 for p in properties: 581 self.properties[p.name] = p 582 583 def set_signals(self, signals: T.List[Signal]) -> None: 584 for s in signals: 585 self.signals[s.name] = s 586 587 def set_functions(self, functions: T.List[Function]) -> None: 588 self.functions.extend(functions) 589 590 def set_implements(self, ifaces: T.List[Type]) -> None: 591 self.implements.extend(ifaces) 592 593 def set_fields(self, fields: T.List[Field]) -> None: 594 self.fields.extend(fields) 595 596 597class Boxed(Type): 598 def __init__(self, name: str, namespace: str, symbol_prefix: str, gtype: GType): 599 super().__init__(name=name, ctype=None, namespace=namespace) 600 self.symbol_prefix = symbol_prefix 601 self.gtype = gtype 602 self.functions: T.List[Function] = [] 603 604 def set_functions(self, functions: T.List[Function]) -> None: 605 self.functions.extend(functions) 606 607 608class Record(Type): 609 def __init__(self, name: str, namespace: str, ctype: str, symbol_prefix: str, 610 gtype: T.Optional[GType] = None, struct_for: T.Optional[str] = None, 611 disguised: bool = False): 612 super().__init__(name=name, ctype=ctype, namespace=namespace) 613 self.symbol_prefix = symbol_prefix 614 self.gtype = gtype 615 self.struct_for = struct_for 616 self.disguised = disguised 617 self.constructors: T.List[Function] = [] 618 self.methods: T.List[Method] = [] 619 self.functions: T.List[Function] = [] 620 self.fields: T.List[Field] = [] 621 622 @property 623 def type_struct(self) -> T.Optional[str]: 624 if self.gtype is not None: 625 return self.gtype.type_struct 626 return self.ctype 627 628 @property 629 def type_func(self) -> T.Optional[str]: 630 if self.gtype is not None: 631 return self.gtype.get_type 632 return None 633 634 def set_constructors(self, ctors: T.List[Function]) -> None: 635 self.constructors.extend(ctors) 636 637 def set_methods(self, methods: T.List[Method]) -> None: 638 self.methods.extend(methods) 639 640 def set_functions(self, functions: T.List[Function]) -> None: 641 self.functions.extend(functions) 642 643 def set_fields(self, fields: T.List[Field]) -> None: 644 self.fields.extend(fields) 645 646 647class Union(Type): 648 def __init__(self, name: str, namespace: str, ctype: str, symbol_prefix: str, gtype: T.Optional[GType]): 649 super().__init__(name=name, ctype=ctype, namespace=namespace) 650 self.symbol_prefix = symbol_prefix 651 self.gtype = gtype 652 self.constructors: T.List[Function] = [] 653 self.methods: T.List[Method] = [] 654 self.functions: T.List[Function] = [] 655 self.fields: T.List[Field] = [] 656 657 @property 658 def type_struct(self) -> T.Optional[str]: 659 if self.gtype is not None: 660 return self.gtype.type_struct 661 return self.ctype 662 663 @property 664 def type_func(self) -> T.Optional[str]: 665 if self.gtype is not None: 666 return self.gtype.get_type 667 return None 668 669 def set_constructors(self, ctors: T.List[Function]) -> None: 670 self.constructors.extend(ctors) 671 672 def set_methods(self, methods: T.List[Method]) -> None: 673 self.methods.extend(methods) 674 675 def set_functions(self, functions: T.List[Function]) -> None: 676 self.functions.extend(functions) 677 678 def set_fields(self, fields: T.List[Field]) -> None: 679 self.fields.extend(fields) 680 681 682class Namespace: 683 def __init__(self, name: str, version: str, identifier_prefix: T.List[str] = [], symbol_prefix: T.List[str] = []): 684 self.name = name 685 self.version = version 686 687 self._shared_libraries: T.List[str] = [] 688 689 self._aliases: T.Mapping[str, Alias] = {} 690 self._bitfields: T.Mapping[str, BitField] = {} 691 self._boxeds: T.Mapping[str, Boxed] = {} 692 self._callbacks: T.List[Callback] = [] 693 self._classes: T.Mapping[str, Class] = {} 694 self._constants: T.Mapping[str, Constant] = {} 695 self._enumerations: T.Mapping[str, Enumeration] = {} 696 self._error_domains: T.Mapping[str, ErrorDomain] = {} 697 self._functions: T.Mapping[str, Function] = {} 698 self._function_macros: T.Mapping[str, FunctionMacro] = {} 699 self._interfaces: T.Mapping[str, Interface] = {} 700 self._records: T.Mapping[str, Record] = {} 701 self._unions: T.Mapping[str, Union] = {} 702 703 self._symbols: T.Mapping[str, Type] = {} 704 self.repository: T.Optional[Repository] = None 705 706 if identifier_prefix: 707 self.identifier_prefix = identifier_prefix 708 else: 709 self.identifier_prefix = [self.name] 710 if symbol_prefix: 711 self.symbol_prefix = symbol_prefix 712 else: 713 self.symbol_prefix = [self.name.lower()] 714 715 def __str__(self): 716 return f"{self.name}-{self.version}" 717 718 def add_shared_libraries(self, libs: T.List[str]) -> None: 719 self._shared_libraries.extend(libs) 720 721 def get_shared_libraries(self) -> T.List[str]: 722 return self._shared_libraries 723 724 def add_alias(self, alias: Alias) -> None: 725 self._aliases[alias.name] = alias 726 727 def add_enumeration(self, enum: Enumeration) -> None: 728 self._enumerations[enum.name] = enum 729 730 def add_error_domain(self, domain: ErrorDomain) -> None: 731 self._error_domains[domain.name] = domain 732 733 def add_class(self, cls: Class) -> None: 734 self._classes[cls.name] = cls 735 736 def add_constant(self, constant: Constant) -> None: 737 self._constants[constant.name] = constant 738 739 def add_interface(self, interface: Interface) -> None: 740 self._interfaces[interface.name] = interface 741 742 def add_boxed(self, boxed: Boxed) -> None: 743 self._boxeds[boxed.name] = boxed 744 745 def add_record(self, record: Record) -> None: 746 self._records[record.name] = record 747 748 def add_union(self, union: Union) -> None: 749 self._unions[union.name] = union 750 751 def add_function(self, function: Function) -> None: 752 self._functions[function.name] = function 753 754 def add_bitfield(self, bitfield: BitField) -> None: 755 self._bitfields[bitfield.name] = bitfield 756 757 def add_function_macro(self, function: FunctionMacro) -> None: 758 self._function_macros[function.name] = function 759 760 def add_callback(self, callback: Callback) -> None: 761 self._callbacks.append(callback) 762 763 def get_classes(self) -> T.List[Class]: 764 return self._classes.values() 765 766 def get_constants(self) -> T.List[Constant]: 767 return self._constants.values() 768 769 def get_enumerations(self) -> T.List[Enumeration]: 770 return self._enumerations.values() 771 772 def get_error_domains(self) -> T.List[ErrorDomain]: 773 return self._error_domains.values() 774 775 def get_aliases(self) -> T.List[Alias]: 776 return self._aliases.values() 777 778 def get_interfaces(self) -> T.List[Interface]: 779 return self._interfaces.values() 780 781 def get_boxeds(self) -> T.List[Boxed]: 782 return self._boxeds.values() 783 784 def get_records(self) -> T.List[Record]: 785 return self._records.values() 786 787 def get_effective_records(self) -> T.List[Record]: 788 def is_effective(r): 789 if "Private" in r.name and r.disguised: 790 return False 791 if r.struct_for is not None: 792 return False 793 return True 794 795 return [x for x in self._records.values() if is_effective(x)] 796 797 def get_unions(self) -> T.List[Union]: 798 return self._unions.values() 799 800 def get_functions(self) -> T.List[Function]: 801 return self._functions.values() 802 803 def get_bitfields(self) -> T.List[BitField]: 804 return self._bitfields.values() 805 806 def get_function_macros(self) -> T.List[FunctionMacro]: 807 return self._function_macros.values() 808 809 def get_effective_function_macros(self) -> T.List[FunctionMacro]: 810 def is_effective(f, ns): 811 # Lower-case identifiers are an automatic pass 812 if f.name.islower(): 813 return True 814 # Try to eliminate the GObject type macros from the pool 815 t = f.name.split('_') 816 # Skip "is-a" macros 817 if 'IS' in t: 818 return False 819 # Skip "get class/iface" macros 820 if 'GET' in t: 821 return False 822 # Re-assemble into what most likely is a type name 823 s = "".join([x.capitalize() if len(x) > 2 else x for x in t]) 824 # Skip "cast" macros 825 if ns.find_class(s) is not None: 826 return False 827 if ns.find_interface(s) is not None: 828 return False 829 if ns.find_record(s) is not None: 830 return False 831 # Anything that survived at this point is likely a valid function 832 # macro 833 return True 834 835 return [x for x in self._function_macros.values() if is_effective(x, self)] 836 837 def get_callbacks(self) -> T.List[Callback]: 838 return self._callbacks 839 840 def find_class(self, cls: str) -> T.Optional[Class]: 841 return self._classes.get(cls) 842 843 def find_record(self, record: str) -> T.Optional[Record]: 844 return self._records.get(record) 845 846 def find_interface(self, iface: str) -> T.Optional[Interface]: 847 return self._interfaces.get(iface) 848 849 def find_union(self, union: str) -> T.Optional[Union]: 850 return self._unions.get(union) 851 852 def find_enumeration(self, enum: str) -> T.Optional[Enumeration]: 853 return self._enumerations.get(enum) 854 855 def find_bitfield(self, bitfield: str) -> T.Optional[BitField]: 856 return self._bitfields.get(bitfield) 857 858 def find_error_domain(self, domain: str) -> T.Optional[ErrorDomain]: 859 return self._error_domains.get(domain) 860 861 def find_alias(self, alias: str) -> T.Optional[Alias]: 862 return self._aliases.get(alias) 863 864 def find_function(self, func: str) -> T.Optional[Function]: 865 if func in self._functions: 866 return self._functions.get(func) 867 if func in self._function_macros: 868 return self._function_macros.get(func) 869 return None 870 871 def find_real_type(self, name: str) -> T.Optional[Type]: 872 if name in self._aliases: 873 return self._aliases[name] 874 if name in self._bitfields: 875 return self._bitfields[name] 876 if name in self._enumerations: 877 return self._enumerations[name] 878 if name in self._error_domains: 879 return self._error_domains[name] 880 if name in self._classes: 881 return self._classes[name] 882 if name in self._interfaces: 883 return self._interfaces[name] 884 if name in self._records: 885 return self._records[name] 886 if name in self._unions: 887 return self._unions[name] 888 return None 889 890 def find_symbol(self, name: str) -> T.Optional[Type]: 891 return self._symbols.get(name) 892 893 def find_prerequisite_type(self, name: str) -> T.Optional[Type]: 894 if name in self._classes: 895 return self._classes[name] 896 if name is self._interfaces: 897 return self._interfaces[name] 898 return None 899 900 901class Repository: 902 def __init__(self): 903 self.includes: T.Mapping[str, Repository] = {} 904 self.packages: T.List[Package] = [] 905 self.c_includes: T.List[CInclude] = [] 906 self.types: T.Mapping[str, T.List[Type]] = {} 907 self._namespaces: T.List[Namespace] = [] 908 self.girfile: T.Optional[str] = None 909 910 def add_namespace(self, ns: Namespace) -> None: 911 self._namespaces.append(ns) 912 ns.repository = self 913 914 def get_namespace(self, ns: str) -> T.Optional[Namespace]: 915 for namespace in self._namespaces: 916 if namespace.name == ns: 917 return namespace 918 return None 919 920 def find_included_namespace(self, ns: str) -> T.Optional[Namespace]: 921 for repo_name in self.includes: 922 repo = self.includes[repo_name] 923 if repo.namespace.name == ns: 924 return repo.namespace 925 return None 926 927 def resolve_empty_ctypes(self, seen_types: T.Mapping[str, T.List[Type]]) -> None: 928 for fqtn in seen_types: 929 types = seen_types[fqtn] 930 resolved_types = [t for t in types if t.resolved] 931 if len(resolved_types) == 0: 932 ns, name = fqtn.split('.', 1) 933 backstop = f"{self.namespace.identifier_prefix[0]}{name}" 934 resolved_types.append(Type(fqtn, backstop)) 935 self.types[fqtn] = resolved_types 936 log.debug(f"Type: {fqtn}: {resolved_types}") 937 938 def resolve_interface_requires(self) -> None: 939 def find_prerequisite_type(includes, ns, name): 940 for repo in includes.values(): 941 if repo.namespace.name != ns: 942 continue 943 prereq = repo.namespace.find_prerequisite_type(name) 944 if prereq is not None: 945 return Type(name=f"{repo.namespace.name}.{prereq.name}", ctype=prereq.ctype) 946 return None 947 948 ifaces = self.namespace.get_interfaces() 949 for iface in ifaces: 950 if iface.prerequisite is None: 951 continue 952 prerequisite = None 953 if '.' in iface.prerequisite.name: 954 ns, name = iface.prerequisite.name.split('.', 1) 955 if ns == self.namespace.name: 956 prerequisite = self.namespace.find_prerequisite_type(name) 957 else: 958 prerequisite = find_prerequisite_type(self.includes, ns, name) 959 else: 960 prerequisite = self.namespace.find_prerequisite_type(iface.prerequisite.name) 961 if prerequisite is not None: 962 if prerequisite.ctype is None: 963 t = self.find_type(prerequisite.name) 964 prerequisite.ctype = t.ctype 965 iface.prerequisite = prerequisite 966 log.debug(f"Prerequisite type for interface {iface}: {iface.prerequisite}") 967 968 def resolve_class_type(self) -> None: 969 classes = self.namespace.get_classes() 970 for cls in classes: 971 if cls.ctype is None: 972 if '.' not in cls.name: 973 name = f"{self.namespace.name}.{cls.name}" 974 else: 975 name = cls.name 976 t = self.find_type(name) 977 if t is not None: 978 cls.ctype = t.base_ctype 979 else: 980 # This is kind of a kludge, but apparently we can get into 981 # class definitions missing a c:type; if that happens, we 982 # take the identifier prefix of the namespace and append the 983 # class name, because that's the inverse of how g-ir-scanner 984 # determines the class name 985 cls.ctype = f"{self.namespace.identifier_prefix[0]}{cls.name}" 986 log.debug(f"Updated C type for {cls}") 987 988 def resolve_class_implements(self) -> None: 989 def find_interface_type(includes, ns, name): 990 for repo in includes.values(): 991 if repo.namespace.name != ns: 992 continue 993 iface = repo.namespace.find_interface(name) 994 if iface is not None: 995 return Type(name=f"{repo.namespace.name}.{iface.name}", ctype=iface.ctype) 996 return None 997 998 classes = self.namespace.get_classes() 999 for cls in classes: 1000 if cls.implements is None: 1001 continue 1002 implements = cls.implements 1003 cls.implements = [] 1004 for iface in implements: 1005 if '.' in iface.name: 1006 ns, name = iface.name.split('.', 1) 1007 if ns == self.namespace.name: 1008 iface_type = self.namespace.find_interface(name) 1009 else: 1010 iface_type = find_interface_type(self.includes, ns, name) 1011 else: 1012 iface_type = self.namespace.find_interface(iface.name) 1013 if iface_type is not None: 1014 if iface_type.ctype is None: 1015 t = self.find_type(iface_type.name) 1016 iface_type.ctype = t.ctype 1017 cls.implements.append(iface_type) 1018 log.debug(f"Interfaces implemented by {cls}: {cls.implements}") 1019 1020 def resolve_class_ancestors(self) -> None: 1021 def find_parent_class(includes, ns, name): 1022 for repo in includes.values(): 1023 if repo.namespace.name != ns: 1024 continue 1025 parent = repo.namespace.find_class(name) 1026 if parent is not None: 1027 return parent 1028 return None 1029 1030 classes = self.namespace.get_classes() 1031 for cls in classes: 1032 if cls.parent is None: 1033 continue 1034 ancestors = [] 1035 parent = cls.parent 1036 while parent is not None: 1037 if '.' in parent.name: 1038 ns, name = parent.name.split('.') 1039 if ns == self.namespace.name: 1040 parent = self.namespace.find_class(name) 1041 else: 1042 parent = find_parent_class(self.includes, ns, name) 1043 else: 1044 parent = self.namespace.find_class(parent.name) 1045 if parent is not None: 1046 if parent.ctype is None: 1047 t = self.find_type(parent.name) 1048 parent.ctype = t.ctype 1049 ancestors.append(parent) 1050 parent = parent.parent 1051 cls.ancestors = ancestors 1052 cls.parent = ancestors[0] 1053 log.debug(f"Ancestors for {cls}: parent: {cls.parent}, ancestors: {cls.ancestors}") 1054 1055 def resolve_moved_to(self) -> None: 1056 functions = list(self.namespace.get_functions()) 1057 old_len = len(functions) 1058 for func in functions[:]: 1059 if func.moved_to is None: 1060 continue 1061 moved_type, moved_func_name = func.moved_to.split('.') 1062 real_type = self.namespace.find_real_type(moved_type) 1063 if real_type is None: 1064 continue 1065 self.namespace._functions.pop(func.name) # XXX: Add accessor 1066 new_len = len(self.namespace._functions) 1067 diff = old_len - new_len 1068 log.debug(f"Removed {old_len} - {new_len} functions: {diff}") 1069 1070 def resolve_symbols(self) -> None: 1071 symbols: T.Mapping[str, Type] = {} 1072 for func in self.namespace.get_functions(): 1073 symbols[func.identifier] = func 1074 for func in self.namespace.get_function_macros(): 1075 symbols[func.identifier] = func 1076 for cls in self.namespace.get_classes(): 1077 for m in cls.constructors: 1078 symbols[m.identifier] = cls 1079 for m in cls.methods: 1080 symbols[m.identifier] = cls 1081 for m in cls.functions: 1082 symbols[m.identifier] = cls 1083 for iface in self.namespace.get_interfaces(): 1084 for m in iface.methods: 1085 symbols[m.identifier] = iface 1086 for m in iface.functions: 1087 symbols[m.identifier] = iface 1088 for record in self.namespace.get_records(): 1089 for m in record.constructors: 1090 symbols[m.identifier] = record 1091 for m in record.methods: 1092 symbols[m.identifier] = record 1093 for m in record.functions: 1094 symbols[m.identifier] = record 1095 for union in self.namespace.get_unions(): 1096 for m in union.constructors: 1097 symbols[m.identifier] = union 1098 for m in union.methods: 1099 symbols[m.identifier] = union 1100 for m in union.functions: 1101 symbols[m.identifier] = union 1102 self.namespace._symbols = symbols 1103 1104 @property 1105 def namespace(self) -> T.Optional[Namespace]: 1106 return self._namespaces[0] 1107 1108 def find_type(self, name: str) -> T.Optional[Type]: 1109 types = self.types.get(name) 1110 if types is None: 1111 return None 1112 for t in types: 1113 if t.resolved: 1114 return t 1115 return types[0] 1116