diff options
-rw-r--r-- | include/clang-c/Index.h | 15 | ||||
-rw-r--r-- | test/Index/get-cursor.m | 21 | ||||
-rw-r--r-- | tools/c-index-test/c-index-test.c | 18 | ||||
-rw-r--r-- | tools/libclang/CIndex.cpp | 57 | ||||
-rw-r--r-- | tools/libclang/libclang.exports | 1 |
5 files changed, 105 insertions, 7 deletions
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index 54f461b9a1..a65bb635b2 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -2904,6 +2904,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. * * The display name contains extra information that helps identify the cursor, diff --git a/test/Index/get-cursor.m b/test/Index/get-cursor.m index ead18de0c0..d73b23a18f 100644 --- a/test/Index/get-cursor.m +++ b/test/Index/get-cursor.m @@ -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]) diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index 5dd9254631..e774e78086 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -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: "); diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 2a05b1b6f7..c63a969fe4 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -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); diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports index 21861fb709..2fe3f1d53c 100644 --- a/tools/libclang/libclang.exports +++ b/tools/libclang/libclang.exports @@ -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 |