Implement a convenience recursive walk method over a cursor and its descendants.
authorEli Bendersky <eliben@google.com>
Thu, 29 May 2014 02:35:27 +0000 (02:35 +0000)
committerEli Bendersky <eliben@google.com>
Thu, 29 May 2014 02:35:27 +0000 (02:35 +0000)
Before r160106 there was a way to recursively visit all descendants of a cursor
via Cursor_visit, but it was removed. Since then, every user needs to
reimplement the recursive descent into get_children.

Adding a walk_preorder() method to Cursor that conveniently implements recursive
walking in a Pythonic way. This also greatly simplifies get_cursor and
get_cursors in tests/cindex/util.py (walk_preorder is now tested through these
utility functions, since they are used in many tests).

llvm-svn: 209793

clang/bindings/python/clang/cindex.py
clang/bindings/python/tests/cindex/util.py

index 779fa14..e03f7e6 100644 (file)
@@ -1391,6 +1391,16 @@ class Cursor(Structure):
             children)
         return iter(children)
 
+    def walk_preorder(self):
+        """Depth-first preorder walk over the cursor and its descendants.
+
+        Yields cursors.
+        """
+        yield self
+        for child in self.get_children():
+            for descendant in child.walk_preorder():
+                yield descendant
+
     def get_tokens(self):
         """Obtain Token instances formulating that compose this Cursor.
 
index 8614b02..c53ba7c 100644 (file)
@@ -39,52 +39,34 @@ def get_cursor(source, spelling):
 
     If the cursor is not found, None is returned.
     """
-    children = []
-    if isinstance(source, Cursor):
-        children = source.get_children()
-    else:
-        # Assume TU
-        children = source.cursor.get_children()
-
-    for cursor in children:
+    # Convenience for calling on a TU.
+    root_cursor = source if isinstance(source, Cursor) else source.cursor
+
+    for cursor in root_cursor.walk_preorder():
         if cursor.spelling == spelling:
             return cursor
 
-        # Recurse into children.
-        result = get_cursor(cursor, spelling)
-        if result is not None:
-            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
+    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.
     """
+    # Convenience for calling on a TU.
+    root_cursor = source if isinstance(source, Cursor) else source.cursor
+
     cursors = []
-    children = []
-    if isinstance(source, Cursor):
-        children = source.get_children()
-    else:
-        # Assume TU
-        children = source.cursor.get_children()
-
-    for cursor in children:
+    for cursor in root_cursor.walk_preorder():
         if cursor.spelling == spelling:
             cursors.append(cursor)
 
-        # Recurse into children.
-        cursors.extend(get_cursors(cursor, spelling))
-
     return cursors
 
-    
-    
 
 __all__ = [
     'get_cursor',