IndexingContext.h revision c6b4a5099588fd21b49c80f730a596a64b2766c6
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 } 44 DeclInfo(DInfoKind K, 45 bool isRedeclaration, bool isDefinition, bool isContainer) 46 : Kind(K) { 47 this->isRedeclaration = isRedeclaration; 48 this->isDefinition = isDefinition; 49 this->isContainer = isContainer; 50 } 51 52 static bool classof(const DeclInfo *) { return true; } 53}; 54 55struct ObjCContainerDeclInfo : public DeclInfo { 56 CXIdxObjCContainerDeclInfo ObjCContDeclInfo; 57 58 ObjCContainerDeclInfo(bool isForwardRef, 59 bool isRedeclaration, 60 bool isImplementation) 61 : DeclInfo(Info_ObjCContainer, isRedeclaration, 62 /*isDefinition=*/!isForwardRef, /*isContainer=*/!isForwardRef) { 63 init(isForwardRef, isImplementation); 64 } 65 ObjCContainerDeclInfo(DInfoKind K, 66 bool isForwardRef, 67 bool isRedeclaration, 68 bool isImplementation) 69 : DeclInfo(K, isRedeclaration, /*isDefinition=*/!isForwardRef, 70 /*isContainer=*/!isForwardRef) { 71 init(isForwardRef, isImplementation); 72 } 73 74 static bool classof(const DeclInfo *D) { 75 return Info_ObjCContainer <= D->Kind && D->Kind <= Info_ObjCCategory; 76 } 77 static bool classof(const ObjCContainerDeclInfo *D) { return true; } 78 79private: 80 void init(bool isForwardRef, bool isImplementation) { 81 if (isForwardRef) 82 ObjCContDeclInfo.kind = CXIdxObjCContainer_ForwardRef; 83 else if (isImplementation) 84 ObjCContDeclInfo.kind = CXIdxObjCContainer_Implementation; 85 else 86 ObjCContDeclInfo.kind = CXIdxObjCContainer_Interface; 87 } 88}; 89 90struct ObjCInterfaceDeclInfo : public ObjCContainerDeclInfo { 91 CXIdxObjCInterfaceDeclInfo ObjCInterDeclInfo; 92 CXIdxObjCProtocolRefListInfo ObjCProtoListInfo; 93 94 ObjCInterfaceDeclInfo(const ObjCInterfaceDecl *D) 95 : ObjCContainerDeclInfo(Info_ObjCInterface, 96 /*isForwardRef=*/false, 97 /*isRedeclaration=*/D->isInitiallyForwardDecl(), 98 /*isImplementation=*/false) { } 99 100 static bool classof(const DeclInfo *D) { 101 return D->Kind == Info_ObjCInterface; 102 } 103 static bool classof(const ObjCInterfaceDeclInfo *D) { return true; } 104}; 105 106struct ObjCProtocolDeclInfo : public ObjCContainerDeclInfo { 107 CXIdxObjCProtocolRefListInfo ObjCProtoRefListInfo; 108 109 ObjCProtocolDeclInfo(const ObjCProtocolDecl *D) 110 : ObjCContainerDeclInfo(Info_ObjCProtocol, 111 /*isForwardRef=*/false, 112 /*isRedeclaration=*/D->isInitiallyForwardDecl(), 113 /*isImplementation=*/false) { } 114 115 static bool classof(const DeclInfo *D) { 116 return D->Kind == Info_ObjCProtocol; 117 } 118 static bool classof(const ObjCProtocolDeclInfo *D) { return true; } 119}; 120 121struct ObjCCategoryDeclInfo : public ObjCContainerDeclInfo { 122 CXIdxObjCCategoryDeclInfo ObjCCatDeclInfo; 123 124 explicit ObjCCategoryDeclInfo(bool isImplementation) 125 : ObjCContainerDeclInfo(Info_ObjCCategory, 126 /*isForwardRef=*/false, 127 /*isRedeclaration=*/isImplementation, 128 /*isImplementation=*/isImplementation) { } 129 130 static bool classof(const DeclInfo *D) { 131 return D->Kind == Info_ObjCCategory; 132 } 133 static bool classof(const ObjCCategoryDeclInfo *D) { return true; } 134}; 135 136struct RefFileOccurence { 137 const FileEntry *File; 138 const Decl *Dcl; 139 140 RefFileOccurence(const FileEntry *File, const Decl *Dcl) 141 : File(File), Dcl(Dcl) { } 142}; 143 144class IndexingContext { 145 ASTContext *Ctx; 146 CXClientData ClientData; 147 IndexerCallbacks &CB; 148 unsigned IndexOptions; 149 CXTranslationUnit CXTU; 150 151 typedef llvm::DenseMap<const FileEntry *, CXIdxClientFile> FileMapTy; 152 typedef llvm::DenseMap<const DeclContext *, CXIdxClientContainer> ContainerMapTy; 153 FileMapTy FileMap; 154 ContainerMapTy ContainerMap; 155 156 llvm::DenseSet<RefFileOccurence> RefFileOccurences; 157 158 SmallVector<DeclGroupRef, 8> TUDeclsInObjCContainer; 159 160 llvm::SmallString<256> StrScratch; 161 unsigned StrAdapterCount; 162 163 class StrAdapter { 164 llvm::SmallString<256> &Scratch; 165 IndexingContext &IdxCtx; 166 167 public: 168 StrAdapter(IndexingContext &indexCtx) 169 : Scratch(indexCtx.StrScratch), IdxCtx(indexCtx) { 170 ++IdxCtx.StrAdapterCount; 171 } 172 173 ~StrAdapter() { 174 --IdxCtx.StrAdapterCount; 175 if (IdxCtx.StrAdapterCount == 0) 176 Scratch.clear(); 177 } 178 179 const char *toCStr(StringRef Str); 180 181 unsigned getCurSize() const { return Scratch.size(); } 182 183 const char *getCStr(unsigned CharIndex) { 184 Scratch.push_back('\0'); 185 return Scratch.data() + CharIndex; 186 } 187 188 SmallVectorImpl<char> &getBuffer() { return Scratch; } 189 }; 190 191 struct ObjCProtocolListInfo { 192 SmallVector<CXIdxObjCProtocolRefInfo, 4> ProtInfos; 193 SmallVector<CXIdxEntityInfo, 4> ProtEntities; 194 SmallVector<CXIdxObjCProtocolRefInfo *, 4> Prots; 195 196 CXIdxObjCProtocolRefListInfo getListInfo() { 197 CXIdxObjCProtocolRefListInfo Info = { Prots.data(), 198 (unsigned)Prots.size() }; 199 return Info; 200 } 201 202 ObjCProtocolListInfo(const ObjCProtocolList &ProtList, 203 IndexingContext &IdxCtx, 204 IndexingContext::StrAdapter &SA); 205 }; 206 207public: 208 IndexingContext(CXClientData clientData, IndexerCallbacks &indexCallbacks, 209 unsigned indexOptions, CXTranslationUnit cxTU) 210 : Ctx(0), ClientData(clientData), CB(indexCallbacks), 211 IndexOptions(indexOptions), CXTU(cxTU), StrAdapterCount(0) { } 212 213 ASTContext &getASTContext() const { return *Ctx; } 214 215 void setASTContext(ASTContext &ctx); 216 217 bool onlyOneRefPerFile() const { 218 return IndexOptions & CXIndexOpt_OneRefPerFile; 219 } 220 221 void enteredMainFile(const FileEntry *File); 222 223 void ppIncludedFile(SourceLocation hashLoc, 224 StringRef filename, const FileEntry *File, 225 bool isImport, bool isAngled); 226 227 void startedTranslationUnit(); 228 229 void indexDecl(const Decl *D); 230 231 void indexTagDecl(const TagDecl *D); 232 233 void indexTypeSourceInfo(TypeSourceInfo *TInfo, const NamedDecl *Parent, 234 const DeclContext *DC = 0); 235 236 void indexTypeLoc(TypeLoc TL, const NamedDecl *Parent, 237 const DeclContext *DC); 238 239 void indexDeclContext(const DeclContext *DC); 240 241 void indexBody(const Stmt *S, const DeclContext *DC); 242 243 void handleDiagnostic(const StoredDiagnostic &StoredDiag); 244 void handleDiagnostic(CXDiagnostic CXDiag); 245 246 void handleFunction(const FunctionDecl *FD); 247 248 void handleVar(const VarDecl *D); 249 250 void handleField(const FieldDecl *D); 251 252 void handleEnumerator(const EnumConstantDecl *D); 253 254 void handleTagDecl(const TagDecl *D); 255 256 void handleTypedef(const TypedefDecl *D); 257 258 void handleObjCClass(const ObjCClassDecl *D); 259 void handleObjCInterface(const ObjCInterfaceDecl *D); 260 void handleObjCImplementation(const ObjCImplementationDecl *D); 261 262 void handleObjCForwardProtocol(const ObjCProtocolDecl *D, 263 SourceLocation Loc, 264 bool isRedeclaration); 265 266 void handleObjCProtocol(const ObjCProtocolDecl *D); 267 268 void handleObjCCategory(const ObjCCategoryDecl *D); 269 void handleObjCCategoryImpl(const ObjCCategoryImplDecl *D); 270 271 void handleObjCMethod(const ObjCMethodDecl *D); 272 273 void handleObjCProperty(const ObjCPropertyDecl *D); 274 275 void handleReference(const NamedDecl *D, SourceLocation Loc, 276 const NamedDecl *Parent, 277 const DeclContext *DC, 278 const Expr *E = 0, 279 CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct); 280 281 bool isNotFromSourceFile(SourceLocation Loc) const; 282 283 void indexTopLevelDecl(Decl *D); 284 void indexTUDeclsInObjCContainer(); 285 void indexDeclGroupRef(DeclGroupRef DG); 286 287 void addTUDeclInObjCContainer(DeclGroupRef DG) { 288 TUDeclsInObjCContainer.push_back(DG); 289 } 290 291 void translateLoc(SourceLocation Loc, CXIdxClientFile *indexFile, CXFile *file, 292 unsigned *line, unsigned *column, unsigned *offset); 293 294private: 295 void handleDecl(const NamedDecl *D, 296 SourceLocation Loc, CXCursor Cursor, 297 DeclInfo &DInfo); 298 299 void handleObjCContainer(const ObjCContainerDecl *D, 300 SourceLocation Loc, CXCursor Cursor, 301 ObjCContainerDeclInfo &ContDInfo); 302 303 void addContainerInMap(const DeclContext *DC, CXIdxClientContainer container); 304 305 const NamedDecl *getEntityDecl(const NamedDecl *D) const; 306 307 CXIdxClientContainer getIndexContainer(const NamedDecl *D) const { 308 return getIndexContainerForDC(D->getDeclContext()); 309 } 310 311 const DeclContext *getScopedContext(const DeclContext *DC) const; 312 CXIdxClientContainer getIndexContainerForDC(const DeclContext *DC) const; 313 314 CXIdxClientFile getIndexFile(const FileEntry *File); 315 316 CXIdxLoc getIndexLoc(SourceLocation Loc) const; 317 318 void getEntityInfo(const NamedDecl *D, 319 CXIdxEntityInfo &EntityInfo, 320 StrAdapter &SA); 321 322 CXCursor getCursor(const NamedDecl *D) { 323 return cxcursor::MakeCXCursor(const_cast<NamedDecl*>(D), CXTU); 324 } 325 326 CXCursor getRefCursor(const NamedDecl *D, SourceLocation Loc); 327}; 328 329}} // end clang::cxindex 330 331namespace llvm { 332 /// Define DenseMapInfo so that FileID's can be used as keys in DenseMap and 333 /// DenseSets. 334 template <> 335 struct DenseMapInfo<clang::cxindex::RefFileOccurence> { 336 static inline clang::cxindex::RefFileOccurence getEmptyKey() { 337 return clang::cxindex::RefFileOccurence(0, 0); 338 } 339 340 static inline clang::cxindex::RefFileOccurence getTombstoneKey() { 341 return clang::cxindex::RefFileOccurence((const clang::FileEntry *)~0, 342 (const clang::Decl *)~0); 343 } 344 345 static unsigned getHashValue(clang::cxindex::RefFileOccurence S) { 346 llvm::FoldingSetNodeID ID; 347 ID.AddPointer(S.File); 348 ID.AddPointer(S.Dcl); 349 return ID.ComputeHash(); 350 } 351 352 static bool isEqual(clang::cxindex::RefFileOccurence LHS, 353 clang::cxindex::RefFileOccurence RHS) { 354 return LHS.File == RHS.File && LHS.Dcl == RHS.Dcl; 355 } 356 }; 357} 358