]> granicus.if.org Git - clang/commitdiff
[libclang] Introduce clang_Cursor_getSpellingNameRange().
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Fri, 30 Mar 2012 20:58:35 +0000 (20:58 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Fri, 30 Mar 2012 20:58:35 +0000 (20:58 +0000)
It retrieves a source range for a piece that forms the cursors spelling name.
Most of the times there is only one range for the complete spelling but for
objc methods and objc message expressions, there are multiple pieces for each
selector identifier.

Part of rdar://11113120

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

include/clang-c/Index.h
test/Index/get-cursor.m
tools/c-index-test/c-index-test.c
tools/libclang/CIndex.cpp
tools/libclang/libclang.exports

index 54f461b9a10525f051f532006ba28c3041cc666e..a65bb635b26b216e7332bc91da18859674a8c548 100644 (file)
@@ -2903,6 +2903,21 @@ CINDEX_LINKAGE CXString clang_constructUSR_ObjCProperty(const char *property,
  */
 CINDEX_LINKAGE CXString clang_getCursorSpelling(CXCursor);
 
+/**
+ * \brief Retrieve a range for a piece that forms the cursors spelling name.
+ * Most of the times there is only one range for the complete spelling but for
+ * objc methods and objc message expressions, there are multiple pieces for each
+ * selector identifier.
+ * 
+ * \param pieceIndex the index of the spelling name piece. If this is greater
+ * than the actual number of pieces, it will return a NULL (invalid) range.
+ *  
+ * \param options Reserved.
+ */
+CINDEX_LINKAGE CXSourceRange clang_Cursor_getSpellingNameRange(CXCursor,
+                                                          unsigned pieceIndex,
+                                                          unsigned options);
+
 /**
  * \brief Retrieve the display name for the entity referenced by this cursor.
  *
index ead18de0c019dfbddcf59842179e36ee9c2e2883..d73b23a18f1448aa1cec99e5628971f37096c61e 100644 (file)
@@ -52,6 +52,14 @@ void foo1(Test2 *test2) {
   ++test2.implicitProp;
 }
 
+@interface Test3
+-(void)setFoo:(int)x withBar:(int)y;
+@end
+
+void foo3(Test3 *test3) {
+  [test3 setFoo:2 withBar:4];
+}
+
 // RUN: c-index-test -cursor-at=%s:4:28 -cursor-at=%s:5:28 %s | FileCheck -check-prefix=CHECK-PROP %s
 // CHECK-PROP: ObjCPropertyDecl=foo1:4:26
 // CHECK-PROP: ObjCPropertyDecl=foo2:5:27
@@ -68,7 +76,12 @@ void foo1(Test2 *test2) {
 // RUN: c-index-test -cursor-at=%s:38:6 -cursor-at=%s:40:11 \
 // RUN:   -cursor-at=%s:50:20 -cursor-at=%s:51:15 -cursor-at=%s:52:20 %s | FileCheck -check-prefix=CHECK-MEMBERREF %s
 // CHECK-MEMBERREF: 38:6 MemberRefExpr=x:34:16 SingleRefName=[38:6 - 38:7] RefName=[38:6 - 38:7] Extent=[38:3 - 38:7]
-// CHECK-MEMBERREF: 40:9 MemberRefExpr=name:23:21 Extent=[40:3 - 40:13] Spelling=name
-// CHECK-MEMBERREF: 50:17 MemberRefExpr=implicitProp:45:7 Extent=[50:11 - 50:29] Spelling=implicitProp
-// CHECK-MEMBERREF: 51:9 MemberRefExpr=setImplicitProp::46:8 Extent=[51:3 - 51:21]
-// CHECK-MEMBERREF: 52:11 MemberRefExpr=setImplicitProp::46:8 Extent=[52:5 - 52:23]
+// CHECK-MEMBERREF: 40:9 MemberRefExpr=name:23:21 Extent=[40:3 - 40:13] Spelling=name ([40:9 - 40:13])
+// CHECK-MEMBERREF: 50:17 MemberRefExpr=implicitProp:45:7 Extent=[50:11 - 50:29] Spelling=implicitProp ([50:17 - 50:29])
+// CHECK-MEMBERREF: 51:9 MemberRefExpr=setImplicitProp::46:8 Extent=[51:3 - 51:21] Spelling=setImplicitProp: ([51:9 - 51:21])
+// CHECK-MEMBERREF: 52:11 MemberRefExpr=setImplicitProp::46:8 Extent=[52:5 - 52:23] Spelling=setImplicitProp: ([52:11 - 52:23])
+
+// RUN: c-index-test -cursor-at=%s:56:24 -cursor-at=%s:60:14 \
+// RUN:   %s | FileCheck -check-prefix=CHECK-SPELLRANGE %s
+// CHECK-SPELLRANGE: 56:8 ObjCInstanceMethodDecl=setFoo:withBar::56:8 Extent=[56:1 - 56:37] Spelling=setFoo:withBar: ([56:8 - 56:14][56:22 - 56:29])
+// CHECK-SPELLRANGE: 60:3 ObjCMessageExpr=setFoo:withBar::56:8 Extent=[60:3 - 60:29] Spelling=setFoo:withBar: ([60:10 - 60:16][60:19 - 60:26])
index 5dd925463133655a0e77d11d04b20e6113491050..e774e78086c5be687b031c0049e9367c2c2cce66 100644 (file)
@@ -171,7 +171,8 @@ static void PrintRange(CXSourceRange R, const char *str) {
   if (!begin_file || !end_file)
     return;
 
-  printf(" %s=", str);
+  if (str)
+    printf(" %s=", str);
   PrintExtent(stdout, begin_line, begin_column, end_line, end_column);
 }
 
@@ -1449,8 +1450,19 @@ static int inspect_cursor_at(int argc, const char **argv) {
         PrintCursorExtent(Cursor);
         Spelling = clang_getCursorSpelling(Cursor);
         cspell = clang_getCString(Spelling);
-        if (cspell && strlen(cspell) != 0)
-          printf(" Spelling=%s", cspell);
+        if (cspell && strlen(cspell) != 0) {
+          unsigned pieceIndex;
+          CXSourceRange range, extent;
+          extent = clang_getCursorExtent(Cursor);
+          printf(" Spelling=%s (", cspell);
+          for (pieceIndex = 0; ; ++pieceIndex) {
+            range = clang_Cursor_getSpellingNameRange(Cursor, pieceIndex, 0);
+            if (clang_Range_isNull(range))
+              break;
+            PrintRange(range, 0);
+          }
+          printf(")");
+        }
         clang_disposeString(Spelling);
         if (completionString != NULL) {
           printf("\nCompletion string: ");
index 2a05b1b6f7282ad8fc90825fd20a2d8553244d71..c63a969fe46d7a49fd7bea9b389f82a92937c2ba 100644 (file)
@@ -3167,6 +3167,63 @@ CXString clang_getCursorSpelling(CXCursor C) {
   return createCXString("");
 }
 
+CXSourceRange clang_Cursor_getSpellingNameRange(CXCursor C,
+                                                unsigned pieceIndex,
+                                                unsigned options) {
+  if (clang_Cursor_isNull(C))
+    return clang_getNullRange();
+
+  ASTContext &Ctx = getCursorContext(C);
+
+  if (clang_isStatement(C.kind)) {
+    Stmt *S = getCursorStmt(C);
+    if (LabelStmt *Label = dyn_cast_or_null<LabelStmt>(S)) {
+      if (pieceIndex > 0)
+        return clang_getNullRange();
+      return cxloc::translateSourceRange(Ctx, Label->getIdentLoc());
+    }
+
+    return clang_getNullRange();
+  }
+
+  if (C.kind == CXCursor_ObjCMessageExpr) {
+    if (ObjCMessageExpr *
+          ME = dyn_cast_or_null<ObjCMessageExpr>(getCursorExpr(C))) {
+      if (pieceIndex >= ME->getNumSelectorLocs())
+        return clang_getNullRange();
+      return cxloc::translateSourceRange(Ctx, ME->getSelectorLoc(pieceIndex));
+    }
+  }
+
+  if (C.kind == CXCursor_ObjCInstanceMethodDecl ||
+      C.kind == CXCursor_ObjCClassMethodDecl) {
+    if (ObjCMethodDecl *
+          MD = dyn_cast_or_null<ObjCMethodDecl>(getCursorDecl(C))) {
+      if (pieceIndex >= MD->getNumSelectorLocs())
+        return clang_getNullRange();
+      return cxloc::translateSourceRange(Ctx, MD->getSelectorLoc(pieceIndex));
+    }
+  }
+
+  // FIXME: A CXCursor_InclusionDirective should give the location of the
+  // filename, but we don't keep track of this.
+
+  // FIXME: A CXCursor_AnnotateAttr should give the location of the annotation
+  // but we don't keep track of this.
+
+  // FIXME: A CXCursor_AsmLabelAttr should give the location of the label
+  // but we don't keep track of this.
+
+  // Default handling, give the location of the cursor.
+
+  if (pieceIndex > 0)
+    return clang_getNullRange();
+
+  CXSourceLocation CXLoc = clang_getCursorLocation(C);
+  SourceLocation Loc = cxloc::translateSourceLocation(CXLoc);
+  return cxloc::translateSourceRange(Ctx, Loc);
+}
+
 CXString clang_getCursorDisplayName(CXCursor C) {
   if (!clang_isDeclaration(C.kind))
     return clang_getCursorSpelling(C);
index 21861fb7097cb1d70ffc2a12420d164795e685ed..2fe3f1d53c6c08de3a6e3db37e8dcecd30bdcf29 100644 (file)
@@ -4,6 +4,7 @@ clang_CXIndex_getGlobalOptions
 clang_CXIndex_setGlobalOptions
 clang_CXXMethod_isStatic
 clang_CXXMethod_isVirtual
+clang_Cursor_getSpellingNameRange
 clang_Cursor_getTranslationUnit
 clang_Cursor_isNull
 clang_IndexAction_create