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