IndexDecl.cpp revision db4d7a5f47d13bf346260ac35eaafd2c92e5606e
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.indexFunctionLocalSymbols()) { 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 if (D->isThisDeclarationADefinition()) { 48 const Stmt *Body = D->getBody(); 49 if (Body) { 50 IndexCtx.indexBody(Body, D, D); 51 } 52 } 53 return true; 54 } 55 56 bool VisitVarDecl(VarDecl *D) { 57 IndexCtx.handleVar(D); 58 handleDeclarator(D); 59 IndexCtx.indexBody(D->getInit(), D); 60 return true; 61 } 62 63 bool VisitFieldDecl(FieldDecl *D) { 64 IndexCtx.handleField(D); 65 handleDeclarator(D); 66 if (D->isBitField()) 67 IndexCtx.indexBody(D->getBitWidth(), D); 68 else if (D->hasInClassInitializer()) 69 IndexCtx.indexBody(D->getInClassInitializer(), D); 70 return true; 71 } 72 73 bool VisitEnumConstantDecl(EnumConstantDecl *D) { 74 IndexCtx.handleEnumerator(D); 75 IndexCtx.indexBody(D->getInitExpr(), D); 76 return true; 77 } 78 79 bool VisitTypedefDecl(TypedefNameDecl *D) { 80 IndexCtx.handleTypedefName(D); 81 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); 82 return true; 83 } 84 85 bool VisitTagDecl(TagDecl *D) { 86 // Non-free standing tags are handled in indexTypeSourceInfo. 87 if (D->isFreeStanding()) 88 IndexCtx.indexTagDecl(D); 89 return true; 90 } 91 92 bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { 93 IndexCtx.handleObjCInterface(D); 94 95 if (D->isThisDeclarationADefinition()) { 96 IndexCtx.indexTUDeclsInObjCContainer(); 97 IndexCtx.indexDeclContext(D); 98 } 99 return true; 100 } 101 102 bool VisitObjCProtocolDecl(ObjCProtocolDecl *D) { 103 IndexCtx.handleObjCProtocol(D); 104 105 if (D->isThisDeclarationADefinition()) { 106 IndexCtx.indexTUDeclsInObjCContainer(); 107 IndexCtx.indexDeclContext(D); 108 } 109 return true; 110 } 111 112 bool VisitObjCImplementationDecl(ObjCImplementationDecl *D) { 113 const ObjCInterfaceDecl *Class = D->getClassInterface(); 114 if (!Class) 115 return true; 116 117 if (Class->isImplicitInterfaceDecl()) 118 IndexCtx.handleObjCInterface(Class); 119 120 IndexCtx.handleObjCImplementation(D); 121 122 IndexCtx.indexTUDeclsInObjCContainer(); 123 IndexCtx.indexDeclContext(D); 124 return true; 125 } 126 127 bool VisitObjCCategoryDecl(ObjCCategoryDecl *D) { 128 IndexCtx.handleObjCCategory(D); 129 130 IndexCtx.indexTUDeclsInObjCContainer(); 131 IndexCtx.indexDeclContext(D); 132 return true; 133 } 134 135 bool VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { 136 const ObjCCategoryDecl *Cat = D->getCategoryDecl(); 137 if (!Cat) 138 return true; 139 140 IndexCtx.handleObjCCategoryImpl(D); 141 142 IndexCtx.indexTUDeclsInObjCContainer(); 143 IndexCtx.indexDeclContext(D); 144 return true; 145 } 146 147 bool VisitObjCMethodDecl(ObjCMethodDecl *D) { 148 IndexCtx.handleObjCMethod(D); 149 IndexCtx.indexTypeSourceInfo(D->getResultTypeSourceInfo(), D); 150 for (ObjCMethodDecl::param_iterator 151 I = D->param_begin(), E = D->param_end(); I != E; ++I) 152 handleDeclarator(*I, D); 153 154 if (D->isThisDeclarationADefinition()) { 155 const Stmt *Body = D->getBody(); 156 if (Body) { 157 IndexCtx.indexBody(Body, D, D); 158 } 159 } 160 return true; 161 } 162 163 bool VisitObjCPropertyDecl(ObjCPropertyDecl *D) { 164 IndexCtx.handleObjCProperty(D); 165 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); 166 return true; 167 } 168 169 bool VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { 170 ObjCPropertyDecl *PD = D->getPropertyDecl(); 171 IndexCtx.handleSynthesizedObjCProperty(D); 172 173 if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 174 return true; 175 assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize); 176 177 if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) { 178 if (!IvarD->getSynthesize()) 179 IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), 0, 180 D->getDeclContext()); 181 } 182 183 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) { 184 if (MD->isSynthesized()) 185 IndexCtx.handleSynthesizedObjCMethod(MD, D->getLocation()); 186 } 187 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) { 188 if (MD->isSynthesized()) 189 IndexCtx.handleSynthesizedObjCMethod(MD, D->getLocation()); 190 } 191 return true; 192 } 193 194 bool VisitNamespaceDecl(NamespaceDecl *D) { 195 IndexCtx.handleNamespace(D); 196 IndexCtx.indexDeclContext(D); 197 return true; 198 } 199 200 bool VisitClassTemplateDecl(ClassTemplateDecl *D) { 201 IndexCtx.handleClassTemplate(D); 202 if (D->isThisDeclarationADefinition()) 203 IndexCtx.indexDeclContext(D->getTemplatedDecl()); 204 return true; 205 } 206 207 bool VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { 208 IndexCtx.handleFunctionTemplate(D); 209 FunctionDecl *FD = D->getTemplatedDecl(); 210 handleDeclarator(FD, D); 211 if (FD->isThisDeclarationADefinition()) { 212 const Stmt *Body = FD->getBody(); 213 if (Body) { 214 IndexCtx.indexBody(Body, D, FD); 215 } 216 } 217 return true; 218 } 219 220 bool VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { 221 IndexCtx.handleTypeAliasTemplate(D); 222 IndexCtx.indexTypeSourceInfo(D->getTemplatedDecl()->getTypeSourceInfo(), D); 223 return true; 224 } 225}; 226 227} // anonymous namespace 228 229void IndexingContext::indexDecl(const Decl *D) { 230 bool Handled = IndexingDeclVisitor(*this).Visit(const_cast<Decl*>(D)); 231 if (!Handled && isa<DeclContext>(D)) 232 indexDeclContext(cast<DeclContext>(D)); 233} 234 235void IndexingContext::indexDeclContext(const DeclContext *DC) { 236 for (DeclContext::decl_iterator 237 I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) { 238 indexDecl(*I); 239 } 240} 241 242void IndexingContext::indexTopLevelDecl(Decl *D) { 243 if (isNotFromSourceFile(D->getLocation())) 244 return; 245 246 if (isa<ObjCMethodDecl>(D)) 247 return; // Wait for the objc container. 248 249 indexDecl(D); 250} 251 252void IndexingContext::indexDeclGroupRef(DeclGroupRef DG) { 253 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) 254 indexTopLevelDecl(*I); 255} 256 257void IndexingContext::indexTUDeclsInObjCContainer() { 258 for (unsigned i = 0, e = TUDeclsInObjCContainer.size(); i != e; ++i) 259 indexDeclGroupRef(TUDeclsInObjCContainer[i]); 260 TUDeclsInObjCContainer.clear(); 261} 262