[clang] [libclang/python] Add typing annotations for the Cursor class (PR #138103)

Vlad Serebrennikov via cfe-commits cfe-commits at lists.llvm.org
Wed May 7 02:00:19 PDT 2025


================
@@ -1913,7 +1916,7 @@ def type(self):
         return self._type
 
     @property
-    def canonical(self):
+    def canonical(self) -> Cursor | None:
         """Return the canonical Cursor corresponding to this Cursor.
----------------
Endilll wrote:

> That said, the input to it comes from clang_getCanonicalCursor which does not seem to ever return the Null-Cursor

Are you sure? It seems that if you pass null cursor to it, you get null cursor back: https://github.com/llvm/llvm-project/blob/ec29f83a02841bb61df88f5fede0054f18c1b367/clang/tools/libclang/CIndex.cpp#L7438-L7440

> so we could theoretically constrain the return type here to just Cursor, by asserting isinstance(the_return_value, Cursor), but this is a bit ugly... what do you think?

Looking at `Cursor.from_cursor_result` and `Cursor.from_result`, it seems that Python bindings make a serious effort to map null cursor to `None`. Which means there should be no way to call `Cursor` methods on a null cursor. Which means that `clang_getCanonicalCursor` will never return null cursor back. So I agree that we should drop `| None` part of type hint.

Instead of the assert you propose, I think all `Cursor` methods should assert that `self` is not a null cursor, and ideally avoid calling `getNullCursor` on every method invocation. That said, we're already are not shy to call it in `from_result` and `from_cursor_result`, so it might be an acceptable overhead.

https://github.com/llvm/llvm-project/pull/138103


More information about the cfe-commits mailing list