blob: 3d3277210e45150a096bd043e4b92184ce5d4204 [file] [log] [blame]
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +00001//===- 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#include "CXTranslationUnit.h"
12#include "CIndexDiagnostic.h"
13
14#include "clang/Frontend/ASTUnit.h"
15#include "clang/AST/DeclObjC.h"
16
17using namespace clang;
18using namespace cxindex;
19using namespace cxcursor;
20
21const char *IndexingContext::StrAdapter::toCStr(StringRef Str) {
22 if (Str.empty())
23 return "";
24 if (Str.data()[Str.size()] == '\0')
25 return Str.data();
26 Scratch += Str;
27 Scratch.push_back('\0');
28 return Scratch.data() + (Scratch.size() - Str.size() - 1);
29}
30
31void IndexingContext::setASTContext(ASTContext &ctx) {
32 Ctx = &ctx;
33 static_cast<ASTUnit*>(CXTU->TUData)->setASTContext(&ctx);
34}
35
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +000036void IndexingContext::enteredMainFile(const FileEntry *File) {
37 if (File && CB.enteredMainFile) {
38 CXIdxClientFile idxFile = CB.enteredMainFile(ClientData, (CXFile)File, 0);
39 FileMap[File] = idxFile;
40 }
41}
42
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +000043void IndexingContext::ppIncludedFile(SourceLocation hashLoc,
44 StringRef filename,
45 const FileEntry *File,
46 bool isImport, bool isAngled) {
47 if (!CB.ppIncludedFile)
48 return;
49
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +000050 StrAdapter SA(*this);
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +000051 CXIdxIncludedFileInfo Info = { getIndexLoc(hashLoc),
52 SA.toCStr(filename),
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +000053 (CXFile)File,
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +000054 isImport, isAngled };
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +000055 CXIdxClientFile idxFile = CB.ppIncludedFile(ClientData, &Info);
56 FileMap[File] = idxFile;
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +000057}
58
59void IndexingContext::ppMacroDefined(SourceLocation Loc, StringRef Name,
60 SourceLocation DefBegin, unsigned Length,
61 const void *OpaqueMacro) {
62 if (!CB.ppMacroDefined)
63 return;
64
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +000065 StrAdapter SA(*this);
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +000066 CXIdxMacroInfo MacroInfo = { getIndexLoc(Loc), SA.toCStr(Name) };
67 CXIdxMacroDefinedInfo Info = { &MacroInfo,
68 getIndexLoc(DefBegin), Length };
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +000069 CXIdxClientMacro idxMacro = CB.ppMacroDefined(ClientData, &Info);
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +000070 MacroMap[OpaqueMacro] = idxMacro;
71}
72
73void IndexingContext::ppMacroUndefined(SourceLocation Loc, StringRef Name,
74 const void *OpaqueMacro) {
75 if (!CB.ppMacroUndefined)
76 return;
77
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +000078 StrAdapter SA(*this);
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +000079 CXIdxMacroUndefinedInfo Info = { getIndexLoc(Loc),
80 SA.toCStr(Name), 0 };
81 CB.ppMacroUndefined(ClientData, &Info);
82}
83
84void IndexingContext::ppMacroExpanded(SourceLocation Loc, StringRef Name,
85 const void *OpaqueMacro) {
86 if (!CB.ppMacroExpanded)
87 return;
88
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +000089 StrAdapter SA(*this);
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +000090 CXIdxMacroExpandedInfo Info = { getIndexLoc(Loc),
91 SA.toCStr(Name), 0 };
92 CB.ppMacroExpanded(ClientData, &Info);
93}
94
95void IndexingContext::invokeStartedTranslationUnit() {
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +000096 CXIdxClientContainer idxCont = 0;
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +000097 if (CB.startedTranslationUnit)
98 idxCont = CB.startedTranslationUnit(ClientData, 0);
99 addContainerInMap(Ctx->getTranslationUnitDecl(), idxCont);
100}
101
102void IndexingContext::invokeFinishedTranslationUnit() {
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000103 endContainer(Ctx->getTranslationUnitDecl());
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000104}
105
106void IndexingContext::handleDiagnostic(const StoredDiagnostic &StoredDiag) {
107 if (!CB.diagnostic)
108 return;
109
110 CXStoredDiagnostic CXDiag(StoredDiag, Ctx->getLangOptions());
111 CB.diagnostic(ClientData, &CXDiag, 0);
112}
113
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000114void IndexingContext::handleDecl(const NamedDecl *D,
115 SourceLocation Loc, CXCursor Cursor,
116 bool isRedeclaration, bool isDefinition,
117 DeclInfo &DInfo) {
118 if (!CB.indexDeclaration)
119 return;
120
121 StrAdapter SA(*this);
122 getEntityInfo(D, DInfo.CXEntInfo, SA);
123 DInfo.entityInfo = &DInfo.CXEntInfo;
124 DInfo.cursor = Cursor;
125 DInfo.loc = getIndexLoc(Loc);
126 DInfo.container = getIndexContainer(D);
127 DInfo.isRedeclaration = isRedeclaration;
128 DInfo.isDefinition = isDefinition;
129
130 CXIdxClientEntity
131 clientEnt = CB.indexDeclaration(ClientData, &DInfo);
132
133 if (!isRedeclaration)
134 addEntityInMap(D, clientEnt);
135}
136
137void IndexingContext::handleObjCContainer(const ObjCContainerDecl *D,
138 SourceLocation Loc, CXCursor Cursor,
139 bool isForwardRef,
140 bool isRedeclaration,
141 bool isImplementation,
142 ObjCContainerDeclInfo &ContDInfo) {
143 ContDInfo.CXObjCContDeclInfo.declInfo = &ContDInfo;
144 if (isForwardRef)
145 ContDInfo.CXObjCContDeclInfo.kind = CXIdxObjCContainer_ForwardRef;
146 else if (isImplementation)
147 ContDInfo.CXObjCContDeclInfo.kind = CXIdxObjCContainer_Implementation;
148 else
149 ContDInfo.CXObjCContDeclInfo.kind = CXIdxObjCContainer_Interface;
150
151 handleDecl(D, Loc, Cursor,
152 isRedeclaration, /*isDefinition=*/!isForwardRef, ContDInfo);
153}
154
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000155void IndexingContext::handleFunction(const FunctionDecl *D) {
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000156 DeclInfo DInfo;
157 handleDecl(D, D->getLocation(), getCursor(D),
158 !D->isFirstDeclaration(), D->isThisDeclarationADefinition(),
159 DInfo);
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000160}
161
162void IndexingContext::handleVar(const VarDecl *D) {
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000163 DeclInfo DInfo;
164 handleDecl(D, D->getLocation(), getCursor(D),
165 !D->isFirstDeclaration(), D->isThisDeclarationADefinition(),
166 DInfo);
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000167}
168
169void IndexingContext::handleField(const FieldDecl *D) {
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000170 DeclInfo DInfo;
171 handleDecl(D, D->getLocation(), getCursor(D),
172 /*isRedeclaration=*/false, /*isDefinition=*/false, DInfo);
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000173}
174
175void IndexingContext::handleEnumerator(const EnumConstantDecl *D) {
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000176 DeclInfo DInfo;
177 handleDecl(D, D->getLocation(), getCursor(D),
178 /*isRedeclaration=*/false, /*isDefinition=*/true, DInfo);
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000179}
180
181void IndexingContext::handleTagDecl(const TagDecl *D) {
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000182 TagDeclInfo TagDInfo;
183 TagDInfo.CXTagDeclInfo.declInfo = &TagDInfo;
184 TagDInfo.CXTagDeclInfo.isAnonymous = D->getIdentifier() == 0;
185 handleDecl(D, D->getLocation(), getCursor(D),
186 !D->isFirstDeclaration(), D->isThisDeclarationADefinition(),
187 TagDInfo);
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000188}
189
190void IndexingContext::handleTypedef(const TypedefDecl *D) {
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000191 DeclInfo DInfo;
192 handleDecl(D, D->getLocation(), getCursor(D),
193 !D->isFirstDeclaration(), /*isDefinition=*/true, DInfo);
194}
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000195
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000196void IndexingContext::handleObjCClass(const ObjCClassDecl *D) {
197 ObjCContainerDeclInfo ContDInfo;
198 const ObjCClassDecl::ObjCClassRef *Ref = D->getForwardDecl();
199 ObjCInterfaceDecl *IFaceD = Ref->getInterface();
200 SourceLocation Loc = Ref->getLocation();
201 bool isRedeclaration = IFaceD->getLocation() != Loc;
202 handleObjCContainer(IFaceD, Loc, MakeCursorObjCClassRef(IFaceD, Loc, CXTU),
203 /*isForwardRef=*/true, isRedeclaration,
204 /*isImplementation=*/false, ContDInfo);
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000205}
206
207void IndexingContext::handleObjCInterface(const ObjCInterfaceDecl *D) {
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000208 ObjCContainerDeclInfo ContDInfo;
209 handleObjCContainer(D, D->getLocation(), getCursor(D),
210 /*isForwardRef=*/false,
211 /*isRedeclaration=*/D->isInitiallyForwardDecl(),
212 /*isImplementation=*/false, ContDInfo);
213}
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000214
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000215void IndexingContext::handleObjCImplementation(
216 const ObjCImplementationDecl *D) {
217 ObjCContainerDeclInfo ContDInfo;
218 const ObjCInterfaceDecl *Class = D->getClassInterface();
219 handleObjCContainer(Class, D->getLocation(), getCursor(D),
220 /*isForwardRef=*/false,
221 /*isRedeclaration=*/!Class->isImplicitInterfaceDecl(),
222 /*isImplementation=*/true, ContDInfo);
223}
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000224
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000225void IndexingContext::handleObjCForwardProtocol(const ObjCProtocolDecl *D,
226 SourceLocation Loc,
227 bool isRedeclaration) {
228 ObjCContainerDeclInfo ContDInfo;
229 handleObjCContainer(D, Loc, MakeCursorObjCProtocolRef(D, Loc, CXTU),
230 /*isForwardRef=*/true,
231 isRedeclaration,
232 /*isImplementation=*/false, ContDInfo);
233}
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000234
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000235void IndexingContext::handleObjCProtocol(const ObjCProtocolDecl *D) {
236 ObjCContainerDeclInfo ContDInfo;
237 handleObjCContainer(D, D->getLocation(), getCursor(D),
238 /*isForwardRef=*/false,
239 /*isRedeclaration=*/D->isInitiallyForwardDecl(),
240 /*isImplementation=*/false, ContDInfo);
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000241}
242
243void IndexingContext::defineObjCInterface(const ObjCInterfaceDecl *D) {
244 if (!CB.defineObjCClass)
245 return;
246
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000247 StrAdapter SA(*this);
248 CXIdxObjCBaseClassInfo BaseClass;
249 CXIdxEntityInfo BaseEntity;
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000250 if (D->getSuperClass()) {
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000251 getEntityInfo(D->getSuperClass(), BaseEntity, SA);
252 BaseClass.objcClass = &BaseEntity;
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000253 BaseClass.loc = getIndexLoc(D->getSuperClassLoc());
254 }
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000255
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000256 SmallVector<CXIdxObjCProtocolRefInfo, 4> ProtInfos;
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000257 SmallVector<CXIdxEntityInfo, 4> ProtEntities;
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000258 ObjCInterfaceDecl::protocol_loc_iterator LI = D->protocol_loc_begin();
259 for (ObjCInterfaceDecl::protocol_iterator
260 I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I, ++LI) {
261 SourceLocation Loc = *LI;
262 ObjCProtocolDecl *PD = *I;
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000263 ProtEntities.push_back(CXIdxEntityInfo());
264 getEntityInfo(PD, ProtEntities.back(), SA);
265 CXIdxObjCProtocolRefInfo ProtInfo = { 0, getIndexLoc(Loc) };
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000266 ProtInfos.push_back(ProtInfo);
267 }
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000268
269 for (unsigned i = 0, e = ProtInfos.size(); i != e; ++i)
270 ProtInfos[i].protocol = &ProtEntities[i];
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000271
272 SmallVector<CXIdxObjCProtocolRefInfo *, 4> Prots;
273 for (unsigned i = 0, e = Prots.size(); i != e; ++i)
274 Prots.push_back(&ProtInfos[i]);
275
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000276 CXIdxEntityInfo ClassEntity;
277 getEntityInfo(D, ClassEntity, SA);
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000278 CXIdxObjCClassDefineInfo Info = { getCursor(D),
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000279 &ClassEntity,
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000280 getIndexContainerForDC(D),
281 D->getSuperClass() ? &BaseClass : 0,
282 Prots.data(),
Matt Beaumont-Gaycb6e5c12011-10-17 22:19:09 +0000283 static_cast<unsigned>(Prots.size()) };
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000284 CB.defineObjCClass(ClientData, &Info);
285}
286
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000287void IndexingContext::handleObjCCategory(const ObjCCategoryDecl *D) {
288 ObjCCategoryDeclInfo CatDInfo;
289 CXIdxEntityInfo ClassEntity;
290 StrAdapter SA(*this);
291 getEntityInfo(D->getClassInterface(), ClassEntity, SA);
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000292
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000293 CatDInfo.CXObjCCatDeclInfo.containerInfo = &CatDInfo.CXObjCContDeclInfo;
294 CatDInfo.CXObjCCatDeclInfo.objcClass = &ClassEntity;
295 handleObjCContainer(D, D->getLocation(), getCursor(D),
296 /*isForwardRef=*/false,
297 /*isRedeclaration=*/false,
298 /*isImplementation=*/false, CatDInfo);
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000299}
300
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000301void IndexingContext::handleObjCCategoryImpl(const ObjCCategoryImplDecl *D) {
302 const ObjCCategoryDecl *CatD = D->getCategoryDecl();
303 ObjCCategoryDeclInfo CatDInfo;
304 CXIdxEntityInfo ClassEntity;
305 StrAdapter SA(*this);
306 getEntityInfo(CatD->getClassInterface(), ClassEntity, SA);
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000307
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000308 CatDInfo.CXObjCCatDeclInfo.containerInfo = &CatDInfo.CXObjCContDeclInfo;
309 CatDInfo.CXObjCCatDeclInfo.objcClass = &ClassEntity;
310 handleObjCContainer(CatD, D->getLocation(), getCursor(D),
311 /*isForwardRef=*/false,
312 /*isRedeclaration=*/true,
313 /*isImplementation=*/true, CatDInfo);
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000314}
315
316void IndexingContext::handleObjCMethod(const ObjCMethodDecl *D) {
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000317 DeclInfo DInfo;
318 handleDecl(D, D->getLocation(), getCursor(D),
319 !D->isCanonicalDecl(), D->isThisDeclarationADefinition(),
320 DInfo);
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000321}
322
323void IndexingContext::handleObjCProperty(const ObjCPropertyDecl *D) {
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000324 DeclInfo DInfo;
325 handleDecl(D, D->getLocation(), getCursor(D),
326 /*isRedeclaration=*/false, /*isDefinition=*/false,
327 DInfo);
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000328}
329
330void IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
331 const NamedDecl *Parent,
332 const DeclContext *DC,
Argyrios Kyrtzidis0c7735e52011-10-18 15:50:50 +0000333 const Expr *E,
334 CXIdxEntityRefKind Kind) {
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000335 if (Loc.isInvalid())
336 return;
337 if (!CB.indexEntityReference)
338 return;
339 if (isNotFromSourceFile(D->getLocation()))
340 return;
341
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000342 StrAdapter SA(*this);
Benjamin Kramerf1b4e002011-10-28 13:37:11 +0000343 CXCursor Cursor = E ? MakeCXCursor(const_cast<Expr*>(E),
344 const_cast<Decl*>(cast<Decl>(DC)), CXTU)
345 : getRefCursor(D, Loc);
346
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000347 CXIdxEntityInfo RefEntity, ParentEntity;
348 getEntityInfo(D, RefEntity, SA);
349 getEntityInfo(Parent, ParentEntity, SA);
Benjamin Kramerf1b4e002011-10-28 13:37:11 +0000350 CXIdxEntityRefInfo Info = { Cursor,
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000351 getIndexLoc(Loc),
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000352 &RefEntity,
353 &ParentEntity,
Argyrios Kyrtzidis0c7735e52011-10-18 15:50:50 +0000354 getIndexContainerForDC(DC),
355 Kind };
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000356 CB.indexEntityReference(ClientData, &Info);
357}
358
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000359void IndexingContext::startContainer(const NamedDecl *D, bool isStmtBody,
360 const DeclContext *DC) {
361 if (!CB.startedContainer)
362 return;
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000363
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000364 if (!DC)
365 DC = cast<DeclContext>(D);
366
367 StrAdapter SA(*this);
368 CXIdxEntityInfo Entity;
369 getEntityInfo(D, Entity, SA);
370 CXIdxContainerInfo Info;
371 Info.entity = &Entity;
372 Info.cursor = getCursor(D);
373 Info.loc = getIndexLoc(D->getLocation());
374 Info.isObjCImpl = isa<ObjCImplDecl>(D);
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000375
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000376 CXIdxClientContainer clientCont = CB.startedContainer(ClientData, &Info);
377 addContainerInMap(DC, clientCont);
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000378}
379
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000380void IndexingContext::endContainer(const DeclContext *DC) {
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000381 if (CB.endedContainer) {
382 CXIdxEndContainerInfo Info = { getIndexContainerForDC(DC),
383 getIndexLoc(cast<Decl>(DC)->getLocEnd()) };
384 CB.endedContainer(ClientData, &Info);
385 }
386}
387
388bool IndexingContext::isNotFromSourceFile(SourceLocation Loc) const {
389 if (Loc.isInvalid())
390 return true;
391 SourceManager &SM = Ctx->getSourceManager();
392 SourceLocation FileLoc = SM.getFileLoc(Loc);
393 FileID FID = SM.getFileID(FileLoc);
394 return SM.getFileEntryForID(FID) == 0;
395}
396
397void IndexingContext::addContainerInMap(const DeclContext *DC,
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000398 CXIdxClientContainer container) {
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000399 assert(getScopedContext(DC) == DC);
400 ContainerMapTy::iterator I = ContainerMap.find(DC);
401 if (I == ContainerMap.end()) {
402 if (container)
403 ContainerMap[DC] = container;
404 return;
405 }
406 // Allow changing the container of a previously seen DeclContext so we
407 // can handle invalid user code, like a function re-definition.
408 if (container)
409 I->second = container;
410 else
411 ContainerMap.erase(I);
412}
413
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000414void IndexingContext::addEntityInMap(const NamedDecl *D,
415 CXIdxClientEntity entity) {
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000416 assert(getEntityDecl(D) == D &&
417 "Tried to add a non-entity (canonical) decl");
418 assert(EntityMap.find(D) == EntityMap.end());
419 if (entity || D->isFromASTFile())
420 EntityMap[D] = entity;
421}
422
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000423CXIdxClientEntity IndexingContext::getClientEntity(const NamedDecl *D) {
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000424 if (!D)
425 return 0;
426 D = getEntityDecl(D);
427 EntityMapTy::const_iterator I = EntityMap.find(D);
428 if (I != EntityMap.end())
429 return I->second;
430
431 if (!D->isFromASTFile()) {
432 //assert(0 && "Entity not in map");
433 return 0;
434 }
435
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000436 StrAdapter SA(*this);
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000437
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000438 CXIdxClientEntity idxEntity = 0;
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000439 if (CB.importedEntity) {
440 CXIdxEntityInfo EntityInfo;
441 getEntityInfo(D, EntityInfo, SA);
442 CXIdxImportedEntityInfo Info = { &EntityInfo,
443 getCursor(D),
444 getIndexLoc(D->getLocation()),
445 /*CXIdxASTFile*/0 };
446 idxEntity = CB.importedEntity(ClientData, &Info);
447 }
448 addEntityInMap(D, idxEntity);
449 return idxEntity;
450}
451
452const NamedDecl *IndexingContext::getEntityDecl(const NamedDecl *D) const {
453 assert(D);
454 D = cast<NamedDecl>(D->getCanonicalDecl());
455
456 if (const ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(D)) {
457 if (Cat->IsClassExtension())
458 return getEntityDecl(Cat->getClassInterface());
459
460 } else if (const ObjCImplementationDecl *
461 ImplD = dyn_cast<ObjCImplementationDecl>(D)) {
462 return getEntityDecl(ImplD->getClassInterface());
463
464 } else if (const ObjCCategoryImplDecl *
465 CatImplD = dyn_cast<ObjCCategoryImplDecl>(D)) {
466 return getEntityDecl(CatImplD->getCategoryDecl());
467 }
468
469 return D;
470}
471
472const DeclContext *
473IndexingContext::getScopedContext(const DeclContext *DC) const {
474 // Local contexts are ignored for indexing.
475 const DeclContext *FuncCtx = cast<Decl>(DC)->getParentFunctionOrMethod();
476 if (FuncCtx)
477 return FuncCtx;
478
479 // We consider enums always scoped for indexing.
480 if (isa<TagDecl>(DC))
481 return DC;
482
483 if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) {
484 if (NS->isAnonymousNamespace())
485 return getScopedContext(NS->getParent());
486 return NS;
487 }
488
489 return DC->getRedeclContext();
490}
491
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000492CXIdxClientContainer
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000493IndexingContext::getIndexContainerForDC(const DeclContext *DC) const {
494 DC = getScopedContext(DC);
495 ContainerMapTy::const_iterator I = ContainerMap.find(DC);
496// assert(I != ContainerMap.end() &&
497// "Failed to include a scoped context in the container map");
498 return I->second;
499}
500
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000501CXIdxClientFile IndexingContext::getIndexFile(const FileEntry *File) {
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000502 if (!File)
503 return 0;
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000504
505 FileMapTy::iterator FI = FileMap.find(File);
506 if (FI != FileMap.end())
507 return FI->second;
508
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000509 return 0;
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000510}
511
512CXIdxLoc IndexingContext::getIndexLoc(SourceLocation Loc) const {
513 CXIdxLoc idxLoc = { {0, 0}, 0 };
514 if (Loc.isInvalid())
515 return idxLoc;
516
517 idxLoc.ptr_data[0] = (void*)this;
518 idxLoc.int_data = Loc.getRawEncoding();
519 return idxLoc;
520}
521
522void IndexingContext::translateLoc(SourceLocation Loc,
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000523 CXIdxClientFile *indexFile, CXFile *file,
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000524 unsigned *line, unsigned *column,
525 unsigned *offset) {
526 if (Loc.isInvalid())
527 return;
528
529 SourceManager &SM = Ctx->getSourceManager();
530 Loc = SM.getFileLoc(Loc);
531
532 std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
533 FileID FID = LocInfo.first;
534 unsigned FileOffset = LocInfo.second;
535
536 if (FID.isInvalid())
537 return;
538
539 const FileEntry *FE = SM.getFileEntryForID(FID);
540 if (indexFile)
541 *indexFile = getIndexFile(FE);
542 if (file)
543 *file = (void *)FE;
544 if (line)
545 *line = SM.getLineNumber(FID, FileOffset);
546 if (column)
547 *column = SM.getColumnNumber(FID, FileOffset);
548 if (offset)
549 *offset = FileOffset;
550}
551
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000552void IndexingContext::getEntityInfo(const NamedDecl *D,
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000553 CXIdxEntityInfo &EntityInfo,
554 StrAdapter &SA) {
555 D = getEntityDecl(D);
556 EntityInfo.kind = CXIdxEntity_Unexposed;
557 EntityInfo.clientEntity = getClientEntity(D);
558
559 if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
560 switch (TD->getTagKind()) {
561 case TTK_Struct:
562 EntityInfo.kind = CXIdxEntity_Struct; break;
563 case TTK_Union:
564 EntityInfo.kind = CXIdxEntity_Union; break;
565 case TTK_Class:
566 EntityInfo.kind = CXIdxEntity_CXXClass; break;
567 case TTK_Enum:
568 EntityInfo.kind = CXIdxEntity_Enum; break;
569 }
570
571 } else {
572 switch (D->getKind()) {
573 case Decl::Typedef:
574 EntityInfo.kind = CXIdxEntity_Typedef; break;
575 case Decl::Function:
576 EntityInfo.kind = CXIdxEntity_Function; break;
577 case Decl::Var:
578 EntityInfo.kind = CXIdxEntity_Variable; break;
579 case Decl::Field:
580 EntityInfo.kind = CXIdxEntity_Field; break;
581 case Decl::EnumConstant:
582 EntityInfo.kind = CXIdxEntity_EnumConstant; break;
583 case Decl::ObjCInterface:
584 EntityInfo.kind = CXIdxEntity_ObjCClass; break;
585 case Decl::ObjCProtocol:
586 EntityInfo.kind = CXIdxEntity_ObjCProtocol; break;
587 case Decl::ObjCCategory:
588 EntityInfo.kind = CXIdxEntity_ObjCCategory; break;
589 case Decl::ObjCMethod:
590 EntityInfo.kind = CXIdxEntity_ObjCMethod; break;
591 case Decl::ObjCProperty:
592 EntityInfo.kind = CXIdxEntity_ObjCProperty; break;
593 case Decl::ObjCIvar:
594 EntityInfo.kind = CXIdxEntity_ObjCIvar; break;
595 default:
596 break;
597 }
598 }
599
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000600 if (IdentifierInfo *II = D->getIdentifier()) {
601 EntityInfo.name = SA.toCStr(II->getName());
602
603 } else if (isa<RecordDecl>(D) || isa<NamespaceDecl>(D)) {
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000604 EntityInfo.name = 0; // anonymous record/namespace.
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000605
606 } else {
607 unsigned Begin = SA.getCurSize();
608 {
609 llvm::raw_svector_ostream OS(SA.getBuffer());
610 D->printName(OS);
611 }
612 EntityInfo.name = SA.getCStr(Begin);
613 }
614
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000615 {
616 unsigned Begin = SA.getCurSize();
617 bool Ignore = getDeclCursorUSR(D, SA.getBuffer());
618 if (Ignore) {
619 EntityInfo.USR = "";
620 } else {
621 EntityInfo.USR = SA.getCStr(Begin);
622 }
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000623 }
624}
625
626CXCursor IndexingContext::getRefCursor(const NamedDecl *D, SourceLocation Loc) {
627 if (const TypeDecl *TD = dyn_cast<TypeDecl>(D))
628 return MakeCursorTypeRef(TD, Loc, CXTU);
629 if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D))
630 return MakeCursorObjCClassRef(ID, Loc, CXTU);
631 if (const ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D))
632 return MakeCursorObjCProtocolRef(PD, Loc, CXTU);
633
634 //assert(0 && "not yet");
635 return clang_getNullCursor();
636}