IndexDecl.cpp revision bd9482d859a74bf2c45ef8b8aedec61c0e1c8374
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 "clang/AST/DeclVisitor.h"
13
14using namespace clang;
15using namespace cxindex;
16
17namespace {
18
19class IndexingDeclVisitor : public DeclVisitor<IndexingDeclVisitor, bool> {
20  IndexingContext &IndexCtx;
21
22public:
23  explicit IndexingDeclVisitor(IndexingContext &indexCtx)
24    : IndexCtx(indexCtx) { }
25
26  void handleDeclarator(DeclaratorDecl *D, const NamedDecl *Parent = 0) {
27    if (!Parent) Parent = D;
28    IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent);
29    IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent);
30  }
31
32  bool VisitFunctionDecl(FunctionDecl *D) {
33    IndexCtx.handleFunction(D);
34    handleDeclarator(D);
35    if (D->isThisDeclarationADefinition()) {
36      const Stmt *Body = D->getBody();
37      if (Body) {
38        IndexCtx.indexBody(Body, D, D);
39      }
40    }
41    return true;
42  }
43
44  bool VisitVarDecl(VarDecl *D) {
45    IndexCtx.handleVar(D);
46    handleDeclarator(D);
47    IndexCtx.indexBody(D->getInit(), D);
48    return true;
49  }
50
51  bool VisitFieldDecl(FieldDecl *D) {
52    IndexCtx.handleField(D);
53    handleDeclarator(D);
54    if (D->isBitField())
55      IndexCtx.indexBody(D->getBitWidth(), D);
56    else if (D->hasInClassInitializer())
57      IndexCtx.indexBody(D->getInClassInitializer(), D);
58    return true;
59  }
60
61  bool VisitEnumConstantDecl(EnumConstantDecl *D) {
62    IndexCtx.handleEnumerator(D);
63    IndexCtx.indexBody(D->getInitExpr(), D);
64    return true;
65  }
66
67  bool VisitTypedefDecl(TypedefNameDecl *D) {
68    IndexCtx.handleTypedefName(D);
69    IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
70    return true;
71  }
72
73  bool VisitTagDecl(TagDecl *D) {
74    // Non-free standing tags are handled in indexTypeSourceInfo.
75    if (D->isFreeStanding())
76      IndexCtx.indexTagDecl(D);
77    return true;
78  }
79
80  bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
81    IndexCtx.handleObjCInterface(D);
82
83    if (D->isThisDeclarationADefinition()) {
84      IndexCtx.indexTUDeclsInObjCContainer();
85      IndexCtx.indexDeclContext(D);
86    }
87    return true;
88  }
89
90  bool VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
91    IndexCtx.handleObjCProtocol(D);
92
93    if (D->isThisDeclarationADefinition()) {
94      IndexCtx.indexTUDeclsInObjCContainer();
95      IndexCtx.indexDeclContext(D);
96    }
97    return true;
98  }
99
100  bool VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
101    const ObjCInterfaceDecl *Class = D->getClassInterface();
102    if (!Class)
103      return true;
104
105    if (Class->isImplicitInterfaceDecl())
106      IndexCtx.handleObjCInterface(Class);
107
108    IndexCtx.handleObjCImplementation(D);
109
110    IndexCtx.indexTUDeclsInObjCContainer();
111    IndexCtx.indexDeclContext(D);
112    return true;
113  }
114
115  bool VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
116    IndexCtx.handleObjCCategory(D);
117
118    IndexCtx.indexTUDeclsInObjCContainer();
119    IndexCtx.indexDeclContext(D);
120    return true;
121  }
122
123  bool VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
124    const ObjCCategoryDecl *Cat = D->getCategoryDecl();
125    if (!Cat)
126      return true;
127
128    IndexCtx.handleObjCCategoryImpl(D);
129
130    IndexCtx.indexTUDeclsInObjCContainer();
131    IndexCtx.indexDeclContext(D);
132    return true;
133  }
134
135  bool VisitObjCMethodDecl(ObjCMethodDecl *D) {
136    IndexCtx.handleObjCMethod(D);
137    IndexCtx.indexTypeSourceInfo(D->getResultTypeSourceInfo(), D);
138    for (ObjCMethodDecl::param_iterator
139           I = D->param_begin(), E = D->param_end(); I != E; ++I)
140      handleDeclarator(*I, D);
141
142    if (D->isThisDeclarationADefinition()) {
143      const Stmt *Body = D->getBody();
144      if (Body) {
145        IndexCtx.indexBody(Body, D, D);
146      }
147    }
148    return true;
149  }
150
151  bool VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
152    IndexCtx.handleObjCProperty(D);
153    IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
154    return true;
155  }
156
157  bool VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
158    ObjCPropertyDecl *PD = D->getPropertyDecl();
159    IndexCtx.handleSynthesizedObjCProperty(D);
160
161    if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
162      return true;
163    assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize);
164
165    if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) {
166      if (!IvarD->getSynthesize())
167        IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), 0,
168                                 D->getDeclContext());
169    }
170
171    if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) {
172      if (MD->isSynthesized())
173        IndexCtx.handleSynthesizedObjCMethod(MD, D->getLocation());
174    }
175    if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) {
176      if (MD->isSynthesized())
177        IndexCtx.handleSynthesizedObjCMethod(MD, D->getLocation());
178    }
179    return true;
180  }
181
182  bool VisitNamespaceDecl(NamespaceDecl *D) {
183    IndexCtx.handleNamespace(D);
184    IndexCtx.indexDeclContext(D);
185    return true;
186  }
187
188  bool VisitClassTemplateDecl(ClassTemplateDecl *D) {
189    IndexCtx.handleClassTemplate(D);
190    if (D->isThisDeclarationADefinition())
191      IndexCtx.indexDeclContext(D->getTemplatedDecl());
192    return true;
193  }
194
195  bool VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
196    IndexCtx.handleFunctionTemplate(D);
197    FunctionDecl *FD = D->getTemplatedDecl();
198    handleDeclarator(FD, D);
199    if (FD->isThisDeclarationADefinition()) {
200      const Stmt *Body = FD->getBody();
201      if (Body) {
202        IndexCtx.indexBody(Body, D, FD);
203      }
204    }
205    return true;
206  }
207
208  bool VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
209    IndexCtx.handleTypeAliasTemplate(D);
210    IndexCtx.indexTypeSourceInfo(D->getTemplatedDecl()->getTypeSourceInfo(), D);
211    return true;
212  }
213};
214
215} // anonymous namespace
216
217void IndexingContext::indexDecl(const Decl *D) {
218  bool Handled = IndexingDeclVisitor(*this).Visit(const_cast<Decl*>(D));
219  if (!Handled && isa<DeclContext>(D))
220    indexDeclContext(cast<DeclContext>(D));
221}
222
223void IndexingContext::indexDeclContext(const DeclContext *DC) {
224  for (DeclContext::decl_iterator
225         I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) {
226    indexDecl(*I);
227  }
228}
229
230void IndexingContext::indexTopLevelDecl(Decl *D) {
231  if (isNotFromSourceFile(D->getLocation()))
232    return;
233
234  if (isa<ObjCMethodDecl>(D))
235    return; // Wait for the objc container.
236
237  indexDecl(D);
238}
239
240void IndexingContext::indexDeclGroupRef(DeclGroupRef DG) {
241  for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
242    indexTopLevelDecl(*I);
243}
244
245void IndexingContext::indexTUDeclsInObjCContainer() {
246  for (unsigned i = 0, e = TUDeclsInObjCContainer.size(); i != e; ++i)
247    indexDeclGroupRef(TUDeclsInObjCContainer[i]);
248  TUDeclsInObjCContainer.clear();
249}
250