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 14 using namespace clang; 15 using namespace cxindex; 16 17 namespace { 18 19 class IndexingDeclVisitor : public DeclVisitor<IndexingDeclVisitor, bool> { 20 IndexingContext &IndexCtx; 21 22 public: 23 explicit IndexingDeclVisitor(IndexingContext &indexCtx) 24 : IndexCtx(indexCtx) { } 25 26 bool VisitFunctionDecl(FunctionDecl *D) { 27 IndexCtx.handleFunction(D); 28 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); 29 if (D->isThisDeclarationADefinition()) { 30 const Stmt *Body = D->getBody(); 31 if (Body) { 32 IndexCtx.invokeStartedStatementBody(D, D); 33 IndexCtx.indexBody(Body, D); 34 IndexCtx.invokeEndedContainer(D); 35 } 36 } 37 return true; 38 } 39 40 bool VisitVarDecl(VarDecl *D) { 41 IndexCtx.handleVar(D); 42 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); 43 return true; 44 } 45 46 bool VisitFieldDecl(FieldDecl *D) { 47 IndexCtx.handleField(D); 48 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); 49 return true; 50 } 51 52 bool VisitEnumConstantDecl(EnumConstantDecl *D) { 53 IndexCtx.handleEnumerator(D); 54 return true; 55 } 56 57 bool VisitTypedefDecl(TypedefDecl *D) { 58 IndexCtx.handleTypedef(D); 59 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); 60 return true; 61 } 62 63 bool VisitTagDecl(TagDecl *D) { 64 // Non-free standing tags are handled in indexTypeSourceInfo. 65 if (D->isFreeStanding()) 66 IndexCtx.indexTagDecl(D); 67 return true; 68 } 69 70 bool VisitObjCClassDecl(ObjCClassDecl *D) { 71 ObjCClassDecl::ObjCClassRef *Ref = D->getForwardDecl(); 72 if (Ref->getInterface()->getLocation() == Ref->getLocation()) { 73 IndexCtx.handleObjCInterface(Ref->getInterface()); 74 } else { 75 IndexCtx.handleReference(Ref->getInterface(), 76 Ref->getLocation(), 77 0, 78 Ref->getInterface()->getDeclContext()); 79 } 80 return true; 81 } 82 83 bool VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) { 84 ObjCForwardProtocolDecl::protocol_loc_iterator LI = D->protocol_loc_begin(); 85 for (ObjCForwardProtocolDecl::protocol_iterator 86 I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I, ++LI) { 87 SourceLocation Loc = *LI; 88 ObjCProtocolDecl *PD = *I; 89 90 if (PD->getLocation() == Loc) { 91 IndexCtx.handleObjCProtocol(PD); 92 } else { 93 IndexCtx.handleReference(PD, Loc, 0, PD->getDeclContext()); 94 } 95 } 96 return true; 97 } 98 99 bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { 100 // Only definitions are handled here. 101 if (D->isForwardDecl()) 102 return true; 103 104 if (!D->isInitiallyForwardDecl()) 105 IndexCtx.handleObjCInterface(D); 106 107 IndexCtx.indexTUDeclsInObjCContainer(); 108 IndexCtx.invokeStartedObjCContainer(D); 109 IndexCtx.defineObjCInterface(D); 110 IndexCtx.indexDeclContext(D); 111 IndexCtx.invokeEndedContainer(D); 112 return true; 113 } 114 115 bool VisitObjCProtocolDecl(ObjCProtocolDecl *D) { 116 // Only definitions are handled here. 117 if (D->isForwardDecl()) 118 return true; 119 120 if (!D->isInitiallyForwardDecl()) 121 IndexCtx.handleObjCProtocol(D); 122 123 IndexCtx.indexTUDeclsInObjCContainer(); 124 IndexCtx.invokeStartedObjCContainer(D); 125 IndexCtx.indexDeclContext(D); 126 IndexCtx.invokeEndedContainer(D); 127 return true; 128 } 129 130 bool VisitObjCImplementationDecl(ObjCImplementationDecl *D) { 131 ObjCInterfaceDecl *Class = D->getClassInterface(); 132 if (Class->isImplicitInterfaceDecl()) 133 IndexCtx.handleObjCInterface(Class); 134 135 IndexCtx.indexTUDeclsInObjCContainer(); 136 IndexCtx.invokeStartedObjCContainer(D); 137 IndexCtx.indexDeclContext(D); 138 IndexCtx.invokeEndedContainer(D); 139 return true; 140 } 141 142 bool VisitObjCCategoryDecl(ObjCCategoryDecl *D) { 143 if (!D->IsClassExtension()) 144 IndexCtx.handleObjCCategory(D); 145 146 IndexCtx.indexTUDeclsInObjCContainer(); 147 IndexCtx.invokeStartedObjCContainer(D); 148 IndexCtx.indexDeclContext(D); 149 IndexCtx.invokeEndedContainer(D); 150 return true; 151 } 152 153 bool VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { 154 IndexCtx.indexTUDeclsInObjCContainer(); 155 IndexCtx.invokeStartedObjCContainer(D); 156 IndexCtx.indexDeclContext(D); 157 IndexCtx.invokeEndedContainer(D); 158 return true; 159 } 160 161 bool VisitObjCMethodDecl(ObjCMethodDecl *D) { 162 IndexCtx.handleObjCMethod(D); 163 IndexCtx.indexTypeSourceInfo(D->getResultTypeSourceInfo(), D); 164 for (ObjCMethodDecl::param_iterator 165 I = D->param_begin(), E = D->param_end(); I != E; ++I) 166 IndexCtx.indexTypeSourceInfo((*I)->getTypeSourceInfo(), D); 167 168 if (D->isThisDeclarationADefinition()) { 169 const Stmt *Body = D->getBody(); 170 if (Body) { 171 IndexCtx.invokeStartedStatementBody(D, D); 172 IndexCtx.indexBody(Body, D); 173 IndexCtx.invokeEndedContainer(D); 174 } 175 } 176 return true; 177 } 178 179 bool VisitObjCPropertyDecl(ObjCPropertyDecl *D) { 180 IndexCtx.handleObjCProperty(D); 181 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); 182 return true; 183 } 184 }; 185 186 } // anonymous namespace 187 188 void IndexingContext::indexDecl(const Decl *D) { 189 bool Handled = IndexingDeclVisitor(*this).Visit(const_cast<Decl*>(D)); 190 if (!Handled && isa<DeclContext>(D)) 191 indexDeclContext(cast<DeclContext>(D)); 192 } 193 194 void IndexingContext::indexDeclContext(const DeclContext *DC) { 195 for (DeclContext::decl_iterator 196 I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) { 197 indexDecl(*I); 198 } 199 } 200 201 void IndexingContext::indexDeclGroupRef(DeclGroupRef DG) { 202 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) { 203 Decl *D = *I; 204 if (isNotFromSourceFile(D->getLocation())) 205 return; 206 207 if (isa<ObjCMethodDecl>(D)) 208 continue; // Wait for the objc container. 209 210 indexDecl(D); 211 } 212 } 213 214 void IndexingContext::indexTUDeclsInObjCContainer() { 215 for (unsigned i = 0, e = TUDeclsInObjCContainer.size(); i != e; ++i) 216 indexDeclGroupRef(TUDeclsInObjCContainer[i]); 217 TUDeclsInObjCContainer.clear(); 218 } 219