]> granicus.if.org Git - clang/commitdiff
[libclang, bindings]: add spelling location
authorMasud Rahman <llvm@masudrahman.com>
Sat, 21 Oct 2017 20:53:49 +0000 (20:53 +0000)
committerMasud Rahman <llvm@masudrahman.com>
Sat, 21 Oct 2017 20:53:49 +0000 (20:53 +0000)
 o) Add a 'Location' class that represents the four properties of a
    physical location

 o) Enhance 'SourceLocation' to provide 'expansion' and 'spelling'
    locations, maintaining backwards compatibility with existing code by
    forwarding the four properties to 'expansion'.

 o) Update the implementation to use 'clang_getExpansionLocation'
    instead of the deprecated 'clang_getInstantiationLocation', which
    has been present since 2011.

 o) Update the implementation of 'clang_getSpellingLocation' to actually
    obtain spelling location instead of file location.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@316278 91177308-0d34-0410-b5e6-96231b3b80d8

bindings/python/clang/cindex.py
bindings/python/tests/cindex/test_location.py
tools/libclang/CXSourceLocation.cpp

index d72dd14ef9f30e9e115454f92c365f0e17fbc96f..3f70bba493c776c5f40d66a5629d4a3254fbdad7 100644 (file)
@@ -214,25 +214,45 @@ class _CXString(Structure):
         assert isinstance(res, _CXString)
         return conf.lib.clang_getCString(res)
 
+class Location(object):
+    """A Location is a specific kind of source location.  A SourceLocation
+    refers to several kinds of locations (e.g.  spelling location vs. expansion
+    location)."""
+
+    def __init__(self, file, line, column, offset):
+        self._file   = File(file) if file else None
+        self._line   = int(line.value)
+        self._column = int(column.value)
+        self._offset = int(offset.value)
+
+
+    @property
+    def file(self):
+        """Get the file represented by this source location."""
+        return self._file
+
+    @property
+    def line(self):
+        """Get the line represented by this source location."""
+        return self._line
+
+    @property
+    def column(self):
+        """Get the column represented by this source location."""
+        return self._column
+
+    @property
+    def offset(self):
+        """Get the file offset represented by this source location."""
+        return self._offset
 
 class SourceLocation(Structure):
     """
     A SourceLocation represents a particular location within a source file.
     """
     _fields_ = [("ptr_data", c_void_p * 2), ("int_data", c_uint)]
-    _data = None
-
-    def _get_instantiation(self):
-        if self._data is None:
-            f, l, c, o = c_object_p(), c_uint(), c_uint(), c_uint()
-            conf.lib.clang_getInstantiationLocation(self, byref(f), byref(l),
-                    byref(c), byref(o))
-            if f:
-                f = File(f)
-            else:
-                f = None
-            self._data = (f, int(l.value), int(c.value), int(o.value))
-        return self._data
+    _expansion = None
+    _spelling = None
 
     @staticmethod
     def from_position(tu, file, line, column):
@@ -252,25 +272,73 @@ class SourceLocation(Structure):
         """
         return conf.lib.clang_getLocationForOffset(tu, file, offset)
 
+    @property
+    def expansion(self):
+        """
+        The source location where then entity this object is referring to is
+        expanded.
+        """
+        if not self._expansion:
+            file   = c_object_p()
+            line   = c_uint()
+            column = c_uint()
+            offset = c_uint()
+            conf.lib.clang_getExpansionLocation(self,
+                                                byref(file),
+                                                byref(line),
+                                                byref(column),
+                                                byref(offset))
+
+            self._expansion = Location(file, line, column, offset)
+        return self._expansion
+
+    @property
+    def spelling(self):
+        """
+        The source location where then entity this object is referring to is
+        written.
+        """
+        if not self._spelling:
+            file   = c_object_p()
+            line   = c_uint()
+            column = c_uint()
+            offset = c_uint()
+            conf.lib.clang_getSpellingLocation(self,
+                                               byref(file),
+                                               byref(line),
+                                               byref(column),
+                                               byref(offset))
+
+            self._spelling = Location(file, line, column, offset)
+        return self._spelling
+
     @property
     def file(self):
-        """Get the file represented by this source location."""
-        return self._get_instantiation()[0]
+        """Get the file represented by this source location.
+
+        DEPRECATED: use expansion.file."""
+        return self.expansion.file
 
     @property
     def line(self):
-        """Get the line represented by this source location."""
-        return self._get_instantiation()[1]
+        """Get the line represented by this source location.
+
+        DEPRECATED: use expansion.line."""
+        return self.expansion.line
 
     @property
     def column(self):
-        """Get the column represented by this source location."""
-        return self._get_instantiation()[2]
+        """Get the column represented by this source location.
+
+        DEPRECATED: use expansion.column."""
+        return self.expansion.column
 
     @property
     def offset(self):
-        """Get the file offset represented by this source location."""
-        return self._get_instantiation()[3]
+        """Get the file offset represented by this source location.
+
+        DEPRECATED: use expansion.offset."""
+        return self.expansion.offset
 
     def __eq__(self, other):
         return conf.lib.clang_equalLocations(self, other)
@@ -1543,8 +1611,7 @@ class Cursor(Structure):
     @property
     def location(self):
         """
-        Return the source location (the starting character) of the entity
-        pointed at by the cursor.
+        Return the source locations of the entity pointed at by the cursor.
         """
         if not hasattr(self, '_loc'):
             self._loc = conf.lib.clang_getCursorLocation(self)
@@ -3692,7 +3759,11 @@ functionList = [
   ("clang_getInclusions",
    [TranslationUnit, callbacks['translation_unit_includes'], py_object]),
 
-  ("clang_getInstantiationLocation",
+  ("clang_getExpansionLocation",
+   [SourceLocation, POINTER(c_object_p), POINTER(c_uint), POINTER(c_uint),
+    POINTER(c_uint)]),
+
+  ("clang_getSpellingLocation",
    [SourceLocation, POINTER(c_object_p), POINTER(c_uint), POINTER(c_uint),
     POINTER(c_uint)]),
 
@@ -4154,6 +4225,7 @@ __all__ = [
     'FixIt',
     'Index',
     'LinkageKind',
+    'Location',
     'SourceLocation',
     'SourceRange',
     'TLSKind',
index 9e9ef487af18e03f73c8e1de0403cf906e14f2d6..d6875330ec60fcbba2f47d4dfb23097835ba4c9c 100644 (file)
@@ -93,3 +93,10 @@ def test_extent():
     location3 = SourceLocation.from_position(tu, file, 1, 6)
     range3 = SourceRange.from_locations(location1, location3)
     assert range1 != range3
+
+def test_spelling_location():
+    tu = get_tu('''#define ONE int one
+ONE;''')
+    one = get_cursor(tu, 'one')
+    assert one.location.spelling.line == 1
+    assert one.location.expansion.line == 2
index 2e0ea4e440999ecb6955367653d18a70089246e5..b1637e01abb8df4c121c63cd0e551646296d5dfc 100644 (file)
@@ -318,8 +318,7 @@ void clang_getSpellingLocation(CXSourceLocation location,
   
   const SourceManager &SM =
   *static_cast<const SourceManager*>(location.ptr_data[0]);
-  // FIXME: This should call SourceManager::getSpellingLoc().
-  SourceLocation SpellLoc = SM.getFileLoc(Loc);
+  SourceLocation SpellLoc = SM.getSpellingLoc(Loc);
   std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(SpellLoc);
   FileID FID = LocInfo.first;
   unsigned FileOffset = LocInfo.second;