-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[libclang/python] Add typing annotations for the Type class #140378
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-clang Author: Jannick Kremer (DeinAlptraum) ChangesThis fully annotates the Type class, resolving 75 strict typing errors as the next step towards #76664 Full diff: https://github.com/llvm/llvm-project/pull/140378.diff 1 Files Affected:
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)
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Our error handling story is bad and inconsistent, but that's out of scope of this PR
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/94/builds/7226 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/35/builds/10177 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/136/builds/3945 Here is the relevant piece of the build log for the reference
|
We should be more consistent about mapping invalid types and invalid cursor to exceptions: llvm-project/clang/bindings/python/clang/cindex.py Lines 2659 to 2660 in ffb9bbf
We also need an exception hierarchy that can hold various invalid kinds of cursors. |
@uweigand it seems that it's a rather common (yet intermittent) failure with this particular bot. Can you look into it? |
@Endilll thanks for the heads-up! Looks like there has been some issue with network connectivity in our test lab over the weekend. This is supposed to be resolved now; I'll keep observing the status for a bit. |
) This fully annotates the Type class, resolving 75 strict typing errors as the next step towards llvm#76664
This fully annotates the Type class, resolving 75 strict typing errors as the next step towards #76664