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