- Adding lexical_parent and semantic_parent properties to clang.cindex.Cursor
- Two new tests (one for each property), require libclang built from r155858 or later to pass
- New test utility function (get_cursors) that gets all the nodes with a specific spelling.
Patch by Evan Pipho.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@156286 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/bindings/python/clang/cindex.py b/bindings/python/clang/cindex.py
index d988e76..a88c12b 100644
--- a/bindings/python/clang/cindex.py
+++ b/bindings/python/clang/cindex.py
@@ -1047,6 +1047,22 @@
return self._hash
+ @property
+ def semantic_parent(self):
+ """Return the semantic parent for this cursor."""
+ if not hasattr(self, '_semantic_parent'):
+ self._semantic_parent = Cursor_semantic_parent(self)
+
+ return self._semantic_parent
+
+ @property
+ def lexical_parent(self):
+ """Return the lexical parent for this cursor."""
+ if not hasattr(self, '_lexical_parent'):
+ self._lexical_parent = Cursor_lexical_parent(self)
+
+ return self._lexical_parent
+
def get_children(self):
"""Return an iterator for accessing the children of this cursor."""
@@ -1974,6 +1990,16 @@
Cursor_objc_type_encoding.restype = _CXString
Cursor_objc_type_encoding.errcheck = _CXString.from_result
+Cursor_semantic_parent = lib.clang_getCursorSemanticParent
+Cursor_semantic_parent.argtypes = [Cursor]
+Cursor_semantic_parent.restype = Cursor
+Cursor_semantic_parent.errcheck = Cursor.from_result
+
+Cursor_lexical_parent = lib.clang_getCursorLexicalParent
+Cursor_lexical_parent.argtypes = [Cursor]
+Cursor_lexical_parent.restype = Cursor
+Cursor_lexical_parent.errcheck = Cursor.from_result
+
Cursor_visit_callback = CFUNCTYPE(c_int, Cursor, Cursor, py_object)
Cursor_visit = lib.clang_visitChildren
Cursor_visit.argtypes = [Cursor, Cursor_visit_callback, py_object]
diff --git a/bindings/python/tests/cindex/test_cursor.py b/bindings/python/tests/cindex/test_cursor.py
index 0582d2a..8b12f8d 100644
--- a/bindings/python/tests/cindex/test_cursor.py
+++ b/bindings/python/tests/cindex/test_cursor.py
@@ -1,6 +1,7 @@
from clang.cindex import CursorKind
from clang.cindex import TypeKind
from .util import get_cursor
+from .util import get_cursors
from .util import get_tu
kInput = """\
@@ -75,6 +76,30 @@
underlying = typedef.underlying_typedef_type
assert underlying.kind == TypeKind.INT
+kParentTest = """\
+ class C {
+ void f();
+ }
+
+ void C::f() { }
+ """
+def test_semantic_parent():
+ tu = get_tu(kParentTest, 'cpp')
+ curs = get_cursors(tu, 'f')
+ decl = get_cursor(tu, 'C')
+ assert(len(curs) == 2)
+ assert(curs[0].semantic_parent == curs[1].semantic_parent)
+ assert(curs[0].semantic_parent == decl)
+
+def test_lexical_parent():
+ tu = get_tu(kParentTest, 'cpp')
+ curs = get_cursors(tu, 'f')
+ decl = get_cursor(tu, 'C')
+ assert(len(curs) == 2)
+ assert(curs[0].lexical_parent != curs[1].lexical_parent)
+ assert(curs[0].lexical_parent == decl)
+ assert(curs[1].lexical_parent == tu.cursor)
+
def test_enum_type():
tu = get_tu('enum TEST { FOO=1, BAR=2 };')
enum = get_cursor(tu, 'TEST')
diff --git a/bindings/python/tests/cindex/util.py b/bindings/python/tests/cindex/util.py
index f924094..e945aea 100644
--- a/bindings/python/tests/cindex/util.py
+++ b/bindings/python/tests/cindex/util.py
@@ -58,9 +58,38 @@
return result
return None
+
+def get_cursors(source, spelling):
+ """Obtain all cursors from a source object with a specific spelling.
+ This provides a convenient search mechanism to find all cursors with specific
+ spelling within a source. The first argument can be either a
+ TranslationUnit or Cursor instance.
+
+ If no cursors are found, an empty list is returned.
+ """
+ cursors = []
+ children = []
+ if isinstance(source, Cursor):
+ children = source.get_children()
+ else:
+ # Assume TU
+ children = source.cursor.get_children()
+
+ for cursor in children:
+ if cursor.spelling == spelling:
+ cursors.append(cursor)
+
+ # Recurse into children.
+ cursors.extend(get_cursors(cursor, spelling))
+
+ return cursors
+
+
+
__all__ = [
'get_cursor',
+ 'get_cursors',
'get_tu',
]