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