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