IndexBody.cpp revision 651f13cea278ec967336033dd032faef0e9fc2ec
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 "clang/AST/DataRecursiveASTVisitor.h"
12
13using namespace clang;
14using namespace cxindex;
15
16namespace {
17
18class BodyIndexer : public DataRecursiveASTVisitor<BodyIndexer> {
19  IndexingContext &IndexCtx;
20  const NamedDecl *Parent;
21  const DeclContext *ParentDC;
22
23  typedef DataRecursiveASTVisitor<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 (ObjCMethodDecl *MD = E->getMethodDecl())
72      IndexCtx.handleReference(MD, E->getSelectorStartLoc(),
73                               Parent, ParentDC, E,
74                               E->isImplicit() ? CXIdxEntityRef_Implicit
75                                               : CXIdxEntityRef_Direct);
76    return true;
77  }
78
79  bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
80    if (E->isExplicitProperty())
81      IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(),
82                               Parent, ParentDC, E);
83
84    // No need to do a handleReference for the objc method, because there will
85    // be a message expr as part of PseudoObjectExpr.
86    return true;
87  }
88
89  bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) {
90    IndexCtx.handleReference(E->getPropertyDecl(), E->getMemberLoc(), Parent,
91                             ParentDC, E, CXIdxEntityRef_Direct);
92    return true;
93  }
94
95  bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
96    IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(),
97                             Parent, ParentDC, E, CXIdxEntityRef_Direct);
98    return true;
99  }
100
101  bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
102    if (ObjCMethodDecl *MD = E->getBoxingMethod())
103      IndexCtx.handleReference(MD, E->getLocStart(),
104                               Parent, ParentDC, E, CXIdxEntityRef_Implicit);
105    return true;
106  }
107
108  bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
109    if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod())
110      IndexCtx.handleReference(MD, E->getLocStart(),
111                               Parent, ParentDC, E, CXIdxEntityRef_Implicit);
112    return true;
113  }
114
115  bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
116    if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod())
117      IndexCtx.handleReference(MD, E->getLocStart(),
118                               Parent, ParentDC, E, CXIdxEntityRef_Implicit);
119    return true;
120  }
121
122  bool VisitCXXConstructExpr(CXXConstructExpr *E) {
123    IndexCtx.handleReference(E->getConstructor(), E->getLocation(),
124                             Parent, ParentDC, E);
125    return true;
126  }
127
128  bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
129    if (E->getOperatorLoc().isInvalid())
130      return true; // implicit.
131    return base::TraverseCXXOperatorCallExpr(E);
132  }
133
134  bool VisitDeclStmt(DeclStmt *S) {
135    if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
136      IndexCtx.indexDeclGroupRef(S->getDeclGroup());
137      return true;
138    }
139
140    DeclGroupRef DG = S->getDeclGroup();
141    for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) {
142      const Decl *D = *I;
143      if (!D)
144        continue;
145      if (!IndexCtx.isFunctionLocalDecl(D))
146        IndexCtx.indexTopLevelDecl(D);
147    }
148
149    return true;
150  }
151
152  bool TraverseLambdaCapture(LambdaExpr::Capture C) {
153    if (C.capturesThis())
154      return true;
155
156    if (C.capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols())
157      IndexCtx.handleReference(C.getCapturedVar(), C.getLocation(),
158                               Parent, ParentDC);
159
160    // FIXME: Lambda init-captures.
161    return true;
162  }
163
164};
165
166} // anonymous namespace
167
168void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent,
169                                const DeclContext *DC) {
170  if (!S)
171    return;
172
173  if (DC == 0)
174    DC = Parent->getLexicalDeclContext();
175  BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast<Stmt*>(S));
176}
177