IndexingContext.cpp revision dd93c596cd95e1b96031ff47efe0a5095ff3d7f1
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#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
36void 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
43void IndexingContext::ppIncludedFile(SourceLocation hashLoc,
44                                     StringRef filename,
45                                     const FileEntry *File,
46                                     bool isImport, bool isAngled) {
47  if (!CB.ppIncludedFile)
48    return;
49
50  StrAdapter SA(*this);
51  CXIdxIncludedFileInfo Info = { getIndexLoc(hashLoc),
52                                 SA.toCStr(filename),
53                                 (CXFile)File,
54                                 isImport, isAngled };
55  CXIdxClientFile idxFile = CB.ppIncludedFile(ClientData, &Info);
56  FileMap[File] = idxFile;
57}
58
59void IndexingContext::ppMacroDefined(SourceLocation Loc, StringRef Name,
60                                     SourceLocation DefBegin, unsigned Length,
61                                     const void *OpaqueMacro) {
62  if (!CB.ppMacroDefined)
63    return;
64
65  StrAdapter SA(*this);
66  CXIdxMacroInfo MacroInfo =  { getIndexLoc(Loc), SA.toCStr(Name) };
67  CXIdxMacroDefinedInfo Info = { &MacroInfo,
68                                 getIndexLoc(DefBegin), Length };
69  CXIdxClientMacro idxMacro = CB.ppMacroDefined(ClientData, &Info);
70  MacroMap[OpaqueMacro] = idxMacro;
71}
72
73void IndexingContext::ppMacroUndefined(SourceLocation Loc, StringRef Name,
74                                       const void *OpaqueMacro) {
75  if (!CB.ppMacroUndefined)
76    return;
77
78  StrAdapter SA(*this);
79  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
89  StrAdapter SA(*this);
90  CXIdxMacroExpandedInfo Info = { getIndexLoc(Loc),
91                                   SA.toCStr(Name), 0 };
92  CB.ppMacroExpanded(ClientData, &Info);
93}
94
95void IndexingContext::invokeStartedTranslationUnit() {
96  CXIdxClientContainer idxCont = 0;
97  if (CB.startedTranslationUnit)
98    idxCont = CB.startedTranslationUnit(ClientData, 0);
99  addContainerInMap(Ctx->getTranslationUnitDecl(), idxCont);
100}
101
102void IndexingContext::invokeFinishedTranslationUnit() {
103  endContainer(Ctx->getTranslationUnitDecl());
104}
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
114void 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
155void IndexingContext::handleFunction(const FunctionDecl *D) {
156  DeclInfo DInfo;
157  handleDecl(D, D->getLocation(), getCursor(D),
158             !D->isFirstDeclaration(), D->isThisDeclarationADefinition(),
159             DInfo);
160}
161
162void IndexingContext::handleVar(const VarDecl *D) {
163  DeclInfo DInfo;
164  handleDecl(D, D->getLocation(), getCursor(D),
165             !D->isFirstDeclaration(), D->isThisDeclarationADefinition(),
166             DInfo);
167}
168
169void IndexingContext::handleField(const FieldDecl *D) {
170  DeclInfo DInfo;
171  handleDecl(D, D->getLocation(), getCursor(D),
172             /*isRedeclaration=*/false, /*isDefinition=*/false, DInfo);
173}
174
175void IndexingContext::handleEnumerator(const EnumConstantDecl *D) {
176  DeclInfo DInfo;
177  handleDecl(D, D->getLocation(), getCursor(D),
178             /*isRedeclaration=*/false, /*isDefinition=*/true, DInfo);
179}
180
181void IndexingContext::handleTagDecl(const TagDecl *D) {
182  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);
188}
189
190void IndexingContext::handleTypedef(const TypedefDecl *D) {
191  DeclInfo DInfo;
192  handleDecl(D, D->getLocation(), getCursor(D),
193             !D->isFirstDeclaration(), /*isDefinition=*/true, DInfo);
194}
195
196void 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);
205}
206
207void IndexingContext::handleObjCInterface(const ObjCInterfaceDecl *D) {
208  ObjCContainerDeclInfo ContDInfo;
209  handleObjCContainer(D, D->getLocation(), getCursor(D),
210                      /*isForwardRef=*/false,
211                      /*isRedeclaration=*/D->isInitiallyForwardDecl(),
212                      /*isImplementation=*/false, ContDInfo);
213}
214
215void 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}
224
225void 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}
234
235void 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);
241}
242
243void IndexingContext::defineObjCInterface(const ObjCInterfaceDecl *D) {
244  if (!CB.defineObjCClass)
245    return;
246
247  StrAdapter SA(*this);
248  CXIdxObjCBaseClassInfo BaseClass;
249  CXIdxEntityInfo BaseEntity;
250  if (D->getSuperClass()) {
251    getEntityInfo(D->getSuperClass(), BaseEntity, SA);
252    BaseClass.objcClass = &BaseEntity;
253    BaseClass.loc = getIndexLoc(D->getSuperClassLoc());
254  }
255
256  SmallVector<CXIdxObjCProtocolRefInfo, 4> ProtInfos;
257  SmallVector<CXIdxEntityInfo, 4> ProtEntities;
258  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;
263    ProtEntities.push_back(CXIdxEntityInfo());
264    getEntityInfo(PD, ProtEntities.back(), SA);
265    CXIdxObjCProtocolRefInfo ProtInfo = { 0, getIndexLoc(Loc) };
266    ProtInfos.push_back(ProtInfo);
267  }
268
269  for (unsigned i = 0, e = ProtInfos.size(); i != e; ++i)
270    ProtInfos[i].protocol = &ProtEntities[i];
271
272  SmallVector<CXIdxObjCProtocolRefInfo *, 4> Prots;
273  for (unsigned i = 0, e = Prots.size(); i != e; ++i)
274    Prots.push_back(&ProtInfos[i]);
275
276  CXIdxEntityInfo ClassEntity;
277  getEntityInfo(D, ClassEntity, SA);
278  CXIdxObjCClassDefineInfo Info = { getCursor(D),
279                                    &ClassEntity,
280                                    getIndexContainerForDC(D),
281                                    D->getSuperClass() ? &BaseClass : 0,
282                                    Prots.data(),
283                                    static_cast<unsigned>(Prots.size()) };
284  CB.defineObjCClass(ClientData, &Info);
285}
286
287void IndexingContext::handleObjCCategory(const ObjCCategoryDecl *D) {
288  ObjCCategoryDeclInfo CatDInfo;
289  CXIdxEntityInfo ClassEntity;
290  StrAdapter SA(*this);
291  getEntityInfo(D->getClassInterface(), ClassEntity, SA);
292
293  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);
299}
300
301void 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);
307
308  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);
314}
315
316void IndexingContext::handleObjCMethod(const ObjCMethodDecl *D) {
317  DeclInfo DInfo;
318  handleDecl(D, D->getLocation(), getCursor(D),
319             !D->isCanonicalDecl(), D->isThisDeclarationADefinition(),
320             DInfo);
321}
322
323void IndexingContext::handleObjCProperty(const ObjCPropertyDecl *D) {
324  DeclInfo DInfo;
325  handleDecl(D, D->getLocation(), getCursor(D),
326             /*isRedeclaration=*/false, /*isDefinition=*/false,
327             DInfo);
328}
329
330void IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
331                                      const NamedDecl *Parent,
332                                      const DeclContext *DC,
333                                      const Expr *E,
334                                      CXIdxEntityRefKind Kind) {
335  if (Loc.isInvalid())
336    return;
337  if (!CB.indexEntityReference)
338    return;
339  if (isNotFromSourceFile(D->getLocation()))
340    return;
341
342  StrAdapter SA(*this);
343  CXCursor Cursor = E ? MakeCXCursor(const_cast<Expr*>(E),
344                                     const_cast<Decl*>(cast<Decl>(DC)), CXTU)
345                      : getRefCursor(D, Loc);
346
347  CXIdxEntityInfo RefEntity, ParentEntity;
348  getEntityInfo(D, RefEntity, SA);
349  getEntityInfo(Parent, ParentEntity, SA);
350  CXIdxEntityRefInfo Info = { Cursor,
351                              getIndexLoc(Loc),
352                              &RefEntity,
353                              &ParentEntity,
354                              getIndexContainerForDC(DC),
355                              Kind };
356  CB.indexEntityReference(ClientData, &Info);
357}
358
359void IndexingContext::startContainer(const NamedDecl *D, bool isStmtBody,
360                                     const DeclContext *DC) {
361  if (!CB.startedContainer)
362    return;
363
364  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);
375
376  CXIdxClientContainer clientCont = CB.startedContainer(ClientData, &Info);
377  addContainerInMap(DC, clientCont);
378}
379
380void IndexingContext::endContainer(const DeclContext *DC) {
381  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,
398                                        CXIdxClientContainer container) {
399  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
414void IndexingContext::addEntityInMap(const NamedDecl *D,
415                                     CXIdxClientEntity entity) {
416  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
423CXIdxClientEntity IndexingContext::getClientEntity(const NamedDecl *D) {
424  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
436  StrAdapter SA(*this);
437
438  CXIdxClientEntity idxEntity = 0;
439  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
492CXIdxClientContainer
493IndexingContext::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
501CXIdxClientFile IndexingContext::getIndexFile(const FileEntry *File) {
502  if (!File)
503    return 0;
504
505  FileMapTy::iterator FI = FileMap.find(File);
506  if (FI != FileMap.end())
507    return FI->second;
508
509  return 0;
510}
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,
523                                   CXIdxClientFile *indexFile, CXFile *file,
524                                   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
552void IndexingContext::getEntityInfo(const NamedDecl *D,
553                                     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
600  if (IdentifierInfo *II = D->getIdentifier()) {
601    EntityInfo.name = SA.toCStr(II->getName());
602
603  } else if (isa<RecordDecl>(D) || isa<NamespaceDecl>(D)) {
604    EntityInfo.name = 0; // anonymous record/namespace.
605
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
615  {
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    }
623  }
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}
637