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