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