IndexDecl.cpp revision 375bb1413c041055262c8a416f20d10474a5eda9
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 VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) { 81 ObjCForwardProtocolDecl::protocol_loc_iterator LI = D->protocol_loc_begin(); 82 for (ObjCForwardProtocolDecl::protocol_iterator 83 I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I, ++LI) { 84 SourceLocation Loc = *LI; 85 ObjCProtocolDecl *PD = *I; 86 87 bool isRedeclaration = PD->getLocation() != Loc; 88 IndexCtx.handleObjCForwardProtocol(PD, Loc, isRedeclaration); 89 } 90 return true; 91 } 92 93 bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { 94 IndexCtx.handleObjCInterface(D); 95 96 if (D->isThisDeclarationADefinition()) { 97 IndexCtx.indexTUDeclsInObjCContainer(); 98 IndexCtx.indexDeclContext(D); 99 } 100 return true; 101 } 102 103 bool VisitObjCProtocolDecl(ObjCProtocolDecl *D) { 104 // Forward decls are handled at VisitObjCForwardProtocolDecl. 105 if (D->isForwardDecl()) 106 return true; 107 108 IndexCtx.handleObjCProtocol(D); 109 110 IndexCtx.indexTUDeclsInObjCContainer(); 111 IndexCtx.indexDeclContext(D); 112 return true; 113 } 114 115 bool VisitObjCImplementationDecl(ObjCImplementationDecl *D) { 116 const ObjCInterfaceDecl *Class = D->getClassInterface(); 117 if (!Class) 118 return true; 119 120 if (Class->isImplicitInterfaceDecl()) 121 IndexCtx.handleObjCInterface(Class); 122 123 IndexCtx.handleObjCImplementation(D); 124 125 IndexCtx.indexTUDeclsInObjCContainer(); 126 IndexCtx.indexDeclContext(D); 127 return true; 128 } 129 130 bool VisitObjCCategoryDecl(ObjCCategoryDecl *D) { 131 IndexCtx.handleObjCCategory(D); 132 133 IndexCtx.indexTUDeclsInObjCContainer(); 134 IndexCtx.indexDeclContext(D); 135 return true; 136 } 137 138 bool VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { 139 const ObjCCategoryDecl *Cat = D->getCategoryDecl(); 140 if (!Cat) 141 return true; 142 143 IndexCtx.handleObjCCategoryImpl(D); 144 145 IndexCtx.indexTUDeclsInObjCContainer(); 146 IndexCtx.indexDeclContext(D); 147 return true; 148 } 149 150 bool VisitObjCMethodDecl(ObjCMethodDecl *D) { 151 IndexCtx.handleObjCMethod(D); 152 IndexCtx.indexTypeSourceInfo(D->getResultTypeSourceInfo(), D); 153 for (ObjCMethodDecl::param_iterator 154 I = D->param_begin(), E = D->param_end(); I != E; ++I) 155 handleDeclarator(*I, D); 156 157 if (D->isThisDeclarationADefinition()) { 158 const Stmt *Body = D->getBody(); 159 if (Body) { 160 IndexCtx.indexBody(Body, D, D); 161 } 162 } 163 return true; 164 } 165 166 bool VisitObjCPropertyDecl(ObjCPropertyDecl *D) { 167 IndexCtx.handleObjCProperty(D); 168 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); 169 return true; 170 } 171 172 bool VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { 173 ObjCPropertyDecl *PD = D->getPropertyDecl(); 174 IndexCtx.handleSynthesizedObjCProperty(D); 175 176 if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 177 return true; 178 assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize); 179 180 if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) { 181 if (!IvarD->getSynthesize()) 182 IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), 0, 183 D->getDeclContext()); 184 } 185 186 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) { 187 if (MD->isSynthesized()) 188 IndexCtx.handleSynthesizedObjCMethod(MD, D->getLocation()); 189 } 190 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) { 191 if (MD->isSynthesized()) 192 IndexCtx.handleSynthesizedObjCMethod(MD, D->getLocation()); 193 } 194 return true; 195 } 196 197 bool VisitNamespaceDecl(NamespaceDecl *D) { 198 IndexCtx.handleNamespace(D); 199 IndexCtx.indexDeclContext(D); 200 return true; 201 } 202 203 bool VisitClassTemplateDecl(ClassTemplateDecl *D) { 204 IndexCtx.handleClassTemplate(D); 205 if (D->isThisDeclarationADefinition()) 206 IndexCtx.indexDeclContext(D->getTemplatedDecl()); 207 return true; 208 } 209 210 bool VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { 211 IndexCtx.handleFunctionTemplate(D); 212 FunctionDecl *FD = D->getTemplatedDecl(); 213 handleDeclarator(FD, D); 214 if (FD->isThisDeclarationADefinition()) { 215 const Stmt *Body = FD->getBody(); 216 if (Body) { 217 IndexCtx.indexBody(Body, D, FD); 218 } 219 } 220 return true; 221 } 222 223 bool VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { 224 IndexCtx.handleTypeAliasTemplate(D); 225 IndexCtx.indexTypeSourceInfo(D->getTemplatedDecl()->getTypeSourceInfo(), D); 226 return true; 227 } 228}; 229 230} // anonymous namespace 231 232void IndexingContext::indexDecl(const Decl *D) { 233 bool Handled = IndexingDeclVisitor(*this).Visit(const_cast<Decl*>(D)); 234 if (!Handled && isa<DeclContext>(D)) 235 indexDeclContext(cast<DeclContext>(D)); 236} 237 238void IndexingContext::indexDeclContext(const DeclContext *DC) { 239 for (DeclContext::decl_iterator 240 I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) { 241 indexDecl(*I); 242 } 243} 244 245void IndexingContext::indexTopLevelDecl(Decl *D) { 246 if (isNotFromSourceFile(D->getLocation())) 247 return; 248 249 if (isa<ObjCMethodDecl>(D)) 250 return; // Wait for the objc container. 251 252 indexDecl(D); 253} 254 255void IndexingContext::indexDeclGroupRef(DeclGroupRef DG) { 256 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) 257 indexTopLevelDecl(*I); 258} 259 260void IndexingContext::indexTUDeclsInObjCContainer() { 261 for (unsigned i = 0, e = TUDeclsInObjCContainer.size(); i != e; ++i) 262 indexDeclGroupRef(TUDeclsInObjCContainer[i]); 263 TUDeclsInObjCContainer.clear(); 264} 265