[libclang] Indexing API:
-For indexDeclaration, also pass the declaration attributes as an array of cursors.
-Rename CXIndexOpt_OneRefPerFile -> CXIndexOpt_SuppressRedundantRefs, and only pass
a reference if a declaration/definition does not exist in the file.
-Other fixes.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@144942 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/tools/libclang/IndexingContext.cpp b/tools/libclang/IndexingContext.cpp
index f63fd3f..d31ccdf 100644
--- a/tools/libclang/IndexingContext.cpp
+++ b/tools/libclang/IndexingContext.cpp
@@ -13,6 +13,7 @@
#include "clang/Frontend/ASTUnit.h"
#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
using namespace clang;
using namespace cxindex;
@@ -42,6 +43,55 @@
Prots.push_back(&ProtInfos[i]);
}
+IndexingContext::AttrListInfo::AttrListInfo(const Decl *D,
+ IndexingContext &IdxCtx,
+ StrAdapter &SA) {
+ for (AttrVec::const_iterator AttrI = D->attr_begin(), AttrE = D->attr_end();
+ AttrI != AttrE; ++AttrI) {
+ const Attr *A = *AttrI;
+ CXCursor C = MakeCXCursor(A, const_cast<Decl *>(D), IdxCtx.CXTU);
+ CXIdxLoc Loc = IdxCtx.getIndexLoc(A->getLocation());
+ switch (C.kind) {
+ default:
+ Attrs.push_back(AttrInfo(CXIdxAttr_Unexposed, C, Loc, A));
+ break;
+ case CXCursor_IBActionAttr:
+ Attrs.push_back(AttrInfo(CXIdxAttr_IBAction, C, Loc, A));
+ break;
+ case CXCursor_IBOutletAttr:
+ Attrs.push_back(AttrInfo(CXIdxAttr_IBOutlet, C, Loc, A));
+ break;
+ case CXCursor_IBOutletCollectionAttr:
+ IBCollAttrs.push_back(IBOutletCollectionInfo(C, Loc, A));
+ break;
+ }
+ }
+
+ for (unsigned i = 0, e = IBCollAttrs.size(); i != e; ++i) {
+ IBOutletCollectionInfo &IBInfo = IBCollAttrs[i];
+ CXAttrs.push_back(&IBInfo);
+
+ const IBOutletCollectionAttr *
+ IBAttr = cast<IBOutletCollectionAttr>(IBInfo.A);
+ IBInfo.IBCollInfo.attrInfo = &IBInfo;
+ IBInfo.IBCollInfo.classLoc = IdxCtx.getIndexLoc(IBAttr->getInterfaceLoc());
+ IBInfo.IBCollInfo.objcClass = 0;
+ IBInfo.IBCollInfo.classCursor = clang_getNullCursor();
+ QualType Ty = IBAttr->getInterface();
+ if (const ObjCInterfaceType *InterTy = Ty->getAs<ObjCInterfaceType>()) {
+ if (const ObjCInterfaceDecl *InterD = InterTy->getInterface()) {
+ IdxCtx.getEntityInfo(InterD, IBInfo.CXClassInfo, SA);
+ IBInfo.IBCollInfo.objcClass = &IBInfo.CXClassInfo;
+ IBInfo.IBCollInfo.classCursor = MakeCursorObjCClassRef(InterD,
+ IBAttr->getInterfaceLoc(), IdxCtx.CXTU);
+ }
+ }
+ }
+
+ for (unsigned i = 0, e = Attrs.size(); i != e; ++i)
+ CXAttrs.push_back(&Attrs[i]);
+}
+
const char *IndexingContext::StrAdapter::toCStr(StringRef Str) {
if (Str.empty())
return "";
@@ -57,6 +107,12 @@
static_cast<ASTUnit*>(CXTU->TUData)->setASTContext(&ctx);
}
+bool IndexingContext::shouldAbort() {
+ if (!CB.abortQuery)
+ return false;
+ return CB.abortQuery(ClientData, 0);
+}
+
void IndexingContext::enteredMainFile(const FileEntry *File) {
if (File && CB.enteredMainFile) {
CXIdxClientFile idxFile = CB.enteredMainFile(ClientData, (CXFile)File, 0);
@@ -87,90 +143,90 @@
addContainerInMap(Ctx->getTranslationUnitDecl(), idxCont);
}
-void IndexingContext::handleDiagnostic(const StoredDiagnostic &StoredDiag) {
+void IndexingContext::handleDiagnosticSet(CXDiagnostic CXDiagSet) {
if (!CB.diagnostic)
return;
- CXStoredDiagnostic CXDiag(StoredDiag, Ctx->getLangOptions());
- CB.diagnostic(ClientData, &CXDiag, 0);
+ CB.diagnostic(ClientData, CXDiagSet, 0);
}
-void IndexingContext::handleDiagnostic(CXDiagnostic CXDiag) {
- if (!CB.diagnostic)
- return;
-
- CB.diagnostic(ClientData, CXDiag, 0);
-}
-
-void IndexingContext::handleDecl(const NamedDecl *D,
+bool IndexingContext::handleDecl(const NamedDecl *D,
SourceLocation Loc, CXCursor Cursor,
DeclInfo &DInfo) {
if (!CB.indexDeclaration || !D)
- return;
+ return false;
StrAdapter SA(*this);
getEntityInfo(D, DInfo.CXEntInfo, SA);
if (!DInfo.CXEntInfo.USR || Loc.isInvalid())
- return;
+ return false;
+ markEntityOccurrenceInFile(D, Loc);
+
DInfo.entityInfo = &DInfo.CXEntInfo;
DInfo.cursor = Cursor;
DInfo.loc = getIndexLoc(Loc);
DInfo.container = getIndexContainer(D);
DInfo.isImplicit = D->isImplicit();
+ AttrListInfo AttrList(D, *this, SA);
+ DInfo.attributes = AttrList.getAttrs();
+ DInfo.numAttributes = AttrList.getNumAttrs();
+
CXIdxClientContainer clientCont = 0;
CXIdxDeclOut DeclOut = { DInfo.isContainer ? &clientCont : 0 };
CB.indexDeclaration(ClientData, &DInfo, &DeclOut);
if (DInfo.isContainer)
addContainerInMap(cast<DeclContext>(D), clientCont);
+
+ return true;
}
-void IndexingContext::handleObjCContainer(const ObjCContainerDecl *D,
+bool IndexingContext::handleObjCContainer(const ObjCContainerDecl *D,
SourceLocation Loc, CXCursor Cursor,
ObjCContainerDeclInfo &ContDInfo) {
ContDInfo.ObjCContDeclInfo.declInfo = &ContDInfo;
- handleDecl(D, Loc, Cursor, ContDInfo);
+ return handleDecl(D, Loc, Cursor, ContDInfo);
}
-void IndexingContext::handleFunction(const FunctionDecl *D) {
+bool IndexingContext::handleFunction(const FunctionDecl *D) {
DeclInfo DInfo(!D->isFirstDeclaration(), D->isThisDeclarationADefinition(),
D->isThisDeclarationADefinition());
- handleDecl(D, D->getLocation(), getCursor(D), DInfo);
+ return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
}
-void IndexingContext::handleVar(const VarDecl *D) {
+bool IndexingContext::handleVar(const VarDecl *D) {
DeclInfo DInfo(!D->isFirstDeclaration(), D->isThisDeclarationADefinition(),
/*isContainer=*/false);
- handleDecl(D, D->getLocation(), getCursor(D), DInfo);
+ return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
}
-void IndexingContext::handleField(const FieldDecl *D) {
+bool IndexingContext::handleField(const FieldDecl *D) {
DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true,
/*isContainer=*/false);
- handleDecl(D, D->getLocation(), getCursor(D), DInfo);
+ return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
}
-void IndexingContext::handleEnumerator(const EnumConstantDecl *D) {
+bool IndexingContext::handleEnumerator(const EnumConstantDecl *D) {
DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true,
/*isContainer=*/false);
- handleDecl(D, D->getLocation(), getCursor(D), DInfo);
+ return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
}
-void IndexingContext::handleTagDecl(const TagDecl *D) {
+bool IndexingContext::handleTagDecl(const TagDecl *D) {
DeclInfo DInfo(!D->isFirstDeclaration(), D->isThisDeclarationADefinition(),
D->isThisDeclarationADefinition());
- handleDecl(D, D->getLocation(), getCursor(D), DInfo);
+ return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
}
-void IndexingContext::handleTypedef(const TypedefDecl *D) {
+bool IndexingContext::handleTypedef(const TypedefDecl *D) {
DeclInfo DInfo(!D->isFirstDeclaration(), /*isDefinition=*/true,
/*isContainer=*/false);
- handleDecl(D, D->getLocation(), getCursor(D), DInfo);
+ return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
}
-void IndexingContext::handleObjCClass(const ObjCClassDecl *D) {
+bool IndexingContext::handleObjCClass(const ObjCClassDecl *D) {
const ObjCClassDecl::ObjCClassRef *Ref = D->getForwardDecl();
ObjCInterfaceDecl *IFaceD = Ref->getInterface();
SourceLocation Loc = Ref->getLocation();
@@ -178,11 +234,11 @@
ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/true, isRedeclaration,
/*isImplementation=*/false);
- handleObjCContainer(IFaceD, Loc, MakeCursorObjCClassRef(IFaceD, Loc, CXTU),
- ContDInfo);
+ return handleObjCContainer(IFaceD, Loc,
+ MakeCursorObjCClassRef(IFaceD, Loc, CXTU), ContDInfo);
}
-void IndexingContext::handleObjCInterface(const ObjCInterfaceDecl *D) {
+bool IndexingContext::handleObjCInterface(const ObjCInterfaceDecl *D) {
StrAdapter SA(*this);
CXIdxBaseClassInfo BaseClass;
@@ -204,44 +260,45 @@
InterInfo.ObjCInterDeclInfo.superInfo = D->getSuperClass() ? &BaseClass : 0;
InterInfo.ObjCInterDeclInfo.protocols = &InterInfo.ObjCProtoListInfo;
- handleObjCContainer(D, D->getLocation(), getCursor(D), InterInfo);
+ return handleObjCContainer(D, D->getLocation(), getCursor(D), InterInfo);
}
-void IndexingContext::handleObjCImplementation(
+bool IndexingContext::handleObjCImplementation(
const ObjCImplementationDecl *D) {
ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/false,
/*isRedeclaration=*/true,
/*isImplementation=*/true);
- handleObjCContainer(D, D->getLocation(), getCursor(D), ContDInfo);
+ return handleObjCContainer(D, D->getLocation(), getCursor(D), ContDInfo);
}
-void IndexingContext::handleObjCForwardProtocol(const ObjCProtocolDecl *D,
+bool IndexingContext::handleObjCForwardProtocol(const ObjCProtocolDecl *D,
SourceLocation Loc,
bool isRedeclaration) {
ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/true,
isRedeclaration,
/*isImplementation=*/false);
- handleObjCContainer(D, Loc, MakeCursorObjCProtocolRef(D, Loc, CXTU),
- ContDInfo);
+ return handleObjCContainer(D, Loc, MakeCursorObjCProtocolRef(D, Loc, CXTU),
+ ContDInfo);
}
-void IndexingContext::handleObjCProtocol(const ObjCProtocolDecl *D) {
+bool IndexingContext::handleObjCProtocol(const ObjCProtocolDecl *D) {
StrAdapter SA(*this);
ObjCProtocolListInfo ProtListInfo(D->getReferencedProtocols(), *this, SA);
ObjCProtocolDeclInfo ProtInfo(D);
ProtInfo.ObjCProtoRefListInfo = ProtListInfo.getListInfo();
- handleObjCContainer(D, D->getLocation(), getCursor(D), ProtInfo);
+ return handleObjCContainer(D, D->getLocation(), getCursor(D), ProtInfo);
}
-void IndexingContext::handleObjCCategory(const ObjCCategoryDecl *D) {
+bool IndexingContext::handleObjCCategory(const ObjCCategoryDecl *D) {
ObjCCategoryDeclInfo CatDInfo(/*isImplementation=*/false);
CXIdxEntityInfo ClassEntity;
StrAdapter SA(*this);
const ObjCInterfaceDecl *IFaceD = D->getClassInterface();
SourceLocation ClassLoc = D->getLocation();
- SourceLocation CategoryLoc = D->getCategoryNameLoc();
+ SourceLocation CategoryLoc = D->IsClassExtension() ? ClassLoc
+ : D->getCategoryNameLoc();
getEntityInfo(IFaceD, ClassEntity, SA);
CatDInfo.ObjCCatDeclInfo.containerInfo = &CatDInfo.ObjCContDeclInfo;
@@ -254,10 +311,10 @@
CatDInfo.ObjCCatDeclInfo.classCursor = clang_getNullCursor();
}
CatDInfo.ObjCCatDeclInfo.classLoc = getIndexLoc(ClassLoc);
- handleObjCContainer(D, CategoryLoc, getCursor(D), CatDInfo);
+ return handleObjCContainer(D, CategoryLoc, getCursor(D), CatDInfo);
}
-void IndexingContext::handleObjCCategoryImpl(const ObjCCategoryImplDecl *D) {
+bool IndexingContext::handleObjCCategoryImpl(const ObjCCategoryImplDecl *D) {
const ObjCCategoryDecl *CatD = D->getCategoryDecl();
ObjCCategoryDeclInfo CatDInfo(/*isImplementation=*/true);
CXIdxEntityInfo ClassEntity;
@@ -277,69 +334,78 @@
CatDInfo.ObjCCatDeclInfo.classCursor = clang_getNullCursor();
}
CatDInfo.ObjCCatDeclInfo.classLoc = getIndexLoc(ClassLoc);
- handleObjCContainer(D, CategoryLoc, getCursor(D), CatDInfo);
+ return handleObjCContainer(D, CategoryLoc, getCursor(D), CatDInfo);
}
-void IndexingContext::handleObjCMethod(const ObjCMethodDecl *D) {
+bool IndexingContext::handleObjCMethod(const ObjCMethodDecl *D) {
DeclInfo DInfo(!D->isCanonicalDecl(), D->isThisDeclarationADefinition(),
D->isThisDeclarationADefinition());
- handleDecl(D, D->getLocation(), getCursor(D), DInfo);
+ return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
}
-void IndexingContext::handleObjCProperty(const ObjCPropertyDecl *D) {
+bool IndexingContext::handleSynthesizedObjCProperty(
+ const ObjCPropertyImplDecl *D) {
+ ObjCPropertyDecl *PD = D->getPropertyDecl();
+ return handleReference(PD, D->getLocation(), getCursor(D), 0, D->getDeclContext());
+}
+
+bool IndexingContext::handleSynthesizedObjCMethod(const ObjCMethodDecl *D,
+ SourceLocation Loc) {
+ DeclInfo DInfo(/*isRedeclaration=*/true, /*isDefinition=*/true,
+ /*isContainer=*/false);
+ return handleDecl(D, Loc, getCursor(D), DInfo);
+}
+
+bool IndexingContext::handleObjCProperty(const ObjCPropertyDecl *D) {
DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/false,
/*isContainer=*/false);
- handleDecl(D, D->getLocation(), getCursor(D), DInfo);
+ return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
}
-void IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
+bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
const NamedDecl *Parent,
const DeclContext *DC,
const Expr *E,
CXIdxEntityRefKind Kind) {
if (!D)
- return;
- if (D->getParentFunctionOrMethod())
- return;
- if (Loc.isInvalid())
- return;
- if (!CB.indexEntityReference)
- return;
- if (isNotFromSourceFile(D->getLocation()))
- return;
+ return false;
- D = getEntityDecl(D);
+ CXCursor Cursor = E ? MakeCXCursor(const_cast<Expr*>(E),
+ const_cast<Decl*>(cast<Decl>(DC)), CXTU)
+ : getRefCursor(D, Loc);
+ return handleReference(D, Loc, Cursor, Parent, DC, E, Kind);
+}
+
+bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
+ CXCursor Cursor,
+ const NamedDecl *Parent,
+ const DeclContext *DC,
+ const Expr *E,
+ CXIdxEntityRefKind Kind) {
+ if (!D)
+ return false;
+ if (D->getParentFunctionOrMethod())
+ return false;
+ if (Loc.isInvalid())
+ return false;
+ if (!CB.indexEntityReference)
+ return false;
+ if (isNotFromSourceFile(D->getLocation()))
+ return false;
StrAdapter SA(*this);
CXIdxEntityInfo RefEntity, ParentEntity;
getEntityInfo(D, RefEntity, SA);
if (!RefEntity.USR)
- return;
+ return false;
getEntityInfo(Parent, ParentEntity, SA);
- if (onlyOneRefPerFile()) {
- SourceManager &SM = Ctx->getSourceManager();
- SourceLocation FileLoc = SM.getFileLoc(Loc);
-
- std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
- FileID FID = LocInfo.first;
- if (FID.isInvalid())
- return;
-
- const FileEntry *FE = SM.getFileEntryForID(FID);
- if (!FE)
- return;
- RefFileOccurence RefOccur(FE, D);
- std::pair<llvm::DenseSet<RefFileOccurence>::iterator, bool>
- res = RefFileOccurences.insert(RefOccur);
- if (!res.second)
- return; // already in map.
+ if (suppressRefs()) {
+ if (markEntityOccurrenceInFile(D, Loc))
+ return false; // already occurred.
}
- CXCursor Cursor = E ? MakeCXCursor(const_cast<Expr*>(E),
- const_cast<Decl*>(cast<Decl>(DC)), CXTU)
- : getRefCursor(D, Loc);
CXIdxEntityRefInfo Info = { Cursor,
getIndexLoc(Loc),
&RefEntity,
@@ -347,6 +413,7 @@
getIndexContainerForDC(DC),
Kind };
CB.indexEntityReference(ClientData, &Info);
+ return true;
}
bool IndexingContext::isNotFromSourceFile(SourceLocation Loc) const {
@@ -375,15 +442,34 @@
ContainerMap.erase(I);
}
+bool IndexingContext::markEntityOccurrenceInFile(const NamedDecl *D,
+ SourceLocation Loc) {
+ SourceManager &SM = Ctx->getSourceManager();
+ SourceLocation FileLoc = SM.getFileLoc(Loc);
+ D = getEntityDecl(D);
+
+ std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
+ FileID FID = LocInfo.first;
+ if (FID.isInvalid())
+ return true;
+
+ const FileEntry *FE = SM.getFileEntryForID(FID);
+ if (!FE)
+ return true;
+ RefFileOccurence RefOccur(FE, D);
+ std::pair<llvm::DenseSet<RefFileOccurence>::iterator, bool>
+ res = RefFileOccurences.insert(RefOccur);
+ if (!res.second)
+ return true; // already in map.
+
+ return false;
+}
+
const NamedDecl *IndexingContext::getEntityDecl(const NamedDecl *D) const {
assert(D);
D = cast<NamedDecl>(D->getCanonicalDecl());
- if (const ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(D)) {
- if (Cat->IsClassExtension())
- return getEntityDecl(Cat->getClassInterface());
-
- } else if (const ObjCImplementationDecl *
+ if (const ObjCImplementationDecl *
ImplD = dyn_cast<ObjCImplementationDecl>(D)) {
return getEntityDecl(ImplD->getClassInterface());
@@ -563,7 +649,14 @@
return MakeCursorObjCClassRef(ID, Loc, CXTU);
if (const ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D))
return MakeCursorObjCProtocolRef(PD, Loc, CXTU);
-
- //assert(0 && "not yet");
+ if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(D))
+ return MakeCursorTemplateRef(Template, Loc, CXTU);
+ if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(D))
+ return MakeCursorNamespaceRef(Namespace, Loc, CXTU);
+ if (const NamespaceAliasDecl *Namespace = dyn_cast<NamespaceAliasDecl>(D))
+ return MakeCursorNamespaceRef(Namespace, Loc, CXTU);
+ if (const FieldDecl *Field = dyn_cast<FieldDecl>(D))
+ return MakeCursorMemberRef(Field, Loc, CXTU);
+
return clang_getNullCursor();
}