IndexBody.cpp revision 3bed3d196dbb5ad2ea7442da4b6c2fbf6bb5fcc6
1//===- CIndexHigh.cpp - Higher level API functions ------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "IndexingContext.h"
11
12#include "RecursiveASTVisitor.h"
13
14using namespace clang;
15using namespace cxindex;
16
17namespace {
18
19class BodyIndexer : public cxindex::RecursiveASTVisitor<BodyIndexer> {
20  IndexingContext &IndexCtx;
21  const NamedDecl *Parent;
22  const DeclContext *ParentDC;
23
24  typedef RecursiveASTVisitor<BodyIndexer> base;
25public:
26  BodyIndexer(IndexingContext &indexCtx,
27              const NamedDecl *Parent, const DeclContext *DC)
28    : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { }
29
30  bool shouldWalkTypesOfTypeLocs() const { return false; }
31
32  bool TraverseTypeLoc(TypeLoc TL) {
33    IndexCtx.indexTypeLoc(TL, Parent, ParentDC);
34    return true;
35  }
36
37  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
38    IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
39    return true;
40  }
41
42  bool VisitDeclRefExpr(DeclRefExpr *E) {
43    IndexCtx.handleReference(E->getDecl(), E->getLocation(),
44                             Parent, ParentDC, E);
45    return true;
46  }
47
48  bool VisitMemberExpr(MemberExpr *E) {
49    IndexCtx.handleReference(E->getMemberDecl(), E->getMemberLoc(),
50                             Parent, ParentDC, E);
51    return true;
52  }
53
54  bool VisitDesignatedInitExpr(DesignatedInitExpr *E) {
55    for (DesignatedInitExpr::reverse_designators_iterator
56           D = E->designators_rbegin(), DEnd = E->designators_rend();
57           D != DEnd; ++D) {
58      if (D->isFieldDesignator())
59        IndexCtx.handleReference(D->getField(), D->getFieldLoc(),
60                                 Parent, ParentDC, E);
61    }
62    return true;
63  }
64
65  bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
66    IndexCtx.handleReference(E->getDecl(), E->getLocation(),
67                             Parent, ParentDC, E);
68    return true;
69  }
70
71  bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
72    if (TypeSourceInfo *Cls = E->getClassReceiverTypeInfo())
73      IndexCtx.indexTypeSourceInfo(Cls, Parent, ParentDC);
74
75    if (ObjCMethodDecl *MD = E->getMethodDecl())
76      IndexCtx.handleReference(MD, E->getSelectorStartLoc(),
77                               Parent, ParentDC, E,
78                               E->isImplicit() ? CXIdxEntityRef_Implicit
79                                               : CXIdxEntityRef_Direct);
80    return true;
81  }
82
83  bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
84    if (E->isExplicitProperty())
85      IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(),
86                               Parent, ParentDC, E);
87
88    // No need to do a handleReference for the objc method, because there will
89    // be a message expr as part of PseudoObjectExpr.
90    return true;
91  }
92
93  bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
94    IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(),
95                             Parent, ParentDC, E, CXIdxEntityRef_Direct);
96    return true;
97  }
98
99  bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
100    if (ObjCMethodDecl *MD = E->getBoxingMethod())
101      IndexCtx.handleReference(MD, E->getLocStart(),
102                               Parent, ParentDC, E, CXIdxEntityRef_Implicit);
103    return true;
104  }
105
106  bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
107    if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod())
108      IndexCtx.handleReference(MD, E->getLocStart(),
109                               Parent, ParentDC, E, CXIdxEntityRef_Implicit);
110    return true;
111  }
112
113  bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
114    if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod())
115      IndexCtx.handleReference(MD, E->getLocStart(),
116                               Parent, ParentDC, E, CXIdxEntityRef_Implicit);
117    return true;
118  }
119
120  bool VisitCXXConstructExpr(CXXConstructExpr *E) {
121    IndexCtx.handleReference(E->getConstructor(), E->getLocation(),
122                             Parent, ParentDC, E);
123    return true;
124  }
125
126  bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
127    if (E->getOperatorLoc().isInvalid())
128      return true; // implicit.
129    return base::TraverseCXXOperatorCallExpr(E);
130  }
131
132  bool VisitDeclStmt(DeclStmt *S) {
133    if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
134      IndexCtx.indexDeclGroupRef(S->getDeclGroup());
135      return true;
136    }
137
138    DeclGroupRef DG = S->getDeclGroup();
139    for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) {
140      const Decl *D = *I;
141      if (!D)
142        continue;
143      if (!IndexCtx.isFunctionLocalDecl(D))
144        IndexCtx.indexTopLevelDecl(D);
145    }
146
147    return true;
148  }
149
150  bool TraverseLambdaCapture(LambdaExpr::Capture C) {
151    if (C.capturesThis())
152      return true;
153
154    if (IndexCtx.shouldIndexFunctionLocalSymbols())
155      IndexCtx.handleReference(C.getCapturedVar(), C.getLocation(),
156                               Parent, ParentDC);
157    return true;
158  }
159
160};
161
162} // anonymous namespace
163
164void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent,
165                                const DeclContext *DC) {
166  if (!S)
167    return;
168
169  if (DC == 0)
170    DC = Parent->getLexicalDeclContext();
171  BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast<Stmt*>(S));
172}
173