1//===- CIndexHigh.cpp - 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 "IndexingContext.h"
11
12#include "clang/AST/DeclVisitor.h"
13
14using namespace clang;
15using namespace cxindex;
16
17namespace {
18
19class IndexingDeclVisitor : public DeclVisitor<IndexingDeclVisitor, bool> {
20  IndexingContext &IndexCtx;
21
22public:
23  explicit IndexingDeclVisitor(IndexingContext &indexCtx)
24    : IndexCtx(indexCtx) { }
25
26  bool VisitFunctionDecl(FunctionDecl *D) {
27    IndexCtx.handleFunction(D);
28    IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
29    if (D->isThisDeclarationADefinition()) {
30      const Stmt *Body = D->getBody();
31      if (Body) {
32        IndexCtx.invokeStartedStatementBody(D, D);
33        IndexCtx.indexBody(Body, D);
34        IndexCtx.invokeEndedContainer(D);
35      }
36    }
37    return true;
38  }
39
40  bool VisitVarDecl(VarDecl *D) {
41    IndexCtx.handleVar(D);
42    IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
43    return true;
44  }
45
46  bool VisitFieldDecl(FieldDecl *D) {
47    IndexCtx.handleField(D);
48    IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
49    return true;
50  }
51
52  bool VisitEnumConstantDecl(EnumConstantDecl *D) {
53    IndexCtx.handleEnumerator(D);
54    return true;
55  }
56
57  bool VisitTypedefDecl(TypedefDecl *D) {
58    IndexCtx.handleTypedef(D);
59    IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
60    return true;
61  }
62
63  bool VisitTagDecl(TagDecl *D) {
64    // Non-free standing tags are handled in indexTypeSourceInfo.
65    if (D->isFreeStanding())
66      IndexCtx.indexTagDecl(D);
67    return true;
68  }
69
70  bool VisitObjCClassDecl(ObjCClassDecl *D) {
71    ObjCClassDecl::ObjCClassRef *Ref = D->getForwardDecl();
72    if (Ref->getInterface()->getLocation() == Ref->getLocation()) {
73      IndexCtx.handleObjCInterface(Ref->getInterface());
74    } else {
75      IndexCtx.handleReference(Ref->getInterface(),
76                               Ref->getLocation(),
77                               0,
78                               Ref->getInterface()->getDeclContext());
79    }
80    return true;
81  }
82
83  bool VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) {
84    ObjCForwardProtocolDecl::protocol_loc_iterator LI = D->protocol_loc_begin();
85    for (ObjCForwardProtocolDecl::protocol_iterator
86           I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I, ++LI) {
87      SourceLocation Loc = *LI;
88      ObjCProtocolDecl *PD = *I;
89
90      if (PD->getLocation() == Loc) {
91        IndexCtx.handleObjCProtocol(PD);
92      } else {
93        IndexCtx.handleReference(PD, Loc, 0, PD->getDeclContext());
94      }
95    }
96    return true;
97  }
98
99  bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
100    // Only definitions are handled here.
101    if (D->isForwardDecl())
102      return true;
103
104    if (!D->isInitiallyForwardDecl())
105      IndexCtx.handleObjCInterface(D);
106
107    IndexCtx.indexTUDeclsInObjCContainer();
108    IndexCtx.invokeStartedObjCContainer(D);
109    IndexCtx.defineObjCInterface(D);
110    IndexCtx.indexDeclContext(D);
111    IndexCtx.invokeEndedContainer(D);
112    return true;
113  }
114
115  bool VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
116    // Only definitions are handled here.
117    if (D->isForwardDecl())
118      return true;
119
120    if (!D->isInitiallyForwardDecl())
121      IndexCtx.handleObjCProtocol(D);
122
123    IndexCtx.indexTUDeclsInObjCContainer();
124    IndexCtx.invokeStartedObjCContainer(D);
125    IndexCtx.indexDeclContext(D);
126    IndexCtx.invokeEndedContainer(D);
127    return true;
128  }
129
130  bool VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
131    ObjCInterfaceDecl *Class = D->getClassInterface();
132    if (Class->isImplicitInterfaceDecl())
133      IndexCtx.handleObjCInterface(Class);
134
135    IndexCtx.indexTUDeclsInObjCContainer();
136    IndexCtx.invokeStartedObjCContainer(D);
137    IndexCtx.indexDeclContext(D);
138    IndexCtx.invokeEndedContainer(D);
139    return true;
140  }
141
142  bool VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
143    if (!D->IsClassExtension())
144      IndexCtx.handleObjCCategory(D);
145
146    IndexCtx.indexTUDeclsInObjCContainer();
147    IndexCtx.invokeStartedObjCContainer(D);
148    IndexCtx.indexDeclContext(D);
149    IndexCtx.invokeEndedContainer(D);
150    return true;
151  }
152
153  bool VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
154    IndexCtx.indexTUDeclsInObjCContainer();
155    IndexCtx.invokeStartedObjCContainer(D);
156    IndexCtx.indexDeclContext(D);
157    IndexCtx.invokeEndedContainer(D);
158    return true;
159  }
160
161  bool VisitObjCMethodDecl(ObjCMethodDecl *D) {
162    IndexCtx.handleObjCMethod(D);
163    IndexCtx.indexTypeSourceInfo(D->getResultTypeSourceInfo(), D);
164    for (ObjCMethodDecl::param_iterator
165           I = D->param_begin(), E = D->param_end(); I != E; ++I)
166      IndexCtx.indexTypeSourceInfo((*I)->getTypeSourceInfo(), D);
167
168    if (D->isThisDeclarationADefinition()) {
169      const Stmt *Body = D->getBody();
170      if (Body) {
171        IndexCtx.invokeStartedStatementBody(D, D);
172        IndexCtx.indexBody(Body, D);
173        IndexCtx.invokeEndedContainer(D);
174      }
175    }
176    return true;
177  }
178
179  bool VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
180    IndexCtx.handleObjCProperty(D);
181    IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
182    return true;
183  }
184};
185
186} // anonymous namespace
187
188void IndexingContext::indexDecl(const Decl *D) {
189  bool Handled = IndexingDeclVisitor(*this).Visit(const_cast<Decl*>(D));
190  if (!Handled && isa<DeclContext>(D))
191    indexDeclContext(cast<DeclContext>(D));
192}
193
194void IndexingContext::indexDeclContext(const DeclContext *DC) {
195  for (DeclContext::decl_iterator
196         I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) {
197    indexDecl(*I);
198  }
199}
200
201void IndexingContext::indexDeclGroupRef(DeclGroupRef DG) {
202  for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) {
203    Decl *D = *I;
204    if (isNotFromSourceFile(D->getLocation()))
205      return;
206
207    if (isa<ObjCMethodDecl>(D))
208      continue; // Wait for the objc container.
209
210    indexDecl(D);
211  }
212}
213
214void IndexingContext::indexTUDeclsInObjCContainer() {
215  for (unsigned i = 0, e = TUDeclsInObjCContainer.size(); i != e; ++i)
216    indexDeclGroupRef(TUDeclsInObjCContainer[i]);
217  TUDeclsInObjCContainer.clear();
218}
219