[clang] [libclang/python] Add some bindings to the `Cursor` interface (PR #132377)
Jannick Kremer via cfe-commits
cfe-commits at lists.llvm.org
Fri Mar 21 04:51:08 PDT 2025
https://github.com/DeinAlptraum created https://github.com/llvm/llvm-project/pull/132377
Make Cursor hashable
Add `Cursor.has_attr()`
Add `Cursor.specialized_template`
>From c433f194600d72a3902c4eed304439d6e3f2f62b Mon Sep 17 00:00:00 2001
From: Mathias Stearn <redbeard0531 at gmail.com>
Date: Thu, 19 Dec 2024 16:22:04 +0100
Subject: [PATCH] [libclang/python] Add some bindings to the Cursor interface
Make Cursor hashable
Add Cursor.has_attr()
Add Cursor.specialized_template
---
clang/bindings/python/clang/cindex.py | 17 ++++++++
.../python/tests/cindex/test_cursor.py | 40 +++++++++++++++++++
clang/docs/ReleaseNotes.rst | 6 +++
3 files changed, 63 insertions(+)
diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py
index 879a0a3c5c58c..090ee899ad60e 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -1561,6 +1561,9 @@ def __eq__(self, other):
def __ne__(self, other):
return not self.__eq__(other)
+ def __hash__(self) -> int:
+ return self.hash
+
def is_definition(self):
"""
Returns true if the declaration pointed at by the cursor is also a
@@ -2035,6 +2038,13 @@ def lexical_parent(self):
return self._lexical_parent
+ @property
+ def specialized_template(self) -> Cursor | None:
+ """Return the primary template that this cursor is a specialization of, if any."""
+ return Cursor.from_cursor_result(
+ conf.lib.clang_getSpecializedCursorTemplate(self), self
+ )
+
@property
def translation_unit(self):
"""Returns the TranslationUnit to which this Cursor belongs."""
@@ -2178,6 +2188,12 @@ def get_bitfield_width(self):
"""
return conf.lib.clang_getFieldDeclBitWidth(self) # type: ignore [no-any-return]
+ def has_attrs(self) -> bool:
+ """
+ Determine whether the given cursor has any attributes.
+ """
+ return bool(conf.lib.clang_Cursor_hasAttrs(self))
+
@staticmethod
def from_result(res, arg):
assert isinstance(res, Cursor)
@@ -3932,6 +3948,7 @@ def set_property(self, property, value):
("clang_getCursorType", [Cursor], Type),
("clang_getCursorUSR", [Cursor], _CXString),
("clang_Cursor_getMangling", [Cursor], _CXString),
+ ("clang_Cursor_hasAttrs", [Cursor], c_uint),
# ("clang_getCXTUResourceUsage",
# [TranslationUnit],
# CXTUResourceUsage),
diff --git a/clang/bindings/python/tests/cindex/test_cursor.py b/clang/bindings/python/tests/cindex/test_cursor.py
index c6aa65ce3c29f..9947f551cc2f8 100644
--- a/clang/bindings/python/tests/cindex/test_cursor.py
+++ b/clang/bindings/python/tests/cindex/test_cursor.py
@@ -4,6 +4,7 @@
AvailabilityKind,
BinaryOperator,
Config,
+ Cursor,
CursorKind,
PrintingPolicy,
PrintingPolicyProperty,
@@ -995,3 +996,42 @@ def test_pretty_print(self):
pp.set_property(PrintingPolicyProperty.Bool, False)
self.assertEqual(pp.get_property(PrintingPolicyProperty.Bool), False)
self.assertEqual(f.pretty_printed(pp), "void f(_Bool x) {\n}\n")
+
+ def test_has_attrs(self):
+ tu = get_tu(
+ """
+struct A;
+struct A final {};
+
+struct B;
+struct B {};
+""",
+ lang="cpp",
+ )
+ A = get_cursor(tu, "A")
+ B = get_cursor(tu, "B")
+ self.assertTrue(A.get_definition().has_attrs())
+ self.assertFalse(B.get_definition().has_attrs())
+
+ def test_hash(self):
+ def accumulate_cursors(cursor: Cursor, all_cursors: list[Cursor]):
+ all_cursors.append(cursor)
+ for child in cursor.get_children():
+ all_cursors = accumulate_cursors(child, all_cursors)
+ return all_cursors
+
+ tu = get_tu(kInput)
+ all_cursors = accumulate_cursors(tu.cursor, [])
+ cursor_hashes = set()
+ for cursor in all_cursors:
+ self.assertNotIn(hash(cursor), cursor_hashes)
+ cursor_hashes.add(hash(cursor))
+
+ def test_specialized_template(self):
+ tu = get_tu(kTemplateArgTest, lang="cpp")
+ foos = get_cursors(tu, "foo")
+ prime_foo = foos[1].specialized_template
+
+ self.assertNotEqual(foos[0], foos[1])
+ self.assertEqual(foos[0], prime_foo)
+ self.assertIsNone(tu.cursor.specialized_template)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a25808e36bd51..ab68be3702840 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -442,6 +442,12 @@ Sanitizers
Python Binding Changes
----------------------
+- Made ``Cursor`` hashable.
+- Added ``Cursor.has_attrs``, a binding for ``clang_Cursor_hasAttrs``, to check
+ whether a cursor has any attributes.
+- Added ``Cursor.specialized_template``, a binding for
+ ``clang_getSpecializedCursorTemplate``, to retrieve the primary template that
+ the cursor is a specialization of.
- Added ``Type.get_methods``, a binding for ``clang_visitCXXMethods``, which
allows visiting the methods of a class.
More information about the cfe-commits
mailing list