[libclang] Introduce clang_findReferencesInFile which accepts a cursor, a file,
and a callback and finds all identifier references of the cursor in the file.
rdar://7948304
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@141277 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c
index 33044e3..69a179f 100644
--- a/tools/c-index-test/c-index-test.c
+++ b/tools/c-index-test/c-index-test.c
@@ -175,7 +175,8 @@
int want_display_name = 0;
-static void PrintCursor(CXTranslationUnit TU, CXCursor Cursor) {
+static void PrintCursor(CXCursor Cursor) {
+ CXTranslationUnit TU = clang_Cursor_getTranslationUnit(Cursor);
if (clang_isInvalid(Cursor.kind)) {
CXString ks = clang_getCursorKindSpelling(Cursor.kind);
printf("Invalid Cursor => %s", clang_getCString(ks));
@@ -463,7 +464,7 @@
clang_getSpellingLocation(Loc, 0, &line, &column, 0);
printf("// %s: %s:%d:%d: ", FileCheckPrefix,
GetCursorSource(Cursor), line, column);
- PrintCursor(Data->TU, Cursor);
+ PrintCursor(Cursor);
PrintCursorExtent(Cursor);
printf("\n");
return CXChildVisit_Recurse;
@@ -516,7 +517,7 @@
} else if (Ref.kind != CXCursor_FunctionDecl) {
printf("// %s: %s:%d:%d: ", FileCheckPrefix, GetCursorSource(Ref),
curLine, curColumn);
- PrintCursor(Data->TU, Ref);
+ PrintCursor(Ref);
printf("\n");
}
}
@@ -605,7 +606,7 @@
}
if (linkage) {
- PrintCursor(Data->TU, cursor);
+ PrintCursor(cursor);
printf("linkage=%s\n", linkage);
}
@@ -623,7 +624,7 @@
if (!clang_isInvalid(clang_getCursorKind(cursor))) {
CXType T = clang_getCursorType(cursor);
CXString S = clang_getTypeKindSpelling(T.kind);
- PrintCursor(Data->TU, cursor);
+ PrintCursor(cursor);
printf(" typekind=%s", clang_getCString(S));
if (clang_isConstQualifiedType(T))
printf(" const");
@@ -836,7 +837,7 @@
printf("-%s", prefix);
PrintExtent(stdout, start_line, start_col, end_line, end_col);
printf(" ");
- PrintCursor(TU, cursor);
+ PrintCursor(cursor);
printf("\n");
}
@@ -1275,7 +1276,7 @@
unsigned column;
} CursorSourceLocation;
-int inspect_cursor_at(int argc, const char **argv) {
+static int inspect_cursor_at(int argc, const char **argv) {
CXIndex CIdx;
int errorCode;
struct CXUnsavedFile *unsaved_files = 0;
@@ -1344,7 +1345,7 @@
if (I + 1 == Repeats) {
CXCompletionString completionString = clang_getCursorCompletionString(
Cursor);
- PrintCursor(TU, Cursor);
+ PrintCursor(Cursor);
if (completionString != NULL) {
printf("\nCompletion string: ");
print_completion_string(completionString, stdout);
@@ -1363,6 +1364,101 @@
return 0;
}
+static enum CXVisitorResult findFileRefsVisit(void *context,
+ CXCursor cursor, CXSourceRange range) {
+ if (clang_Range_isNull(range))
+ return CXVisit_Continue;
+
+ PrintCursor(cursor);
+ PrintRange(range, "");
+ printf("\n");
+ return CXVisit_Continue;
+}
+
+static int find_file_refs_at(int argc, const char **argv) {
+ CXIndex CIdx;
+ int errorCode;
+ struct CXUnsavedFile *unsaved_files = 0;
+ int num_unsaved_files = 0;
+ CXTranslationUnit TU;
+ CXCursor Cursor;
+ CursorSourceLocation *Locations = 0;
+ unsigned NumLocations = 0, Loc;
+ unsigned Repeats = 1;
+ unsigned I;
+
+ /* Count the number of locations. */
+ while (strstr(argv[NumLocations+1], "-file-refs-at=") == argv[NumLocations+1])
+ ++NumLocations;
+
+ /* Parse the locations. */
+ assert(NumLocations > 0 && "Unable to count locations?");
+ Locations = (CursorSourceLocation *)malloc(
+ NumLocations * sizeof(CursorSourceLocation));
+ for (Loc = 0; Loc < NumLocations; ++Loc) {
+ const char *input = argv[Loc + 1] + strlen("-file-refs-at=");
+ if ((errorCode = parse_file_line_column(input, &Locations[Loc].filename,
+ &Locations[Loc].line,
+ &Locations[Loc].column, 0, 0)))
+ return errorCode;
+ }
+
+ if (parse_remapped_files(argc, argv, NumLocations + 1, &unsaved_files,
+ &num_unsaved_files))
+ return -1;
+
+ if (getenv("CINDEXTEST_EDITING"))
+ Repeats = 5;
+
+ /* Parse the translation unit. When we're testing clang_getCursor() after
+ reparsing, don't remap unsaved files until the second parse. */
+ CIdx = clang_createIndex(1, 1);
+ TU = clang_parseTranslationUnit(CIdx, argv[argc - 1],
+ argv + num_unsaved_files + 1 + NumLocations,
+ argc - num_unsaved_files - 2 - NumLocations,
+ unsaved_files,
+ Repeats > 1? 0 : num_unsaved_files,
+ getDefaultParsingOptions());
+
+ if (!TU) {
+ fprintf(stderr, "unable to parse input\n");
+ return -1;
+ }
+
+ for (I = 0; I != Repeats; ++I) {
+ if (Repeats > 1 &&
+ clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files,
+ clang_defaultReparseOptions(TU))) {
+ clang_disposeTranslationUnit(TU);
+ return 1;
+ }
+
+ for (Loc = 0; Loc < NumLocations; ++Loc) {
+ CXFile file = clang_getFile(TU, Locations[Loc].filename);
+ if (!file)
+ continue;
+
+ Cursor = clang_getCursor(TU,
+ clang_getLocation(TU, file, Locations[Loc].line,
+ Locations[Loc].column));
+ if (I + 1 == Repeats) {
+ PrintCursor(Cursor);
+ printf("\n");
+ CXCursorAndRangeVisitor visitor = { 0, findFileRefsVisit };
+ clang_findReferencesInFile(Cursor, file, visitor);
+ free(Locations[Loc].filename);
+ }
+ }
+ }
+
+ PrintDiagnostics(TU);
+ clang_disposeTranslationUnit(TU);
+ clang_disposeIndex(CIdx);
+ free(Locations);
+ free_remapped_files(unsaved_files, num_unsaved_files);
+ return 0;
+}
+
int perform_token_annotation(int argc, const char **argv) {
const char *input = argv[1];
char *filename = 0;
@@ -1464,7 +1560,7 @@
PrintExtent(stdout, start_line, start_column, end_line, end_column);
if (!clang_isInvalid(cursors[i].kind)) {
printf(" ");
- PrintCursor(TU, cursors[i]);
+ PrintCursor(cursors[i]);
}
printf("\n");
}
@@ -1730,6 +1826,7 @@
"usage: c-index-test -code-completion-at=<site> <compiler arguments>\n"
" c-index-test -code-completion-timing=<site> <compiler arguments>\n"
" c-index-test -cursor-at=<site> <compiler arguments>\n"
+ " c-index-test -file-refs-at=<site> <compiler arguments>\n"
" c-index-test -test-file-scan <AST file> <source file> "
"[FileCheck prefix]\n"
" c-index-test -test-load-tu <AST file> <symbol filter> "
@@ -1776,6 +1873,8 @@
return perform_code_completion(argc, argv, 1);
if (argc > 2 && strstr(argv[1], "-cursor-at=") == argv[1])
return inspect_cursor_at(argc, argv);
+ if (argc > 2 && strstr(argv[1], "-file-refs-at=") == argv[1])
+ return find_file_refs_at(argc, argv);
else if (argc >= 4 && strncmp(argv[1], "-test-load-tu", 13) == 0) {
CXCursorVisitor I = GetVisitor(argv[1] + 13);
if (I)