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