There is no type checking in __eq__, so ctypes will throw if the wrong
Python type is passed in to the C function. Personally, I feel garbage
in means garbage out and it isn't worth testing for this explicitly.

---
 bindings/python/clang/cindex.py               |   20 ++++++++++++++++++++
 bindings/python/tests/cindex/test_location.py |   20 +++++++++++++++++++-
 2 files changed, 39 insertions(+), 1 deletions(-)
diff --git a/bindings/python/clang/cindex.py b/bindings/python/clang/cindex.py
index 48a107c..474740a 100644
--- a/bindings/python/clang/cindex.py
+++ b/bindings/python/clang/cindex.py
@@ -141,16 +141,22 @@ class SourceLocation(Structure):
         """Get the column represented by this source location."""
         return self._get_instantiation()[2]
 
     @property
     def offset(self):
         """Get the file offset represented by this source location."""
         return self._get_instantiation()[3]
 
+    def __eq__(self, other):
+        return SourceLocation_equalLocations(self, other)
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
     def __repr__(self):
         if self.file:
             filename = self.file.name
         else:
             filename = None
         return "<SourceLocation file %r, line %r, column %r>" % (
             filename, self.line, self.column)
 
@@ -181,16 +187,22 @@ class SourceRange(Structure):
     @property
     def end(self):
         """
         Return a SourceLocation representing the last character within a
         source range.
         """
         return SourceRange_end(self)
 
+    def __eq__(self, other):
+        return SourceRange_equalRanges(self, other)
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
     def __repr__(self):
         return "<SourceRange start %r, end %r>" % (self.start, self.end)
 
 class Diagnostic(object):
     """
     A Diagnostic is a single instance of a Clang diagnostic. It includes the
     diagnostic severity, the message, the location the diagnostic occurred, as
     well as additional source ranges and associated fix-it hints.
@@ -1608,29 +1620,37 @@ SourceLocation_loc = lib.clang_getInstantiationLocation
 SourceLocation_loc.argtypes = [SourceLocation, POINTER(c_object_p),
                                POINTER(c_uint), POINTER(c_uint),
                                POINTER(c_uint)]
 
 SourceLocation_getLocation = lib.clang_getLocation
 SourceLocation_getLocation.argtypes = [TranslationUnit, File, c_uint, c_uint]
 SourceLocation_getLocation.restype = SourceLocation
 
+SourceLocation_equalLocations = lib.clang_equalLocations
+SourceLocation_equalLocations.argtypes = [SourceLocation, SourceLocation]
+SourceLocation_equalLocations.restype = bool
+
 # Source Range Functions
 SourceRange_getRange = lib.clang_getRange
 SourceRange_getRange.argtypes = [SourceLocation, SourceLocation]
 SourceRange_getRange.restype = SourceRange
 
 SourceRange_start = lib.clang_getRangeStart
 SourceRange_start.argtypes = [SourceRange]
 SourceRange_start.restype = SourceLocation
 
 SourceRange_end = lib.clang_getRangeEnd
 SourceRange_end.argtypes = [SourceRange]
 SourceRange_end.restype = SourceLocation
 
+SourceRange_equalRanges = lib.clang_equalRanges
+SourceRange_equalRanges.argtypes = [SourceRange, SourceRange]
+SourceRange_equalRanges.restype = bool
+
 # CursorKind Functions
 CursorKind_is_decl = lib.clang_isDeclaration
 CursorKind_is_decl.argtypes = [CursorKind]
 CursorKind_is_decl.restype = bool
 
 CursorKind_is_ref = lib.clang_isReference
 CursorKind_is_ref.argtypes = [CursorKind]
 CursorKind_is_ref.restype = bool
diff --git a/bindings/python/tests/cindex/test_location.py b/bindings/python/tests/cindex/test_location.py
index 300136f..1707f01 100644
--- a/bindings/python/tests/cindex/test_location.py
+++ b/bindings/python/tests/cindex/test_location.py
@@ -1,9 +1,9 @@
-from clang.cindex import Index, File, SourceLocation, Cursor
+from clang.cindex import Index, File, SourceLocation, SourceRange, Cursor
 
 baseInput="int one;\nint two;\n"
 
 def assert_location(loc, line, column, offset):
     assert loc.line == line
     assert loc.column == column
     assert loc.offset == offset
 
@@ -42,21 +42,39 @@ def test_location():
     file = File.from_name(tu, 't.c')
     location = SourceLocation.from_position(tu, file, 1, 5)
     cursor = Cursor.from_location(tu, location)
 
     for n in tu.cursor.get_children():
         if n.spelling == 'one':
             assert n == cursor
 
+    # Ensure locations referring to the same entity are equivalent.
+    location2 = SourceLocation.from_position(tu, file, 1, 5)
+    assert location == location2
+    location3 = SourceLocation.from_position(tu, file, 1, 4)
+    assert location2 != location3
+
 def test_extent():
     index = Index.create()
     tu = index.parse('t.c', unsaved_files = [('t.c',baseInput)])
 
     for n in tu.cursor.get_children():
         if n.spelling == 'one':
             assert_location(n.extent.start,line=1,column=1,offset=0)
             assert_location(n.extent.end,line=1,column=8,offset=7)
             assert baseInput[n.extent.start.offset:n.extent.end.offset] == "int one"
         if n.spelling == 'two':
             assert_location(n.extent.start,line=2,column=1,offset=9)
             assert_location(n.extent.end,line=2,column=8,offset=16)
             assert baseInput[n.extent.start.offset:n.extent.end.offset] == "int two"
+
+    file = File.from_name(tu, 't.c')
+    location1 = SourceLocation.from_position(tu, file, 1, 1)
+    location2 = SourceLocation.from_position(tu, file, 1, 8)
+
+    range1 = SourceRange.from_locations(location1, location2)
+    range2 = SourceRange.from_locations(location1, location2)
+    assert range1 == range2
+
+    location3 = SourceLocation.from_position(tu, file, 1, 6)
+    range3 = SourceRange.from_locations(location1, location3)
+    assert range1 != range3
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to