1 //===- CIndexHigh.cpp - Higher level API functions ------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "IndexingContext.h"
12 #include "clang/AST/DeclVisitor.h"
14 using namespace clang
;
15 using namespace cxindex
;
19 class IndexingDeclVisitor
: public DeclVisitor
<IndexingDeclVisitor
, bool> {
20 IndexingContext
&IndexCtx
;
23 explicit IndexingDeclVisitor(IndexingContext
&indexCtx
)
24 : IndexCtx(indexCtx
) { }
26 void handleDeclarator(DeclaratorDecl
*D
, const NamedDecl
*Parent
= 0) {
27 if (!Parent
) Parent
= D
;
29 if (!IndexCtx
.shouldIndexFunctionLocalSymbols()) {
30 IndexCtx
.indexTypeSourceInfo(D
->getTypeSourceInfo(), Parent
);
31 IndexCtx
.indexNestedNameSpecifierLoc(D
->getQualifierLoc(), Parent
);
33 if (ParmVarDecl
*Parm
= dyn_cast
<ParmVarDecl
>(D
)) {
34 IndexCtx
.handleVar(Parm
);
35 } else if (FunctionDecl
*FD
= dyn_cast
<FunctionDecl
>(D
)) {
36 for (FunctionDecl::param_iterator
37 PI
= FD
->param_begin(), PE
= FD
->param_end(); PI
!= PE
; ++PI
) {
38 IndexCtx
.handleVar(*PI
);
44 void handleObjCMethod(ObjCMethodDecl
*D
) {
45 IndexCtx
.handleObjCMethod(D
);
49 IndexCtx
.indexTypeSourceInfo(D
->getResultTypeSourceInfo(), D
);
50 for (ObjCMethodDecl::param_iterator
51 I
= D
->param_begin(), E
= D
->param_end(); I
!= E
; ++I
)
52 handleDeclarator(*I
, D
);
54 if (D
->isThisDeclarationADefinition()) {
55 const Stmt
*Body
= D
->getBody();
57 IndexCtx
.indexBody(Body
, D
, D
);
62 bool VisitFunctionDecl(FunctionDecl
*D
) {
63 IndexCtx
.handleFunction(D
);
66 if (CXXConstructorDecl
*Ctor
= dyn_cast
<CXXConstructorDecl
>(D
)) {
67 // Constructor initializers.
68 for (CXXConstructorDecl::init_iterator I
= Ctor
->init_begin(),
71 CXXCtorInitializer
*Init
= *I
;
72 if (Init
->isWritten()) {
73 IndexCtx
.indexTypeSourceInfo(Init
->getTypeSourceInfo(), D
);
74 if (const FieldDecl
*Member
= Init
->getAnyMember())
75 IndexCtx
.handleReference(Member
, Init
->getMemberLocation(), D
, D
);
76 IndexCtx
.indexBody(Init
->getInit(), D
, D
);
81 if (D
->isThisDeclarationADefinition()) {
82 const Stmt
*Body
= D
->getBody();
84 IndexCtx
.indexBody(Body
, D
, D
);
90 bool VisitVarDecl(VarDecl
*D
) {
91 IndexCtx
.handleVar(D
);
93 IndexCtx
.indexBody(D
->getInit(), D
);
97 bool VisitFieldDecl(FieldDecl
*D
) {
98 IndexCtx
.handleField(D
);
101 IndexCtx
.indexBody(D
->getBitWidth(), D
);
102 else if (D
->hasInClassInitializer())
103 IndexCtx
.indexBody(D
->getInClassInitializer(), D
);
107 bool VisitEnumConstantDecl(EnumConstantDecl
*D
) {
108 IndexCtx
.handleEnumerator(D
);
109 IndexCtx
.indexBody(D
->getInitExpr(), D
);
113 bool VisitTypedefNameDecl(TypedefNameDecl
*D
) {
114 IndexCtx
.handleTypedefName(D
);
115 IndexCtx
.indexTypeSourceInfo(D
->getTypeSourceInfo(), D
);
119 bool VisitTagDecl(TagDecl
*D
) {
120 // Non-free standing tags are handled in indexTypeSourceInfo.
121 if (D
->isFreeStanding())
122 IndexCtx
.indexTagDecl(D
);
126 bool VisitObjCInterfaceDecl(ObjCInterfaceDecl
*D
) {
127 IndexCtx
.handleObjCInterface(D
);
129 if (D
->isThisDeclarationADefinition()) {
130 IndexCtx
.indexTUDeclsInObjCContainer();
131 IndexCtx
.indexDeclContext(D
);
136 bool VisitObjCProtocolDecl(ObjCProtocolDecl
*D
) {
137 IndexCtx
.handleObjCProtocol(D
);
139 if (D
->isThisDeclarationADefinition()) {
140 IndexCtx
.indexTUDeclsInObjCContainer();
141 IndexCtx
.indexDeclContext(D
);
146 bool VisitObjCImplementationDecl(ObjCImplementationDecl
*D
) {
147 const ObjCInterfaceDecl
*Class
= D
->getClassInterface();
151 if (Class
->isImplicitInterfaceDecl())
152 IndexCtx
.handleObjCInterface(Class
);
154 IndexCtx
.handleObjCImplementation(D
);
156 IndexCtx
.indexTUDeclsInObjCContainer();
158 // Index the ivars first to make sure the synthesized ivars are indexed
159 // before indexing the methods that can reference them.
160 for (ObjCImplementationDecl::ivar_iterator
161 IvarI
= D
->ivar_begin(),
162 IvarE
= D
->ivar_end(); IvarI
!= IvarE
; ++IvarI
) {
163 IndexCtx
.indexDecl(*IvarI
);
165 for (DeclContext::decl_iterator
166 I
= D
->decls_begin(), E
= D
->decls_end(); I
!= E
; ++I
) {
167 if (!isa
<ObjCIvarDecl
>(*I
))
168 IndexCtx
.indexDecl(*I
);
174 bool VisitObjCCategoryDecl(ObjCCategoryDecl
*D
) {
175 IndexCtx
.handleObjCCategory(D
);
177 IndexCtx
.indexTUDeclsInObjCContainer();
178 IndexCtx
.indexDeclContext(D
);
182 bool VisitObjCCategoryImplDecl(ObjCCategoryImplDecl
*D
) {
183 const ObjCCategoryDecl
*Cat
= D
->getCategoryDecl();
187 IndexCtx
.handleObjCCategoryImpl(D
);
189 IndexCtx
.indexTUDeclsInObjCContainer();
190 IndexCtx
.indexDeclContext(D
);
194 bool VisitObjCMethodDecl(ObjCMethodDecl
*D
) {
195 // Methods associated with a property, even user-declared ones, are
196 // handled when we handle the property.
197 if (D
->isSynthesized())
204 bool VisitObjCPropertyDecl(ObjCPropertyDecl
*D
) {
205 if (ObjCMethodDecl
*MD
= D
->getGetterMethodDecl())
206 if (MD
->getLexicalDeclContext() == D
->getLexicalDeclContext())
207 handleObjCMethod(MD
);
208 if (ObjCMethodDecl
*MD
= D
->getSetterMethodDecl())
209 if (MD
->getLexicalDeclContext() == D
->getLexicalDeclContext())
210 handleObjCMethod(MD
);
211 IndexCtx
.handleObjCProperty(D
);
212 IndexCtx
.indexTypeSourceInfo(D
->getTypeSourceInfo(), D
);
216 bool VisitObjCPropertyImplDecl(ObjCPropertyImplDecl
*D
) {
217 ObjCPropertyDecl
*PD
= D
->getPropertyDecl();
218 IndexCtx
.handleSynthesizedObjCProperty(D
);
220 if (D
->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic
)
222 assert(D
->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize
);
224 if (ObjCIvarDecl
*IvarD
= D
->getPropertyIvarDecl()) {
225 if (!IvarD
->getSynthesize())
226 IndexCtx
.handleReference(IvarD
, D
->getPropertyIvarDeclLoc(), 0,
227 D
->getDeclContext());
230 if (ObjCMethodDecl
*MD
= PD
->getGetterMethodDecl()) {
231 if (MD
->isSynthesized())
232 IndexCtx
.handleSynthesizedObjCMethod(MD
, D
->getLocation(),
233 D
->getLexicalDeclContext());
235 if (ObjCMethodDecl
*MD
= PD
->getSetterMethodDecl()) {
236 if (MD
->isSynthesized())
237 IndexCtx
.handleSynthesizedObjCMethod(MD
, D
->getLocation(),
238 D
->getLexicalDeclContext());
243 bool VisitNamespaceDecl(NamespaceDecl
*D
) {
244 IndexCtx
.handleNamespace(D
);
245 IndexCtx
.indexDeclContext(D
);
249 bool VisitUsingDecl(UsingDecl
*D
) {
250 // FIXME: Parent for the following is CXIdxEntity_Unexposed with no USR,
251 // we should do better.
253 IndexCtx
.indexNestedNameSpecifierLoc(D
->getQualifierLoc(), D
);
254 for (UsingDecl::shadow_iterator
255 I
= D
->shadow_begin(), E
= D
->shadow_end(); I
!= E
; ++I
) {
256 IndexCtx
.handleReference((*I
)->getUnderlyingDecl(), D
->getLocation(),
257 D
, D
->getLexicalDeclContext());
262 bool VisitUsingDirectiveDecl(UsingDirectiveDecl
*D
) {
263 // FIXME: Parent for the following is CXIdxEntity_Unexposed with no USR,
264 // we should do better.
266 IndexCtx
.indexNestedNameSpecifierLoc(D
->getQualifierLoc(), D
);
267 IndexCtx
.handleReference(D
->getNominatedNamespaceAsWritten(),
268 D
->getLocation(), D
, D
->getLexicalDeclContext());
272 bool VisitClassTemplateDecl(ClassTemplateDecl
*D
) {
273 IndexCtx
.handleClassTemplate(D
);
274 if (D
->isThisDeclarationADefinition())
275 IndexCtx
.indexDeclContext(D
->getTemplatedDecl());
279 bool VisitClassTemplateSpecializationDecl(
280 ClassTemplateSpecializationDecl
*D
) {
281 // FIXME: Notify subsequent callbacks if info comes from implicit
283 if (D
->isThisDeclarationADefinition() &&
284 (IndexCtx
.shouldIndexImplicitTemplateInsts() ||
285 !IndexCtx
.isTemplateImplicitInstantiation(D
)))
286 IndexCtx
.indexTagDecl(D
);
290 bool VisitFunctionTemplateDecl(FunctionTemplateDecl
*D
) {
291 IndexCtx
.handleFunctionTemplate(D
);
292 FunctionDecl
*FD
= D
->getTemplatedDecl();
293 handleDeclarator(FD
, D
);
294 if (FD
->isThisDeclarationADefinition()) {
295 const Stmt
*Body
= FD
->getBody();
297 IndexCtx
.indexBody(Body
, D
, FD
);
303 bool VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl
*D
) {
304 IndexCtx
.handleTypeAliasTemplate(D
);
305 IndexCtx
.indexTypeSourceInfo(D
->getTemplatedDecl()->getTypeSourceInfo(), D
);
310 } // anonymous namespace
312 void IndexingContext::indexDecl(const Decl
*D
) {
313 if (D
->isImplicit() && shouldIgnoreIfImplicit(D
))
316 bool Handled
= IndexingDeclVisitor(*this).Visit(const_cast<Decl
*>(D
));
317 if (!Handled
&& isa
<DeclContext
>(D
))
318 indexDeclContext(cast
<DeclContext
>(D
));
321 void IndexingContext::indexDeclContext(const DeclContext
*DC
) {
322 for (DeclContext::decl_iterator
323 I
= DC
->decls_begin(), E
= DC
->decls_end(); I
!= E
; ++I
) {
328 void IndexingContext::indexTopLevelDecl(const Decl
*D
) {
329 if (isNotFromSourceFile(D
->getLocation()))
332 if (isa
<ObjCMethodDecl
>(D
))
333 return; // Wait for the objc container.
338 void IndexingContext::indexDeclGroupRef(DeclGroupRef DG
) {
339 for (DeclGroupRef::iterator I
= DG
.begin(), E
= DG
.end(); I
!= E
; ++I
)
340 indexTopLevelDecl(*I
);
343 void IndexingContext::indexTUDeclsInObjCContainer() {
344 while (!TUDeclsInObjCContainer
.empty()) {
345 DeclGroupRef DG
= TUDeclsInObjCContainer
.front();
346 TUDeclsInObjCContainer
.pop_front();
347 indexDeclGroupRef(DG
);