• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/DeclVisitor.h"
12 
13 using namespace clang;
14 using namespace cxindex;
15 
16 namespace {
17 
18 class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
19   IndexingContext &IndexCtx;
20 
21 public:
IndexingDeclVisitor(IndexingContext & indexCtx)22   explicit IndexingDeclVisitor(IndexingContext &indexCtx)
23     : IndexCtx(indexCtx) { }
24 
25   /// \brief Returns true if the given method has been defined explicitly by the
26   /// user.
hasUserDefined(const ObjCMethodDecl * D,const ObjCImplDecl * Container)27   static bool hasUserDefined(const ObjCMethodDecl *D,
28                              const ObjCImplDecl *Container) {
29     const ObjCMethodDecl *MD = Container->getMethod(D->getSelector(),
30                                                     D->isInstanceMethod());
31     return MD && !MD->isImplicit() && MD->isThisDeclarationADefinition();
32   }
33 
handleDeclarator(const DeclaratorDecl * D,const NamedDecl * Parent=0)34   void handleDeclarator(const DeclaratorDecl *D, const NamedDecl *Parent = 0) {
35     if (!Parent) Parent = D;
36 
37     if (!IndexCtx.shouldIndexFunctionLocalSymbols()) {
38       IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent);
39       IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent);
40     } else {
41       if (const ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) {
42         IndexCtx.handleVar(Parm);
43       } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
44         for (FunctionDecl::param_const_iterator PI = FD->param_begin(),
45                                                 PE = FD->param_end();
46              PI != PE; ++PI) {
47           IndexCtx.handleVar(*PI);
48         }
49       }
50     }
51   }
52 
handleObjCMethod(const ObjCMethodDecl * D)53   void handleObjCMethod(const ObjCMethodDecl *D) {
54     IndexCtx.handleObjCMethod(D);
55     if (D->isImplicit())
56       return;
57 
58     IndexCtx.indexTypeSourceInfo(D->getResultTypeSourceInfo(), D);
59     for (ObjCMethodDecl::param_const_iterator I = D->param_begin(),
60                                               E = D->param_end();
61          I != E; ++I)
62       handleDeclarator(*I, D);
63 
64     if (D->isThisDeclarationADefinition()) {
65       const Stmt *Body = D->getBody();
66       if (Body) {
67         IndexCtx.indexBody(Body, D, D);
68       }
69     }
70   }
71 
VisitFunctionDecl(const FunctionDecl * D)72   bool VisitFunctionDecl(const FunctionDecl *D) {
73     IndexCtx.handleFunction(D);
74     handleDeclarator(D);
75 
76     if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
77       // Constructor initializers.
78       for (CXXConstructorDecl::init_const_iterator I = Ctor->init_begin(),
79                                                    E = Ctor->init_end();
80            I != E; ++I) {
81         CXXCtorInitializer *Init = *I;
82         if (Init->isWritten()) {
83           IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D);
84           if (const FieldDecl *Member = Init->getAnyMember())
85             IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D);
86           IndexCtx.indexBody(Init->getInit(), D, D);
87         }
88       }
89     }
90 
91     if (D->isThisDeclarationADefinition()) {
92       const Stmt *Body = D->getBody();
93       if (Body) {
94         IndexCtx.indexBody(Body, D, D);
95       }
96     }
97     return true;
98   }
99 
VisitVarDecl(const VarDecl * D)100   bool VisitVarDecl(const VarDecl *D) {
101     IndexCtx.handleVar(D);
102     handleDeclarator(D);
103     IndexCtx.indexBody(D->getInit(), D);
104     return true;
105   }
106 
VisitFieldDecl(const FieldDecl * D)107   bool VisitFieldDecl(const FieldDecl *D) {
108     IndexCtx.handleField(D);
109     handleDeclarator(D);
110     if (D->isBitField())
111       IndexCtx.indexBody(D->getBitWidth(), D);
112     else if (D->hasInClassInitializer())
113       IndexCtx.indexBody(D->getInClassInitializer(), D);
114     return true;
115   }
116 
VisitMSPropertyDecl(const MSPropertyDecl * D)117   bool VisitMSPropertyDecl(const MSPropertyDecl *D) {
118     handleDeclarator(D);
119     return true;
120   }
121 
VisitEnumConstantDecl(const EnumConstantDecl * D)122   bool VisitEnumConstantDecl(const EnumConstantDecl *D) {
123     IndexCtx.handleEnumerator(D);
124     IndexCtx.indexBody(D->getInitExpr(), D);
125     return true;
126   }
127 
VisitTypedefNameDecl(const TypedefNameDecl * D)128   bool VisitTypedefNameDecl(const TypedefNameDecl *D) {
129     IndexCtx.handleTypedefName(D);
130     IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
131     return true;
132   }
133 
VisitTagDecl(const TagDecl * D)134   bool VisitTagDecl(const TagDecl *D) {
135     // Non-free standing tags are handled in indexTypeSourceInfo.
136     if (D->isFreeStanding())
137       IndexCtx.indexTagDecl(D);
138     return true;
139   }
140 
VisitObjCInterfaceDecl(const ObjCInterfaceDecl * D)141   bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
142     IndexCtx.handleObjCInterface(D);
143 
144     if (D->isThisDeclarationADefinition()) {
145       IndexCtx.indexTUDeclsInObjCContainer();
146       IndexCtx.indexDeclContext(D);
147     }
148     return true;
149   }
150 
VisitObjCProtocolDecl(const ObjCProtocolDecl * D)151   bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
152     IndexCtx.handleObjCProtocol(D);
153 
154     if (D->isThisDeclarationADefinition()) {
155       IndexCtx.indexTUDeclsInObjCContainer();
156       IndexCtx.indexDeclContext(D);
157     }
158     return true;
159   }
160 
VisitObjCImplementationDecl(const ObjCImplementationDecl * D)161   bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) {
162     const ObjCInterfaceDecl *Class = D->getClassInterface();
163     if (!Class)
164       return true;
165 
166     if (Class->isImplicitInterfaceDecl())
167       IndexCtx.handleObjCInterface(Class);
168 
169     IndexCtx.handleObjCImplementation(D);
170 
171     IndexCtx.indexTUDeclsInObjCContainer();
172 
173     // Index the ivars first to make sure the synthesized ivars are indexed
174     // before indexing the methods that can reference them.
175     for (ObjCImplementationDecl::ivar_iterator
176            IvarI = D->ivar_begin(),
177            IvarE = D->ivar_end(); IvarI != IvarE; ++IvarI) {
178       IndexCtx.indexDecl(*IvarI);
179     }
180     for (DeclContext::decl_iterator
181            I = D->decls_begin(), E = D->decls_end(); I != E; ++I) {
182       if (!isa<ObjCIvarDecl>(*I))
183         IndexCtx.indexDecl(*I);
184     }
185 
186     return true;
187   }
188 
VisitObjCCategoryDecl(const ObjCCategoryDecl * D)189   bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
190     IndexCtx.handleObjCCategory(D);
191 
192     IndexCtx.indexTUDeclsInObjCContainer();
193     IndexCtx.indexDeclContext(D);
194     return true;
195   }
196 
VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl * D)197   bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
198     const ObjCCategoryDecl *Cat = D->getCategoryDecl();
199     if (!Cat)
200       return true;
201 
202     IndexCtx.handleObjCCategoryImpl(D);
203 
204     IndexCtx.indexTUDeclsInObjCContainer();
205     IndexCtx.indexDeclContext(D);
206     return true;
207   }
208 
VisitObjCMethodDecl(const ObjCMethodDecl * D)209   bool VisitObjCMethodDecl(const ObjCMethodDecl *D) {
210     // Methods associated with a property, even user-declared ones, are
211     // handled when we handle the property.
212     if (D->isPropertyAccessor())
213       return true;
214 
215     handleObjCMethod(D);
216     return true;
217   }
218 
VisitObjCPropertyDecl(const ObjCPropertyDecl * D)219   bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
220     if (ObjCMethodDecl *MD = D->getGetterMethodDecl())
221       if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
222         handleObjCMethod(MD);
223     if (ObjCMethodDecl *MD = D->getSetterMethodDecl())
224       if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
225         handleObjCMethod(MD);
226     IndexCtx.handleObjCProperty(D);
227     IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
228     return true;
229   }
230 
VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl * D)231   bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
232     ObjCPropertyDecl *PD = D->getPropertyDecl();
233     IndexCtx.handleSynthesizedObjCProperty(D);
234 
235     if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
236       return true;
237     assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize);
238 
239     if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) {
240       if (!IvarD->getSynthesize())
241         IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), 0,
242                                  D->getDeclContext());
243     }
244 
245     if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) {
246       if (MD->isPropertyAccessor() &&
247           !hasUserDefined(MD, cast<ObjCImplDecl>(D->getDeclContext())))
248         IndexCtx.handleSynthesizedObjCMethod(MD, D->getLocation(),
249                                              D->getLexicalDeclContext());
250     }
251     if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) {
252       if (MD->isPropertyAccessor() &&
253           !hasUserDefined(MD, cast<ObjCImplDecl>(D->getDeclContext())))
254         IndexCtx.handleSynthesizedObjCMethod(MD, D->getLocation(),
255                                              D->getLexicalDeclContext());
256     }
257     return true;
258   }
259 
VisitNamespaceDecl(const NamespaceDecl * D)260   bool VisitNamespaceDecl(const NamespaceDecl *D) {
261     IndexCtx.handleNamespace(D);
262     IndexCtx.indexDeclContext(D);
263     return true;
264   }
265 
VisitUsingDecl(const UsingDecl * D)266   bool VisitUsingDecl(const UsingDecl *D) {
267     // FIXME: Parent for the following is CXIdxEntity_Unexposed with no USR,
268     // we should do better.
269 
270     IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
271     for (UsingDecl::shadow_iterator
272            I = D->shadow_begin(), E = D->shadow_end(); I != E; ++I) {
273       IndexCtx.handleReference((*I)->getUnderlyingDecl(), D->getLocation(),
274                                D, D->getLexicalDeclContext());
275     }
276     return true;
277   }
278 
VisitUsingDirectiveDecl(const UsingDirectiveDecl * D)279   bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
280     // FIXME: Parent for the following is CXIdxEntity_Unexposed with no USR,
281     // we should do better.
282 
283     IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
284     IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(),
285                              D->getLocation(), D, D->getLexicalDeclContext());
286     return true;
287   }
288 
VisitClassTemplateDecl(const ClassTemplateDecl * D)289   bool VisitClassTemplateDecl(const ClassTemplateDecl *D) {
290     IndexCtx.handleClassTemplate(D);
291     if (D->isThisDeclarationADefinition())
292       IndexCtx.indexDeclContext(D->getTemplatedDecl());
293     return true;
294   }
295 
VisitClassTemplateSpecializationDecl(const ClassTemplateSpecializationDecl * D)296   bool VisitClassTemplateSpecializationDecl(const
297                                            ClassTemplateSpecializationDecl *D) {
298     // FIXME: Notify subsequent callbacks if info comes from implicit
299     // instantiation.
300     if (D->isThisDeclarationADefinition() &&
301         (IndexCtx.shouldIndexImplicitTemplateInsts() ||
302          !IndexCtx.isTemplateImplicitInstantiation(D)))
303       IndexCtx.indexTagDecl(D);
304     return true;
305   }
306 
VisitFunctionTemplateDecl(const FunctionTemplateDecl * D)307   bool VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
308     IndexCtx.handleFunctionTemplate(D);
309     FunctionDecl *FD = D->getTemplatedDecl();
310     handleDeclarator(FD, D);
311     if (FD->isThisDeclarationADefinition()) {
312       const Stmt *Body = FD->getBody();
313       if (Body) {
314         IndexCtx.indexBody(Body, D, FD);
315       }
316     }
317     return true;
318   }
319 
VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl * D)320   bool VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) {
321     IndexCtx.handleTypeAliasTemplate(D);
322     IndexCtx.indexTypeSourceInfo(D->getTemplatedDecl()->getTypeSourceInfo(), D);
323     return true;
324   }
325 
VisitImportDecl(const ImportDecl * D)326   bool VisitImportDecl(const ImportDecl *D) {
327     IndexCtx.importedModule(D);
328     return true;
329   }
330 };
331 
332 } // anonymous namespace
333 
indexDecl(const Decl * D)334 void IndexingContext::indexDecl(const Decl *D) {
335   if (D->isImplicit() && shouldIgnoreIfImplicit(D))
336     return;
337 
338   bool Handled = IndexingDeclVisitor(*this).Visit(D);
339   if (!Handled && isa<DeclContext>(D))
340     indexDeclContext(cast<DeclContext>(D));
341 }
342 
indexDeclContext(const DeclContext * DC)343 void IndexingContext::indexDeclContext(const DeclContext *DC) {
344   for (DeclContext::decl_iterator
345          I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) {
346     indexDecl(*I);
347   }
348 }
349 
indexTopLevelDecl(const Decl * D)350 void IndexingContext::indexTopLevelDecl(const Decl *D) {
351   if (isNotFromSourceFile(D->getLocation()))
352     return;
353 
354   if (isa<ObjCMethodDecl>(D))
355     return; // Wait for the objc container.
356 
357   indexDecl(D);
358 }
359 
indexDeclGroupRef(DeclGroupRef DG)360 void IndexingContext::indexDeclGroupRef(DeclGroupRef DG) {
361   for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
362     indexTopLevelDecl(*I);
363 }
364 
indexTUDeclsInObjCContainer()365 void IndexingContext::indexTUDeclsInObjCContainer() {
366   while (!TUDeclsInObjCContainer.empty()) {
367     DeclGroupRef DG = TUDeclsInObjCContainer.front();
368     TUDeclsInObjCContainer.pop_front();
369     indexDeclGroupRef(DG);
370   }
371 }
372