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