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