[clang] [libclang/python] Add typing annotations for the Type class (PR #140378)
Jannick Kremer via cfe-commits
cfe-commits at lists.llvm.org
Sat May 17 07:06:07 PDT 2025
https://github.com/DeinAlptraum created https://github.com/llvm/llvm-project/pull/140378
This fully annotates the Type class, resolving 75 strict typing errors as the next step towards #76664
>From 6218826401a236e3f70073de9e07c3bdefe0b048 Mon Sep 17 00:00:00 2001
From: Jannick Kremer <jannick.kremer at mailbox.org>
Date: Sat, 17 May 2025 23:03:32 +0900
Subject: [PATCH] [libclang/python] Add typing annotations for the Type class
---
clang/bindings/python/clang/cindex.py | 127 +++++++++++++-------------
1 file changed, 61 insertions(+), 66 deletions(-)
diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py
index a49441e815004..f65bcad780a70 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -91,6 +91,7 @@
cast as Tcast,
Generic,
Iterator,
+ Literal,
Optional,
Sequence,
Type as TType,
@@ -1982,7 +1983,7 @@ def type(self) -> Type:
Retrieve the Type (if any) of the entity pointed at by the cursor.
"""
if not hasattr(self, "_type"):
- self._type = Type.from_result(conf.lib.clang_getCursorType(self), (self,))
+ self._type = Type.from_result(conf.lib.clang_getCursorType(self), self)
return self._type
@@ -2009,7 +2010,7 @@ def result_type(self) -> Type:
"""Retrieve the Type of the result for this Cursor."""
if not hasattr(self, "_result_type"):
self._result_type = Type.from_result(
- conf.lib.clang_getCursorResultType(self), (self,)
+ conf.lib.clang_getCursorResultType(self), self
)
return self._result_type
@@ -2040,7 +2041,7 @@ def underlying_typedef_type(self) -> Type:
if not hasattr(self, "_underlying_type"):
assert self.kind.is_declaration()
self._underlying_type = Type.from_result(
- conf.lib.clang_getTypedefDeclUnderlyingType(self), (self,)
+ conf.lib.clang_getTypedefDeclUnderlyingType(self), self
)
return self._underlying_type
@@ -2056,7 +2057,7 @@ def enum_type(self) -> Type:
if not hasattr(self, "_enum_type"):
assert self.kind == CursorKind.ENUM_DECL
self._enum_type = Type.from_result(
- conf.lib.clang_getEnumDeclIntegerType(self), (self,)
+ conf.lib.clang_getEnumDeclIntegerType(self), self
)
return self._enum_type
@@ -2197,7 +2198,7 @@ def get_template_argument_kind(self, num: int) -> TemplateArgumentKind:
def get_template_argument_type(self, num: int) -> Type:
"""Returns the CXType for the indicated template argument."""
return Type.from_result(
- conf.lib.clang_Cursor_getTemplateArgumentType(self, num), (self, num)
+ conf.lib.clang_Cursor_getTemplateArgumentType(self, num), self
)
@cursor_null_guard
@@ -2597,8 +2598,10 @@ class Type(Structure):
_fields_ = [("_kind_id", c_int), ("data", c_void_p * 2)]
+ _tu: TranslationUnit
+
@property
- def kind(self):
+ def kind(self) -> TypeKind:
"""Return the kind of this type."""
return TypeKind.from_id(self._kind_id)
@@ -2635,7 +2638,7 @@ def __getitem__(self, key: int) -> Type:
)
result = Type.from_result(
- conf.lib.clang_getArgType(self.parent, key), (self.parent, key)
+ conf.lib.clang_getArgType(self.parent, key), self.parent
)
if result.kind == TypeKind.INVALID:
raise IndexError("Argument could not be retrieved.")
@@ -2646,63 +2649,56 @@ def __getitem__(self, key: int) -> Type:
return ArgumentsIterator(self)
@property
- def element_type(self):
+ def element_type(self) -> Type:
"""Retrieve the Type of elements within this Type.
If accessed on a type that is not an array, complex, or vector type, an
exception will be raised.
"""
- result = Type.from_result(conf.lib.clang_getElementType(self), (self,))
+ result = Type.from_result(conf.lib.clang_getElementType(self), self)
if result.kind == TypeKind.INVALID:
raise Exception("Element type not available on this type.")
return result
@property
- def element_count(self):
+ def element_count(self) -> int:
"""Retrieve the number of elements in this type.
Returns an int.
If the Type is not an array or vector, this raises.
"""
- result = conf.lib.clang_getNumElements(self)
+ result: int = conf.lib.clang_getNumElements(self)
if result < 0:
raise Exception("Type does not have elements.")
return result
@property
- def translation_unit(self):
+ def translation_unit(self) -> TranslationUnit:
"""The TranslationUnit to which this Type is associated."""
# If this triggers an AttributeError, the instance was not properly
# instantiated.
return self._tu
@staticmethod
- def from_result(res, args):
+ def from_result(res: Type, arg: Cursor | Type) -> Type:
assert isinstance(res, Type)
-
- tu = None
- for arg in args:
- if hasattr(arg, "translation_unit"):
- tu = arg.translation_unit
- break
-
- assert tu is not None
- res._tu = tu
+ assert arg.translation_unit is not None
+ res._tu = arg.translation_unit
return res
- def get_num_template_arguments(self):
+ def get_num_template_arguments(self) -> int:
return conf.lib.clang_Type_getNumTemplateArguments(self) # type: ignore [no-any-return]
- def get_template_argument_type(self, num):
+ def get_template_argument_type(self, num: int) -> Type:
return Type.from_result(
- conf.lib.clang_Type_getTemplateArgumentAsType(self, num), (self, num)
+ conf.lib.clang_Type_getTemplateArgumentAsType(self, num), self
)
- def get_canonical(self):
+ def get_canonical(self) -> Type:
"""
Return the canonical type for a Type.
@@ -2712,9 +2708,11 @@ def get_canonical(self):
example, if 'T' is a typedef for 'int', the canonical type for
'T' would be 'int'.
"""
- return Type.from_result(conf.lib.clang_getCanonicalType(self), (self,))
+ return Type.from_result(conf.lib.clang_getCanonicalType(self), self)
- def get_fully_qualified_name(self, policy, with_global_ns_prefix=False):
+ def get_fully_qualified_name(
+ self, policy: PrintingPolicy, with_global_ns_prefix: bool = False
+ ) -> str:
"""
Get the fully qualified name for a type.
@@ -2727,7 +2725,7 @@ def get_fully_qualified_name(self, policy, with_global_ns_prefix=False):
conf.lib.clang_getFullyQualifiedName(self, policy, with_global_ns_prefix)
)
- def is_const_qualified(self):
+ def is_const_qualified(self) -> bool:
"""Determine whether a Type has the "const" qualifier set.
This does not look through typedefs that may have added "const"
@@ -2735,7 +2733,7 @@ def is_const_qualified(self):
"""
return conf.lib.clang_isConstQualifiedType(self) # type: ignore [no-any-return]
- def is_volatile_qualified(self):
+ def is_volatile_qualified(self) -> bool:
"""Determine whether a Type has the "volatile" qualifier set.
This does not look through typedefs that may have added "volatile"
@@ -2743,7 +2741,7 @@ def is_volatile_qualified(self):
"""
return conf.lib.clang_isVolatileQualifiedType(self) # type: ignore [no-any-return]
- def is_restrict_qualified(self):
+ def is_restrict_qualified(self) -> bool:
"""Determine whether a Type has the "restrict" qualifier set.
This does not look through typedefs that may have added "restrict" at
@@ -2751,29 +2749,29 @@ def is_restrict_qualified(self):
"""
return conf.lib.clang_isRestrictQualifiedType(self) # type: ignore [no-any-return]
- def is_function_variadic(self):
+ def is_function_variadic(self) -> bool:
"""Determine whether this function Type is a variadic function type."""
assert self.kind == TypeKind.FUNCTIONPROTO
return conf.lib.clang_isFunctionTypeVariadic(self) # type: ignore [no-any-return]
- def get_address_space(self):
+ def get_address_space(self) -> int:
return conf.lib.clang_getAddressSpace(self) # type: ignore [no-any-return]
- def get_typedef_name(self):
+ def get_typedef_name(self) -> str:
return _CXString.from_result(conf.lib.clang_getTypedefName(self))
- def is_pod(self):
+ def is_pod(self) -> bool:
"""Determine whether this Type represents plain old data (POD)."""
return conf.lib.clang_isPODType(self) # type: ignore [no-any-return]
- def get_pointee(self):
+ def get_pointee(self) -> Type:
"""
For pointer types, returns the type of the pointee.
"""
- return Type.from_result(conf.lib.clang_getPointeeType(self), (self,))
+ return Type.from_result(conf.lib.clang_getPointeeType(self), self)
- def get_declaration(self):
+ def get_declaration(self) -> Cursor:
"""
Return the cursor for the declaration of the given type.
"""
@@ -2781,64 +2779,64 @@ def get_declaration(self):
conf.lib.clang_getTypeDeclaration(self), self
)
- def get_result(self):
+ def get_result(self) -> Type:
"""
Retrieve the result type associated with a function type.
"""
- return Type.from_result(conf.lib.clang_getResultType(self), (self,))
+ return Type.from_result(conf.lib.clang_getResultType(self), self)
- def get_array_element_type(self):
+ def get_array_element_type(self) -> Type:
"""
Retrieve the type of the elements of the array type.
"""
- return Type.from_result(conf.lib.clang_getArrayElementType(self), (self,))
+ return Type.from_result(conf.lib.clang_getArrayElementType(self), self)
- def get_array_size(self):
+ def get_array_size(self) -> int:
"""
Retrieve the size of the constant array.
"""
return conf.lib.clang_getArraySize(self) # type: ignore [no-any-return]
- def get_class_type(self):
+ def get_class_type(self) -> Type:
"""
Retrieve the class type of the member pointer type.
"""
- return Type.from_result(conf.lib.clang_Type_getClassType(self), (self,))
+ return Type.from_result(conf.lib.clang_Type_getClassType(self), self)
- def get_named_type(self):
+ def get_named_type(self) -> Type:
"""
Retrieve the type named by the qualified-id.
"""
- return Type.from_result(conf.lib.clang_Type_getNamedType(self), (self,))
+ return Type.from_result(conf.lib.clang_Type_getNamedType(self), self)
- def get_align(self):
+ def get_align(self) -> int:
"""
Retrieve the alignment of the record.
"""
return conf.lib.clang_Type_getAlignOf(self) # type: ignore [no-any-return]
- def get_size(self):
+ def get_size(self) -> int:
"""
Retrieve the size of the record.
"""
return conf.lib.clang_Type_getSizeOf(self) # type: ignore [no-any-return]
- def get_offset(self, fieldname):
+ def get_offset(self, fieldname: str) -> int:
"""
Retrieve the offset of a field in the record.
"""
return conf.lib.clang_Type_getOffsetOf(self, fieldname) # type: ignore [no-any-return]
- def get_ref_qualifier(self):
+ def get_ref_qualifier(self) -> RefQualifierKind:
"""
Retrieve the ref-qualifier of the type.
"""
return RefQualifierKind.from_id(conf.lib.clang_Type_getCXXRefQualifier(self))
- def get_fields(self):
+ def get_fields(self) -> Iterator[Cursor]:
"""Return an iterator for accessing the fields of this type."""
- def visitor(field, children):
+ def visitor(field: Cursor, _: Any) -> Literal[1]:
assert not field.is_null()
# Create reference to TU so it isn't GC'd before Cursor.
@@ -2850,10 +2848,10 @@ def visitor(field, children):
conf.lib.clang_Type_visitFields(self, fields_visit_callback(visitor), fields)
return iter(fields)
- def get_bases(self):
+ def get_bases(self) -> Iterator[Cursor]:
"""Return an iterator for accessing the base classes of this type."""
- def visitor(base, children):
+ def visitor(base: Cursor, _: Any) -> Literal[1]:
assert not base.is_null()
# Create reference to TU so it isn't GC'd before Cursor.
@@ -2865,10 +2863,10 @@ def visitor(base, children):
conf.lib.clang_visitCXXBaseClasses(self, fields_visit_callback(visitor), bases)
return iter(bases)
- def get_methods(self):
+ def get_methods(self) -> Iterator[Cursor]:
"""Return an iterator for accessing the methods of this type."""
- def visitor(method, children):
+ def visitor(method: Cursor, _: Any) -> Literal[1]:
assert not method.is_null()
# Create reference to TU so it isn't GC'd before Cursor.
@@ -2880,7 +2878,7 @@ def visitor(method, children):
conf.lib.clang_visitCXXMethods(self, fields_visit_callback(visitor), methods)
return iter(methods)
- def get_exception_specification_kind(self):
+ def get_exception_specification_kind(self) -> ExceptionSpecificationKind:
"""
Return the kind of the exception specification; a value from
the ExceptionSpecificationKind enumeration.
@@ -2890,21 +2888,18 @@ def get_exception_specification_kind(self):
)
@property
- def spelling(self):
+ def spelling(self) -> str:
"""Retrieve the spelling of this Type."""
return _CXString.from_result(conf.lib.clang_getTypeSpelling(self))
- def pretty_printed(self, policy):
+ def pretty_printed(self, policy: PrintingPolicy) -> str:
"""Pretty-prints this Type with the given PrintingPolicy"""
return _CXString.from_result(conf.lib.clang_getTypePrettyPrinted(self, policy))
- def __eq__(self, other):
- if not isinstance(other, Type):
- return False
-
- return conf.lib.clang_equalTypes(self, other) # type: ignore [no-any-return]
+ def __eq__(self, other: object) -> bool:
+ return isinstance(other, Type) and conf.lib.clang_equalTypes(self, other)
- def __ne__(self, other):
+ def __ne__(self, other: object) -> bool:
return not self.__eq__(other)
More information about the cfe-commits
mailing list