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