c-index-test.c revision f96b524306ccfa623235d375deee79637bd38f29
1/* c-index-test.c */
2
3#include "clang-c/Index.h"
4#include <stdio.h>
5#include <string.h>
6
7#ifdef _MSC_VER
8char *basename(const char* path)
9{
10    char* base1 = (char*)strrchr(path, '/');
11    char* base2 = (char*)strrchr(path, '\\');
12    if (base1 && base2)
13        return((base1 > base2) ? base1 + 1 : base2 + 1);
14    else if (base1)
15        return(base1 + 1);
16    else if (base2)
17        return(base2 + 1);
18
19    return((char*)path);
20}
21#else
22extern char *basename(const char *);
23#endif
24
25static void PrintCursor(CXCursor Cursor) {
26  if (clang_isInvalid(Cursor.kind))
27    printf("Invalid Cursor => %s\n", clang_getCursorKindSpelling(Cursor.kind));
28  else {
29    CXDecl DeclReferenced;
30    printf("%s=%s", clang_getCursorKindSpelling(Cursor.kind),
31                      clang_getCursorSpelling(Cursor));
32    DeclReferenced = clang_getCursorDecl(Cursor);
33    if (DeclReferenced)
34      printf(":%d:%d", clang_getDeclLine(DeclReferenced),
35                       clang_getDeclColumn(DeclReferenced));
36  }
37}
38
39static void DeclVisitor(CXDecl Dcl, CXCursor Cursor, CXClientData Filter)
40{
41  if (!Filter || (Cursor.kind == *(enum CXCursorKind *)Filter)) {
42    printf("// CHECK: %s:%d:%d: ", basename(clang_getCursorSource(Cursor)),
43                                 clang_getCursorLine(Cursor),
44                                 clang_getCursorColumn(Cursor));
45    PrintCursor(Cursor);
46    printf(" [Context=%s]\n", clang_getDeclSpelling(Dcl));
47  }
48}
49static void TranslationUnitVisitor(CXTranslationUnit Unit, CXCursor Cursor,
50                                   CXClientData Filter)
51{
52  if (!Filter || (Cursor.kind == *(enum CXCursorKind *)Filter)) {
53    printf("// CHECK: %s:%d:%d: ", basename(clang_getCursorSource(Cursor)),
54                                 clang_getCursorLine(Cursor),
55                                 clang_getCursorColumn(Cursor));
56    PrintCursor(Cursor);
57    printf(" [Context=%s]\n", basename(clang_getTranslationUnitSpelling(Unit)));
58
59    clang_loadDeclaration(Cursor.decl, DeclVisitor, 0);
60
61    if (Cursor.kind == CXCursor_FunctionDefn) {
62      const char *startBuf, *endBuf;
63      unsigned startLine, startColumn, endLine, endColumn;
64      clang_getDefinitionSpellingAndExtent(Cursor, &startBuf, &endBuf,
65                                           &startLine, &startColumn,
66                                           &endLine, &endColumn);
67      {
68        /* Probe the entire body, looking for both decls and refs. */
69        unsigned curLine = startLine, curColumn = startColumn;
70        CXCursor Ref;
71
72        while (startBuf < endBuf) {
73          if (*startBuf == '\n') {
74            startBuf++;
75            curLine++;
76            curColumn = 1;
77          } else if (*startBuf != '\t')
78            curColumn++;
79
80          Ref = clang_getCursor(Unit, clang_getCursorSource(Cursor),
81                                curLine, curColumn);
82          if (Ref.kind == CXCursor_NoDeclFound) {
83            /* Nothing found here; that's fine. */
84          } else if (Ref.kind != CXCursor_FunctionDecl) {
85            printf("// CHECK: %s:%d:%d: ", basename(clang_getCursorSource(Ref)),
86                                             curLine, curColumn);
87            PrintCursor(Ref);
88            printf(" [Context:%s]\n", clang_getDeclSpelling(Ref.decl));
89          }
90          startBuf++;
91        }
92      }
93    }
94  }
95}
96
97/*
98 * First sign of life:-)
99 */
100int main(int argc, char **argv) {
101  if (argc != 3) {
102    printf("Incorrect usage of c-index-test (requires 3 arguments)\n");
103    return 0;
104  }
105  {
106  CXIndex Idx;
107  CXTranslationUnit TU;
108  enum CXCursorKind K = CXCursor_NotImplemented;
109
110  Idx = clang_createIndex(/* excludeDeclsFromPCH */ !strcmp(argv[2], "local") ? 1 : 0,
111                          /* displayDiagnostics */ 1);
112
113  TU = clang_createTranslationUnit(Idx, argv[1]);
114
115  if (!TU) {
116    fprintf(stderr, "Unable to load translation unit!\n");
117    return 1;
118  }
119
120  if (!strcmp(argv[2], "all") || !strcmp(argv[2], "local")) {
121    clang_loadTranslationUnit(TU, TranslationUnitVisitor, 0);
122    clang_disposeTranslationUnit(TU);
123    return 1;
124  }
125  /* Perform some simple filtering. */
126  if (!strcmp(argv[2], "category")) K = CXCursor_ObjCCategoryDecl;
127  else if (!strcmp(argv[2], "interface")) K = CXCursor_ObjCInterfaceDecl;
128  else if (!strcmp(argv[2], "protocol")) K = CXCursor_ObjCProtocolDecl;
129  else if (!strcmp(argv[2], "function")) K = CXCursor_FunctionDecl;
130  else if (!strcmp(argv[2], "typedef")) K = CXCursor_TypedefDecl;
131
132  clang_loadTranslationUnit(TU, TranslationUnitVisitor, &K);
133  clang_disposeTranslationUnit(TU);
134  return 1;
135  }
136}
137