IndexDecl.cpp revision 58d2dbea680a75de266c5eff77cc15c323cfd48a
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 29 if (!IndexCtx.shouldIndexFunctionLocalSymbols()) { 30 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent); 31 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent); 32 } else { 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); 39 } 40 } 41 } 42 } 43 44 bool VisitFunctionDecl(FunctionDecl *D) { 45 IndexCtx.handleFunction(D); 46 handleDeclarator(D); 47 48 if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) { 49 // Constructor initializers. 50 for (CXXConstructorDecl::init_iterator I = Ctor->init_begin(), 51 E = Ctor->init_end(); 52 I != E; ++I) { 53 CXXCtorInitializer *Init = *I; 54 if (Init->isWritten()) { 55 IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D); 56 if (const FieldDecl *Member = Init->getAnyMember()) 57 IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D); 58 IndexCtx.indexBody(Init->getInit(), D, D); 59 } 60 } 61 } 62 63 if (D->isThisDeclarationADefinition()) { 64 const Stmt *Body = D->getBody(); 65 if (Body) { 66 IndexCtx.indexBody(Body, D, D); 67 } 68 } 69 return true; 70 } 71 72 bool VisitVarDecl(VarDecl *D) { 73 IndexCtx.handleVar(D); 74 handleDeclarator(D); 75 IndexCtx.indexBody(D->getInit(), D); 76 return true; 77 } 78 79 bool VisitFieldDecl(FieldDecl *D) { 80 IndexCtx.handleField(D); 81 handleDeclarator(D); 82 if (D->isBitField()) 83 IndexCtx.indexBody(D->getBitWidth(), D); 84 else if (D->hasInClassInitializer()) 85 IndexCtx.indexBody(D->getInClassInitializer(), D); 86 return true; 87 } 88 89 bool VisitEnumConstantDecl(EnumConstantDecl *D) { 90 IndexCtx.handleEnumerator(D); 91 IndexCtx.indexBody(D->getInitExpr(), D); 92 return true; 93 } 94 95 bool VisitTypedefDecl(TypedefNameDecl *D) { 96 IndexCtx.handleTypedefName(D); 97 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); 98 return true; 99 } 100 101 bool VisitTagDecl(TagDecl *D) { 102 // Non-free standing tags are handled in indexTypeSourceInfo. 103 if (D->isFreeStanding()) 104 IndexCtx.indexTagDecl(D); 105 return true; 106 } 107 108 bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { 109 IndexCtx.handleObjCInterface(D); 110 111 if (D->isThisDeclarationADefinition()) { 112 IndexCtx.indexTUDeclsInObjCContainer(); 113 IndexCtx.indexDeclContext(D); 114 } 115 return true; 116 } 117 118 bool VisitObjCProtocolDecl(ObjCProtocolDecl *D) { 119 IndexCtx.handleObjCProtocol(D); 120 121 if (D->isThisDeclarationADefinition()) { 122 IndexCtx.indexTUDeclsInObjCContainer(); 123 IndexCtx.indexDeclContext(D); 124 } 125 return true; 126 } 127 128 bool VisitObjCImplementationDecl(ObjCImplementationDecl *D) { 129 const ObjCInterfaceDecl *Class = D->getClassInterface(); 130 if (!Class) 131 return true; 132 133 if (Class->isImplicitInterfaceDecl()) 134 IndexCtx.handleObjCInterface(Class); 135 136 IndexCtx.handleObjCImplementation(D); 137 138 IndexCtx.indexTUDeclsInObjCContainer(); 139 IndexCtx.indexDeclContext(D); 140 return true; 141 } 142 143 bool VisitObjCCategoryDecl(ObjCCategoryDecl *D) { 144 IndexCtx.handleObjCCategory(D); 145 146 IndexCtx.indexTUDeclsInObjCContainer(); 147 IndexCtx.indexDeclContext(D); 148 return true; 149 } 150 151 bool VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { 152 const ObjCCategoryDecl *Cat = D->getCategoryDecl(); 153 if (!Cat) 154 return true; 155 156 IndexCtx.handleObjCCategoryImpl(D); 157 158 IndexCtx.indexTUDeclsInObjCContainer(); 159 IndexCtx.indexDeclContext(D); 160 return true; 161 } 162 163 bool VisitObjCMethodDecl(ObjCMethodDecl *D) { 164 IndexCtx.handleObjCMethod(D); 165 IndexCtx.indexTypeSourceInfo(D->getResultTypeSourceInfo(), D); 166 for (ObjCMethodDecl::param_iterator 167 I = D->param_begin(), E = D->param_end(); I != E; ++I) 168 handleDeclarator(*I, D); 169 170 if (D->isThisDeclarationADefinition()) { 171 const Stmt *Body = D->getBody(); 172 if (Body) { 173 IndexCtx.indexBody(Body, D, D); 174 } 175 } 176 return true; 177 } 178 179 bool VisitObjCPropertyDecl(ObjCPropertyDecl *D) { 180 IndexCtx.handleObjCProperty(D); 181 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); 182 return true; 183 } 184 185 bool VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { 186 ObjCPropertyDecl *PD = D->getPropertyDecl(); 187 IndexCtx.handleSynthesizedObjCProperty(D); 188 189 if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 190 return true; 191 assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize); 192 193 if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) { 194 if (!IvarD->getSynthesize()) 195 IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), 0, 196 D->getDeclContext()); 197 } 198 199 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) { 200 if (MD->isSynthesized()) 201 IndexCtx.handleSynthesizedObjCMethod(MD, D->getLocation()); 202 } 203 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) { 204 if (MD->isSynthesized()) 205 IndexCtx.handleSynthesizedObjCMethod(MD, D->getLocation()); 206 } 207 return true; 208 } 209 210 bool VisitNamespaceDecl(NamespaceDecl *D) { 211 IndexCtx.handleNamespace(D); 212 IndexCtx.indexDeclContext(D); 213 return true; 214 } 215 216 bool VisitUsingDecl(UsingDecl *D) { 217 // FIXME: Parent for the following is CXIdxEntity_Unexposed with no USR, 218 // we should do better. 219 220 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D); 221 for (UsingDecl::shadow_iterator 222 I = D->shadow_begin(), E = D->shadow_end(); I != E; ++I) { 223 IndexCtx.handleReference((*I)->getUnderlyingDecl(), D->getLocation(), 224 D, D->getLexicalDeclContext()); 225 } 226 return true; 227 } 228 229 bool VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { 230 // FIXME: Parent for the following is CXIdxEntity_Unexposed with no USR, 231 // we should do better. 232 233 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D); 234 IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(), 235 D->getLocation(), D, D->getLexicalDeclContext()); 236 return true; 237 } 238 239 bool VisitClassTemplateDecl(ClassTemplateDecl *D) { 240 IndexCtx.handleClassTemplate(D); 241 if (D->isThisDeclarationADefinition()) 242 IndexCtx.indexDeclContext(D->getTemplatedDecl()); 243 return true; 244 } 245 246 bool VisitClassTemplateSpecializationDecl( 247 ClassTemplateSpecializationDecl *D) { 248 // FIXME: Notify subsequent callbacks if info comes from implicit 249 // instantiation. 250 if (D->isThisDeclarationADefinition() && 251 (IndexCtx.shouldIndexImplicitTemplateInsts() || 252 !IndexCtx.isTemplateImplicitInstantiation(D))) 253 IndexCtx.indexTagDecl(D); 254 return true; 255 } 256 257 bool VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { 258 IndexCtx.handleFunctionTemplate(D); 259 FunctionDecl *FD = D->getTemplatedDecl(); 260 handleDeclarator(FD, D); 261 if (FD->isThisDeclarationADefinition()) { 262 const Stmt *Body = FD->getBody(); 263 if (Body) { 264 IndexCtx.indexBody(Body, D, FD); 265 } 266 } 267 return true; 268 } 269 270 bool VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { 271 IndexCtx.handleTypeAliasTemplate(D); 272 IndexCtx.indexTypeSourceInfo(D->getTemplatedDecl()->getTypeSourceInfo(), D); 273 return true; 274 } 275}; 276 277} // anonymous namespace 278 279void IndexingContext::indexDecl(const Decl *D) { 280 if (D->isImplicit() && shouldIgnoreIfImplicit(D)) 281 return; 282 283 bool Handled = IndexingDeclVisitor(*this).Visit(const_cast<Decl*>(D)); 284 if (!Handled && isa<DeclContext>(D)) 285 indexDeclContext(cast<DeclContext>(D)); 286} 287 288void IndexingContext::indexDeclContext(const DeclContext *DC) { 289 for (DeclContext::decl_iterator 290 I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) { 291 indexDecl(*I); 292 } 293} 294 295void IndexingContext::indexTopLevelDecl(Decl *D) { 296 if (isNotFromSourceFile(D->getLocation())) 297 return; 298 299 if (isa<ObjCMethodDecl>(D)) 300 return; // Wait for the objc container. 301 302 indexDecl(D); 303} 304 305void IndexingContext::indexDeclGroupRef(DeclGroupRef DG) { 306 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) 307 indexTopLevelDecl(*I); 308} 309 310void IndexingContext::indexTUDeclsInObjCContainer() { 311 for (unsigned i = 0, e = TUDeclsInObjCContainer.size(); i != e; ++i) 312 indexDeclGroupRef(TUDeclsInObjCContainer[i]); 313 TUDeclsInObjCContainer.clear(); 314} 315