IndexingContext.h revision b395c63b473bf1b3783bff371a993332e8c4c5e3
1//===- IndexingContext.h - 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 "Index_Internal.h" 11#include "CXCursor.h" 12 13#include "clang/AST/DeclObjC.h" 14#include "clang/AST/DeclGroup.h" 15#include "llvm/ADT/DenseSet.h" 16 17namespace clang { 18 class FileEntry; 19 class ObjCPropertyDecl; 20 class ObjCClassDecl; 21 22namespace cxindex { 23 class IndexingContext; 24 25struct DeclInfo : public CXIdxDeclInfo { 26 CXIdxEntityInfo CXEntInfo; 27 enum DInfoKind { 28 Info_Decl, 29 30 Info_ObjCContainer, 31 Info_ObjCInterface, 32 Info_ObjCProtocol, 33 Info_ObjCCategory 34 }; 35 36 DInfoKind Kind; 37 38 DeclInfo(bool isRedeclaration, bool isDefinition, bool isContainer) 39 : Kind(Info_Decl) { 40 this->isRedeclaration = isRedeclaration; 41 this->isDefinition = isDefinition; 42 this->isContainer = isContainer; 43 attributes = 0; 44 numAttributes = 0; 45 } 46 DeclInfo(DInfoKind K, 47 bool isRedeclaration, bool isDefinition, bool isContainer) 48 : Kind(K) { 49 this->isRedeclaration = isRedeclaration; 50 this->isDefinition = isDefinition; 51 this->isContainer = isContainer; 52 attributes = 0; 53 numAttributes = 0; 54 } 55 56 static bool classof(const DeclInfo *) { return true; } 57}; 58 59struct ObjCContainerDeclInfo : public DeclInfo { 60 CXIdxObjCContainerDeclInfo ObjCContDeclInfo; 61 62 ObjCContainerDeclInfo(bool isForwardRef, 63 bool isRedeclaration, 64 bool isImplementation) 65 : DeclInfo(Info_ObjCContainer, isRedeclaration, 66 /*isDefinition=*/!isForwardRef, /*isContainer=*/!isForwardRef) { 67 init(isForwardRef, isImplementation); 68 } 69 ObjCContainerDeclInfo(DInfoKind K, 70 bool isForwardRef, 71 bool isRedeclaration, 72 bool isImplementation) 73 : DeclInfo(K, isRedeclaration, /*isDefinition=*/!isForwardRef, 74 /*isContainer=*/!isForwardRef) { 75 init(isForwardRef, isImplementation); 76 } 77 78 static bool classof(const DeclInfo *D) { 79 return Info_ObjCContainer <= D->Kind && D->Kind <= Info_ObjCCategory; 80 } 81 static bool classof(const ObjCContainerDeclInfo *D) { return true; } 82 83private: 84 void init(bool isForwardRef, bool isImplementation) { 85 if (isForwardRef) 86 ObjCContDeclInfo.kind = CXIdxObjCContainer_ForwardRef; 87 else if (isImplementation) 88 ObjCContDeclInfo.kind = CXIdxObjCContainer_Implementation; 89 else 90 ObjCContDeclInfo.kind = CXIdxObjCContainer_Interface; 91 } 92}; 93 94struct ObjCInterfaceDeclInfo : public ObjCContainerDeclInfo { 95 CXIdxObjCInterfaceDeclInfo ObjCInterDeclInfo; 96 CXIdxObjCProtocolRefListInfo ObjCProtoListInfo; 97 98 ObjCInterfaceDeclInfo(const ObjCInterfaceDecl *D) 99 : ObjCContainerDeclInfo(Info_ObjCInterface, 100 /*isForwardRef=*/false, 101 /*isRedeclaration=*/D->isInitiallyForwardDecl(), 102 /*isImplementation=*/false) { } 103 104 static bool classof(const DeclInfo *D) { 105 return D->Kind == Info_ObjCInterface; 106 } 107 static bool classof(const ObjCInterfaceDeclInfo *D) { return true; } 108}; 109 110struct ObjCProtocolDeclInfo : public ObjCContainerDeclInfo { 111 CXIdxObjCProtocolRefListInfo ObjCProtoRefListInfo; 112 113 ObjCProtocolDeclInfo(const ObjCProtocolDecl *D) 114 : ObjCContainerDeclInfo(Info_ObjCProtocol, 115 /*isForwardRef=*/false, 116 /*isRedeclaration=*/D->isInitiallyForwardDecl(), 117 /*isImplementation=*/false) { } 118 119 static bool classof(const DeclInfo *D) { 120 return D->Kind == Info_ObjCProtocol; 121 } 122 static bool classof(const ObjCProtocolDeclInfo *D) { return true; } 123}; 124 125struct ObjCCategoryDeclInfo : public ObjCContainerDeclInfo { 126 CXIdxObjCCategoryDeclInfo ObjCCatDeclInfo; 127 128 explicit ObjCCategoryDeclInfo(bool isImplementation) 129 : ObjCContainerDeclInfo(Info_ObjCCategory, 130 /*isForwardRef=*/false, 131 /*isRedeclaration=*/isImplementation, 132 /*isImplementation=*/isImplementation) { } 133 134 static bool classof(const DeclInfo *D) { 135 return D->Kind == Info_ObjCCategory; 136 } 137 static bool classof(const ObjCCategoryDeclInfo *D) { return true; } 138}; 139 140struct AttrInfo : public CXIdxAttrInfo { 141 const Attr *A; 142 143 AttrInfo(CXIdxAttrKind Kind, CXCursor C, CXIdxLoc Loc, const Attr *A) { 144 kind = Kind; 145 cursor = C; 146 loc = Loc; 147 this->A = A; 148 } 149 150 static bool classof(const AttrInfo *) { return true; } 151}; 152 153struct IBOutletCollectionInfo : public AttrInfo { 154 CXIdxEntityInfo CXClassInfo; 155 CXIdxIBOutletCollectionAttrInfo IBCollInfo; 156 157 IBOutletCollectionInfo(CXCursor C, CXIdxLoc Loc, const Attr *A) : 158 AttrInfo(CXIdxAttr_IBOutletCollection, C, Loc, A) { 159 assert(C.kind == CXCursor_IBOutletCollectionAttr); 160 } 161 162 static bool classof(const AttrInfo *A) { 163 return A->kind == CXIdxAttr_IBOutletCollection; 164 } 165 static bool classof(const IBOutletCollectionInfo *D) { return true; } 166}; 167 168struct RefFileOccurence { 169 const FileEntry *File; 170 const Decl *Dcl; 171 172 RefFileOccurence(const FileEntry *File, const Decl *Dcl) 173 : File(File), Dcl(Dcl) { } 174}; 175 176class IndexingContext { 177 ASTContext *Ctx; 178 CXClientData ClientData; 179 IndexerCallbacks &CB; 180 unsigned IndexOptions; 181 CXTranslationUnit CXTU; 182 183 typedef llvm::DenseMap<const FileEntry *, CXIdxClientFile> FileMapTy; 184 typedef llvm::DenseMap<const DeclContext *, CXIdxClientContainer> ContainerMapTy; 185 FileMapTy FileMap; 186 ContainerMapTy ContainerMap; 187 188 llvm::DenseSet<RefFileOccurence> RefFileOccurences; 189 190 SmallVector<DeclGroupRef, 8> TUDeclsInObjCContainer; 191 192 llvm::SmallString<256> StrScratch; 193 unsigned StrAdapterCount; 194 195 class StrAdapter { 196 llvm::SmallString<256> &Scratch; 197 IndexingContext &IdxCtx; 198 199 public: 200 StrAdapter(IndexingContext &indexCtx) 201 : Scratch(indexCtx.StrScratch), IdxCtx(indexCtx) { 202 ++IdxCtx.StrAdapterCount; 203 } 204 205 ~StrAdapter() { 206 --IdxCtx.StrAdapterCount; 207 if (IdxCtx.StrAdapterCount == 0) 208 Scratch.clear(); 209 } 210 211 const char *toCStr(StringRef Str); 212 213 unsigned getCurSize() const { return Scratch.size(); } 214 215 const char *getCStr(unsigned CharIndex) { 216 Scratch.push_back('\0'); 217 return Scratch.data() + CharIndex; 218 } 219 220 SmallVectorImpl<char> &getBuffer() { return Scratch; } 221 }; 222 223 struct ObjCProtocolListInfo { 224 SmallVector<CXIdxObjCProtocolRefInfo, 4> ProtInfos; 225 SmallVector<CXIdxEntityInfo, 4> ProtEntities; 226 SmallVector<CXIdxObjCProtocolRefInfo *, 4> Prots; 227 228 CXIdxObjCProtocolRefListInfo getListInfo() const { 229 CXIdxObjCProtocolRefListInfo Info = { Prots.data(), 230 (unsigned)Prots.size() }; 231 return Info; 232 } 233 234 ObjCProtocolListInfo(const ObjCProtocolList &ProtList, 235 IndexingContext &IdxCtx, 236 IndexingContext::StrAdapter &SA); 237 }; 238 239 struct AttrListInfo { 240 SmallVector<AttrInfo, 2> Attrs; 241 SmallVector<IBOutletCollectionInfo, 2> IBCollAttrs; 242 SmallVector<CXIdxAttrInfo *, 2> CXAttrs; 243 244 const CXIdxAttrInfo *const *getAttrs() const { 245 return CXAttrs.data(); 246 } 247 unsigned getNumAttrs() const { return (unsigned)CXAttrs.size(); } 248 249 AttrListInfo(const Decl *D, 250 IndexingContext &IdxCtx, 251 IndexingContext::StrAdapter &SA); 252}; 253 254public: 255 IndexingContext(CXClientData clientData, IndexerCallbacks &indexCallbacks, 256 unsigned indexOptions, CXTranslationUnit cxTU) 257 : Ctx(0), ClientData(clientData), CB(indexCallbacks), 258 IndexOptions(indexOptions), CXTU(cxTU), StrAdapterCount(0) { } 259 260 ASTContext &getASTContext() const { return *Ctx; } 261 262 void setASTContext(ASTContext &ctx); 263 264 bool suppressRefs() const { 265 return IndexOptions & CXIndexOpt_SuppressRedundantRefs; 266 } 267 268 bool shouldAbort(); 269 270 void enteredMainFile(const FileEntry *File); 271 272 void ppIncludedFile(SourceLocation hashLoc, 273 StringRef filename, const FileEntry *File, 274 bool isImport, bool isAngled); 275 276 void startedTranslationUnit(); 277 278 void indexDecl(const Decl *D); 279 280 void indexTagDecl(const TagDecl *D); 281 282 void indexTypeSourceInfo(TypeSourceInfo *TInfo, const NamedDecl *Parent, 283 const DeclContext *DC = 0); 284 285 void indexTypeLoc(TypeLoc TL, const NamedDecl *Parent, 286 const DeclContext *DC); 287 288 void indexDeclContext(const DeclContext *DC); 289 290 void indexBody(const Stmt *S, const DeclContext *DC); 291 292 void handleDiagnosticSet(CXDiagnosticSet CXDiagSet); 293 294 bool handleFunction(const FunctionDecl *FD); 295 296 bool handleVar(const VarDecl *D); 297 298 bool handleField(const FieldDecl *D); 299 300 bool handleEnumerator(const EnumConstantDecl *D); 301 302 bool handleTagDecl(const TagDecl *D); 303 304 bool handleTypedef(const TypedefDecl *D); 305 306 bool handleObjCClass(const ObjCClassDecl *D); 307 bool handleObjCInterface(const ObjCInterfaceDecl *D); 308 bool handleObjCImplementation(const ObjCImplementationDecl *D); 309 310 bool handleObjCForwardProtocol(const ObjCProtocolDecl *D, 311 SourceLocation Loc, 312 bool isRedeclaration); 313 314 bool handleObjCProtocol(const ObjCProtocolDecl *D); 315 316 bool handleObjCCategory(const ObjCCategoryDecl *D); 317 bool handleObjCCategoryImpl(const ObjCCategoryImplDecl *D); 318 319 bool handleObjCMethod(const ObjCMethodDecl *D); 320 321 bool handleSynthesizedObjCProperty(const ObjCPropertyImplDecl *D); 322 bool handleSynthesizedObjCMethod(const ObjCMethodDecl *D, SourceLocation Loc); 323 324 bool handleObjCProperty(const ObjCPropertyDecl *D); 325 326 bool handleReference(const NamedDecl *D, SourceLocation Loc, CXCursor Cursor, 327 const NamedDecl *Parent, 328 const DeclContext *DC, 329 const Expr *E = 0, 330 CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct); 331 332 bool handleReference(const NamedDecl *D, SourceLocation Loc, 333 const NamedDecl *Parent, 334 const DeclContext *DC, 335 const Expr *E = 0, 336 CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct); 337 338 bool isNotFromSourceFile(SourceLocation Loc) const; 339 340 void indexTopLevelDecl(Decl *D); 341 void indexTUDeclsInObjCContainer(); 342 void indexDeclGroupRef(DeclGroupRef DG); 343 344 void addTUDeclInObjCContainer(DeclGroupRef DG) { 345 TUDeclsInObjCContainer.push_back(DG); 346 } 347 348 void translateLoc(SourceLocation Loc, CXIdxClientFile *indexFile, CXFile *file, 349 unsigned *line, unsigned *column, unsigned *offset); 350 351private: 352 bool handleDecl(const NamedDecl *D, 353 SourceLocation Loc, CXCursor Cursor, 354 DeclInfo &DInfo); 355 356 bool handleObjCContainer(const ObjCContainerDecl *D, 357 SourceLocation Loc, CXCursor Cursor, 358 ObjCContainerDeclInfo &ContDInfo); 359 360 void addContainerInMap(const DeclContext *DC, CXIdxClientContainer container); 361 362 bool markEntityOccurrenceInFile(const NamedDecl *D, SourceLocation Loc); 363 364 const NamedDecl *getEntityDecl(const NamedDecl *D) const; 365 366 CXIdxClientContainer getIndexContainer(const NamedDecl *D) const { 367 return getIndexContainerForDC(D->getDeclContext()); 368 } 369 370 const DeclContext *getScopedContext(const DeclContext *DC) const; 371 CXIdxClientContainer getIndexContainerForDC(const DeclContext *DC) const; 372 373 CXIdxClientFile getIndexFile(const FileEntry *File); 374 375 CXIdxLoc getIndexLoc(SourceLocation Loc) const; 376 377 void getEntityInfo(const NamedDecl *D, 378 CXIdxEntityInfo &EntityInfo, 379 StrAdapter &SA); 380 381 CXCursor getCursor(const Decl *D) { 382 return cxcursor::MakeCXCursor(const_cast<Decl*>(D), CXTU); 383 } 384 385 CXCursor getRefCursor(const NamedDecl *D, SourceLocation Loc); 386}; 387 388}} // end clang::cxindex 389 390namespace llvm { 391 /// Define DenseMapInfo so that FileID's can be used as keys in DenseMap and 392 /// DenseSets. 393 template <> 394 struct DenseMapInfo<clang::cxindex::RefFileOccurence> { 395 static inline clang::cxindex::RefFileOccurence getEmptyKey() { 396 return clang::cxindex::RefFileOccurence(0, 0); 397 } 398 399 static inline clang::cxindex::RefFileOccurence getTombstoneKey() { 400 return clang::cxindex::RefFileOccurence((const clang::FileEntry *)~0, 401 (const clang::Decl *)~0); 402 } 403 404 static unsigned getHashValue(clang::cxindex::RefFileOccurence S) { 405 llvm::FoldingSetNodeID ID; 406 ID.AddPointer(S.File); 407 ID.AddPointer(S.Dcl); 408 return ID.ComputeHash(); 409 } 410 411 static bool isEqual(clang::cxindex::RefFileOccurence LHS, 412 clang::cxindex::RefFileOccurence RHS) { 413 return LHS.File == RHS.File && LHS.Dcl == RHS.Dcl; 414 } 415 }; 416} 417