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: 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 VisitEnumConstantDecl(const EnumConstantDecl *D) { 109 IndexCtx.handleEnumerator(D); 110 IndexCtx.indexBody(D->getInitExpr(), D); 111 return true; 112 } 113 114 bool VisitTypedefNameDecl(const TypedefNameDecl *D) { 115 IndexCtx.handleTypedefName(D); 116 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); 117 return true; 118 } 119 120 bool VisitTagDecl(const TagDecl *D) { 121 // Non-free standing tags are handled in indexTypeSourceInfo. 122 if (D->isFreeStanding()) 123 IndexCtx.indexTagDecl(D); 124 return true; 125 } 126 127 bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { 128 IndexCtx.handleObjCInterface(D); 129 130 if (D->isThisDeclarationADefinition()) { 131 IndexCtx.indexTUDeclsInObjCContainer(); 132 IndexCtx.indexDeclContext(D); 133 } 134 return true; 135 } 136 137 bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) { 138 IndexCtx.handleObjCProtocol(D); 139 140 if (D->isThisDeclarationADefinition()) { 141 IndexCtx.indexTUDeclsInObjCContainer(); 142 IndexCtx.indexDeclContext(D); 143 } 144 return true; 145 } 146 147 bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) { 148 const ObjCInterfaceDecl *Class = D->getClassInterface(); 149 if (!Class) 150 return true; 151 152 if (Class->isImplicitInterfaceDecl()) 153 IndexCtx.handleObjCInterface(Class); 154 155 IndexCtx.handleObjCImplementation(D); 156 157 IndexCtx.indexTUDeclsInObjCContainer(); 158 159 // Index the ivars first to make sure the synthesized ivars are indexed 160 // before indexing the methods that can reference them. 161 for (ObjCImplementationDecl::ivar_iterator 162 IvarI = D->ivar_begin(), 163 IvarE = D->ivar_end(); IvarI != IvarE; ++IvarI) { 164 IndexCtx.indexDecl(*IvarI); 165 } 166 for (DeclContext::decl_iterator 167 I = D->decls_begin(), E = D->decls_end(); I != E; ++I) { 168 if (!isa<ObjCIvarDecl>(*I)) 169 IndexCtx.indexDecl(*I); 170 } 171 172 return true; 173 } 174 175 bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { 176 IndexCtx.handleObjCCategory(D); 177 178 IndexCtx.indexTUDeclsInObjCContainer(); 179 IndexCtx.indexDeclContext(D); 180 return true; 181 } 182 183 bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) { 184 const ObjCCategoryDecl *Cat = D->getCategoryDecl(); 185 if (!Cat) 186 return true; 187 188 IndexCtx.handleObjCCategoryImpl(D); 189 190 IndexCtx.indexTUDeclsInObjCContainer(); 191 IndexCtx.indexDeclContext(D); 192 return true; 193 } 194 195 bool VisitObjCMethodDecl(const ObjCMethodDecl *D) { 196 // Methods associated with a property, even user-declared ones, are 197 // handled when we handle the property. 198 if (D->isPropertyAccessor()) 199 return true; 200 201 handleObjCMethod(D); 202 return true; 203 } 204 205 bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { 206 if (ObjCMethodDecl *MD = D->getGetterMethodDecl()) 207 if (MD->getLexicalDeclContext() == D->getLexicalDeclContext()) 208 handleObjCMethod(MD); 209 if (ObjCMethodDecl *MD = D->getSetterMethodDecl()) 210 if (MD->getLexicalDeclContext() == D->getLexicalDeclContext()) 211 handleObjCMethod(MD); 212 IndexCtx.handleObjCProperty(D); 213 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); 214 return true; 215 } 216 217 bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { 218 ObjCPropertyDecl *PD = D->getPropertyDecl(); 219 IndexCtx.handleSynthesizedObjCProperty(D); 220 221 if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 222 return true; 223 assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize); 224 225 if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) { 226 if (!IvarD->getSynthesize()) 227 IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), 0, 228 D->getDeclContext()); 229 } 230 231 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) { 232 if (MD->isPropertyAccessor()) 233 IndexCtx.handleSynthesizedObjCMethod(MD, D->getLocation(), 234 D->getLexicalDeclContext()); 235 } 236 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) { 237 if (MD->isPropertyAccessor()) 238 IndexCtx.handleSynthesizedObjCMethod(MD, D->getLocation(), 239 D->getLexicalDeclContext()); 240 } 241 return true; 242 } 243 244 bool VisitNamespaceDecl(const NamespaceDecl *D) { 245 IndexCtx.handleNamespace(D); 246 IndexCtx.indexDeclContext(D); 247 return true; 248 } 249 250 bool VisitUsingDecl(const UsingDecl *D) { 251 // FIXME: Parent for the following is CXIdxEntity_Unexposed with no USR, 252 // we should do better. 253 254 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D); 255 for (UsingDecl::shadow_iterator 256 I = D->shadow_begin(), E = D->shadow_end(); I != E; ++I) { 257 IndexCtx.handleReference((*I)->getUnderlyingDecl(), D->getLocation(), 258 D, D->getLexicalDeclContext()); 259 } 260 return true; 261 } 262 263 bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) { 264 // FIXME: Parent for the following is CXIdxEntity_Unexposed with no USR, 265 // we should do better. 266 267 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D); 268 IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(), 269 D->getLocation(), D, D->getLexicalDeclContext()); 270 return true; 271 } 272 273 bool VisitClassTemplateDecl(const ClassTemplateDecl *D) { 274 IndexCtx.handleClassTemplate(D); 275 if (D->isThisDeclarationADefinition()) 276 IndexCtx.indexDeclContext(D->getTemplatedDecl()); 277 return true; 278 } 279 280 bool VisitClassTemplateSpecializationDecl(const 281 ClassTemplateSpecializationDecl *D) { 282 // FIXME: Notify subsequent callbacks if info comes from implicit 283 // instantiation. 284 if (D->isThisDeclarationADefinition() && 285 (IndexCtx.shouldIndexImplicitTemplateInsts() || 286 !IndexCtx.isTemplateImplicitInstantiation(D))) 287 IndexCtx.indexTagDecl(D); 288 return true; 289 } 290 291 bool VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) { 292 IndexCtx.handleFunctionTemplate(D); 293 FunctionDecl *FD = D->getTemplatedDecl(); 294 handleDeclarator(FD, D); 295 if (FD->isThisDeclarationADefinition()) { 296 const Stmt *Body = FD->getBody(); 297 if (Body) { 298 IndexCtx.indexBody(Body, D, FD); 299 } 300 } 301 return true; 302 } 303 304 bool VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) { 305 IndexCtx.handleTypeAliasTemplate(D); 306 IndexCtx.indexTypeSourceInfo(D->getTemplatedDecl()->getTypeSourceInfo(), D); 307 return true; 308 } 309 310 bool VisitImportDecl(const ImportDecl *D) { 311 IndexCtx.importedModule(D); 312 return true; 313 } 314 }; 315 316 } // anonymous namespace 317 318 void IndexingContext::indexDecl(const Decl *D) { 319 if (D->isImplicit() && shouldIgnoreIfImplicit(D)) 320 return; 321 322 bool Handled = IndexingDeclVisitor(*this).Visit(D); 323 if (!Handled && isa<DeclContext>(D)) 324 indexDeclContext(cast<DeclContext>(D)); 325 } 326 327 void IndexingContext::indexDeclContext(const DeclContext *DC) { 328 for (DeclContext::decl_iterator 329 I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) { 330 indexDecl(*I); 331 } 332 } 333 334 void IndexingContext::indexTopLevelDecl(const Decl *D) { 335 if (isNotFromSourceFile(D->getLocation())) 336 return; 337 338 if (isa<ObjCMethodDecl>(D)) 339 return; // Wait for the objc container. 340 341 indexDecl(D); 342 } 343 344 void IndexingContext::indexDeclGroupRef(DeclGroupRef DG) { 345 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) 346 indexTopLevelDecl(*I); 347 } 348 349 void IndexingContext::indexTUDeclsInObjCContainer() { 350 while (!TUDeclsInObjCContainer.empty()) { 351 DeclGroupRef DG = TUDeclsInObjCContainer.front(); 352 TUDeclsInObjCContainer.pop_front(); 353 indexDeclGroupRef(DG); 354 } 355 } 356