arthurp created this revision.
arthurp added a reviewer: ilya-biryukov.
Herald added subscribers: cfe-commits, arphaman.
Herald added a project: clang.
arthurp added a comment.

This is my first new revision here, and I guessed on the review based solely on 
resent reviews of related code. Please correct me as needed. Thanks.


Add a python method to Cursor to access clang_getCursorReferenceNameRange 
which was already included in the C function list of the python binding.
Also add required constants and a test.

This revision only changes the python binding and does not touch the
underlying C code at all.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D70358

Files:
  clang/bindings/python/clang/cindex.py
  clang/bindings/python/tests/cindex/test_cursor.py
  clang/bindings/python/tests/cindex/util.py

Index: clang/bindings/python/tests/cindex/util.py
===================================================================
--- clang/bindings/python/tests/cindex/util.py
+++ clang/bindings/python/tests/cindex/util.py
@@ -58,6 +58,18 @@
 
     return None
 
+
+def get_subcursor_by_path(cursor, *path):
+    """Obtain a cursor by following the path provided from cursor.
+
+    path is a series of ints specifying which child to select.
+    """
+
+    if path:
+        return get_subcursor_by_path(list(cursor.get_children())[path[0]], *path[1:])
+    else:
+        return cursor
+
 def get_cursors(source, spelling):
     """Obtain all cursors from a source object with a specific spelling.
 
@@ -84,6 +96,7 @@
 __all__ = [
     'get_cursor',
     'get_cursors',
+    'get_subcursor_by_path',
     'get_tu',
     'skip_if_no_fspath',
     'str_to_path',
Index: clang/bindings/python/tests/cindex/test_cursor.py
===================================================================
--- clang/bindings/python/tests/cindex/test_cursor.py
+++ clang/bindings/python/tests/cindex/test_cursor.py
@@ -9,10 +9,14 @@
 
 from clang.cindex import AvailabilityKind
 from clang.cindex import CursorKind
+from clang.cindex import Cursor
 from clang.cindex import TemplateArgumentKind
 from clang.cindex import TranslationUnit
 from clang.cindex import TypeKind
+from clang.cindex import SourceRange
+from clang.cindex import SourceLocation
 from .util import get_cursor
+from .util import get_subcursor_by_path
 from .util import get_cursors
 from .util import get_tu
 
@@ -53,6 +57,37 @@
         void foo<-7, float, true>();
     """
 
+kCPPReferenceNameRangeTest = """\
+void baz();
+
+class C {
+public:
+    void foo();
+    template <typename T>
+    void bar(T v) { }
+    int operator[](int i) { return i; }
+};
+
+void ref1() {
+    baz();
+}
+
+void ref2() {
+    C x;
+    x.C::foo();
+}
+
+void ref3() {
+    C x;
+    x.bar<const char*>("str");
+}
+
+void ref4() {
+    C x;
+    x[1];
+}
+    """
+
 class TestCursor(unittest.TestCase):
     def test_get_children(self):
         tu = get_tu(kInput)
@@ -554,6 +589,30 @@
                 self.assertEqual(c.referenced.spelling, foo.spelling)
                 break
 
+    def test_get_reference_name_range(self):
+        tu = get_tu(kCPPReferenceNameRangeTest, lang='cpp')
+
+        c = get_subcursor_by_path(get_cursor(tu, 'ref1'), 0, 0)
+        self.assertEqual(c.get_reference_name_range(0, 0),
+                         tu.get_extent("t.cpp", ((12, 5), (12, 10))))
+
+        c = get_subcursor_by_path(get_cursor(tu, 'ref2'), 0, 1)
+        self.assertEqual(c.get_reference_name_range(Cursor.NAME_RANGE_WANT_QUALIFIER, 0),
+                         tu.get_extent("t.cpp", ((17, 5), (17, 15))))
+
+        c = get_subcursor_by_path(get_cursor(tu, 'ref3'), 0, 1)
+        self.assertEqual(c.get_reference_name_range(Cursor.NAME_RANGE_WANT_TEMPLATE_ARGS, 0),
+                         tu.get_extent("t.cpp", ((22, 5), (22, 30))))
+
+        c = get_subcursor_by_path(get_cursor(tu, 'ref4'), 0, 1)
+        self.assertEqual(c.get_reference_name_range(0, 0),
+                         tu.get_extent("t.cpp", ((27, 6), (27, 7))))
+        self.assertEqual(c.get_reference_name_range(0, 1),
+                         tu.get_extent("t.cpp", ((27, 8), (27, 9))))
+        self.assertEqual(c.get_reference_name_range(Cursor.NAME_RANGE_WANT_SINGLE_PIECE, 0),
+                         tu.get_extent("t.cpp", ((27, 6), (27, 9))))
+
+
     def test_mangled_name(self):
         kInputForMangling = """\
         int foo(int, int);
Index: clang/bindings/python/clang/cindex.py
===================================================================
--- clang/bindings/python/clang/cindex.py
+++ clang/bindings/python/clang/cindex.py
@@ -1419,6 +1419,20 @@
     """
     _fields_ = [("_kind_id", c_int), ("xdata", c_int), ("data", c_void_p * 3)]
 
+    # Include the nested-name-specifier, e.g. Foo:: in x.Foo::y, in the range.
+    NAME_RANGE_WANT_QUALIFIER = 0x1
+
+    # Include the explicit template arguments, e.g. <int> in x.f<int>, in the range.
+    NAME_RANGE_WANT_TEMPLATE_ARGS = 0x2
+
+    # If the name is non-contiguous, return the full spanning range.
+    # Non-contiguous names occur in Objective-C when a selector with two or
+    # more parameters is used, or in C++ when using an operator:
+    #
+    #   [object doSomething:here withValue:there]; // Objective-C
+    #   return some_vector[1]; // C++
+    NAME_RANGE_WANT_SINGLE_PIECE = 0x4
+
     @staticmethod
     def from_location(tu, location):
         # We store a reference to the TU in the instance so the TU won't get
@@ -1824,6 +1838,20 @@
         """Returns the value of the indicated arg as an unsigned 64b integer."""
         return conf.lib.clang_Cursor_getTemplateArgumentUnsignedValue(self, num)
 
+    def get_reference_name_range(self, name_flags, piece_index):
+        """Return the source range covering the reference at this cursor, if applicable.
+
+        name_flags is a bitset of the three independent flags: NAME_RANGE_WANT_QUALIFIER,
+        NAME_RANGE_WANT_TEMPLATE_ARGS, NAME_RANGE_WANT_SINGLE_PIECE.
+
+        piece_index identifies a piece of the overall reference. For contiguous names
+        or when passing the flag NAME_RANGE_WANT_SINGLE_PIECE, only one piece with index
+        0 is available. When the NAME_RANGE_WANT_SINGLE_PIECE flag is not passed for a
+        non-contiguous names, this index can be used to retrieve the individual pieces
+        of the name.
+        """
+        return conf.lib.clang_getCursorReferenceNameRange(self, name_flags, piece_index)
+
     def get_children(self):
         """Return an iterator for accessing the children of this cursor."""
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to