diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2011-10-17 19:48:19 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2011-10-17 19:48:19 +0000 |
commit | 4e7064fa7e344e8f87a5b8457e96dfdd252c4a9e (patch) | |
tree | db3fd8ec700eccc7b796986919ef8a4f88eb6696 /tools/libclang/IndexDecl.cpp | |
parent | b4a686df4de21ec4eeca69211b21f7fe716abeae (diff) |
[libclang] Introduce a new high level API for indexing clients that assumes
more of the work involved in indexing a translation unit and simplifies client
implementations.
Only C/ObjC for now, C++ (and comments) to come.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@142233 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools/libclang/IndexDecl.cpp')
-rw-r--r-- | tools/libclang/IndexDecl.cpp | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/tools/libclang/IndexDecl.cpp b/tools/libclang/IndexDecl.cpp new file mode 100644 index 0000000000..5cf9f80263 --- /dev/null +++ b/tools/libclang/IndexDecl.cpp @@ -0,0 +1,218 @@ +//===- CIndexHigh.cpp - Higher level API functions ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "IndexingContext.h" + +#include "clang/AST/DeclVisitor.h" + +using namespace clang; +using namespace cxindex; + +namespace { + +class IndexingDeclVisitor : public DeclVisitor<IndexingDeclVisitor, bool> { + IndexingContext &IndexCtx; + +public: + explicit IndexingDeclVisitor(IndexingContext &indexCtx) + : IndexCtx(indexCtx) { } + + bool VisitFunctionDecl(FunctionDecl *D) { + IndexCtx.handleFunction(D); + IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); + if (D->isThisDeclarationADefinition()) { + const Stmt *Body = D->getBody(); + if (Body) { + IndexCtx.invokeStartedStatementBody(D, D); + IndexCtx.indexBody(Body, D); + IndexCtx.invokeEndedContainer(D); + } + } + return true; + } + + bool VisitVarDecl(VarDecl *D) { + IndexCtx.handleVar(D); + IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); + return true; + } + + bool VisitFieldDecl(FieldDecl *D) { + IndexCtx.handleField(D); + IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); + return true; + } + + bool VisitEnumConstantDecl(EnumConstantDecl *D) { + IndexCtx.handleEnumerator(D); + return true; + } + + bool VisitTypedefDecl(TypedefDecl *D) { + IndexCtx.handleTypedef(D); + IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); + return true; + } + + bool VisitTagDecl(TagDecl *D) { + // Non-free standing tags are handled in indexTypeSourceInfo. + if (D->isFreeStanding()) + IndexCtx.indexTagDecl(D); + return true; + } + + bool VisitObjCClassDecl(ObjCClassDecl *D) { + ObjCClassDecl::ObjCClassRef *Ref = D->getForwardDecl(); + if (Ref->getInterface()->getLocation() == Ref->getLocation()) { + IndexCtx.handleObjCInterface(Ref->getInterface()); + } else { + IndexCtx.handleReference(Ref->getInterface(), + Ref->getLocation(), + 0, + Ref->getInterface()->getDeclContext()); + } + return true; + } + + bool VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) { + ObjCForwardProtocolDecl::protocol_loc_iterator LI = D->protocol_loc_begin(); + for (ObjCForwardProtocolDecl::protocol_iterator + I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I, ++LI) { + SourceLocation Loc = *LI; + ObjCProtocolDecl *PD = *I; + + if (PD->getLocation() == Loc) { + IndexCtx.handleObjCProtocol(PD); + } else { + IndexCtx.handleReference(PD, Loc, 0, PD->getDeclContext()); + } + } + return true; + } + + bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { + // Only definitions are handled here. + if (D->isForwardDecl()) + return true; + + if (!D->isInitiallyForwardDecl()) + IndexCtx.handleObjCInterface(D); + + IndexCtx.indexTUDeclsInObjCContainer(); + IndexCtx.invokeStartedObjCContainer(D); + IndexCtx.defineObjCInterface(D); + IndexCtx.indexDeclContext(D); + IndexCtx.invokeEndedContainer(D); + return true; + } + + bool VisitObjCProtocolDecl(ObjCProtocolDecl *D) { + // Only definitions are handled here. + if (D->isForwardDecl()) + return true; + + if (!D->isInitiallyForwardDecl()) + IndexCtx.handleObjCProtocol(D); + + IndexCtx.indexTUDeclsInObjCContainer(); + IndexCtx.invokeStartedObjCContainer(D); + IndexCtx.indexDeclContext(D); + IndexCtx.invokeEndedContainer(D); + return true; + } + + bool VisitObjCImplementationDecl(ObjCImplementationDecl *D) { + ObjCInterfaceDecl *Class = D->getClassInterface(); + if (Class->isImplicitInterfaceDecl()) + IndexCtx.handleObjCInterface(Class); + + IndexCtx.indexTUDeclsInObjCContainer(); + IndexCtx.invokeStartedObjCContainer(D); + IndexCtx.indexDeclContext(D); + IndexCtx.invokeEndedContainer(D); + return true; + } + + bool VisitObjCCategoryDecl(ObjCCategoryDecl *D) { + if (!D->IsClassExtension()) + IndexCtx.handleObjCCategory(D); + + IndexCtx.indexTUDeclsInObjCContainer(); + IndexCtx.invokeStartedObjCContainer(D); + IndexCtx.indexDeclContext(D); + IndexCtx.invokeEndedContainer(D); + return true; + } + + bool VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { + IndexCtx.indexTUDeclsInObjCContainer(); + IndexCtx.invokeStartedObjCContainer(D); + IndexCtx.indexDeclContext(D); + IndexCtx.invokeEndedContainer(D); + return true; + } + + bool VisitObjCMethodDecl(ObjCMethodDecl *D) { + IndexCtx.handleObjCMethod(D); + IndexCtx.indexTypeSourceInfo(D->getResultTypeSourceInfo(), D); + for (ObjCMethodDecl::param_iterator + I = D->param_begin(), E = D->param_end(); I != E; ++I) + IndexCtx.indexTypeSourceInfo((*I)->getTypeSourceInfo(), D); + + if (D->isThisDeclarationADefinition()) { + const Stmt *Body = D->getBody(); + if (Body) { + IndexCtx.invokeStartedStatementBody(D, D); + IndexCtx.indexBody(Body, D); + IndexCtx.invokeEndedContainer(D); + } + } + return true; + } + + bool VisitObjCPropertyDecl(ObjCPropertyDecl *D) { + IndexCtx.handleObjCProperty(D); + IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); + return true; + } +}; + +} // anonymous namespace + +void IndexingContext::indexDecl(const Decl *D) { + bool Handled = IndexingDeclVisitor(*this).Visit(const_cast<Decl*>(D)); + if (!Handled && isa<DeclContext>(D)) + indexDeclContext(cast<DeclContext>(D)); +} + +void IndexingContext::indexDeclContext(const DeclContext *DC) { + for (DeclContext::decl_iterator + I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) { + indexDecl(*I); + } +} + +void IndexingContext::indexDeclGroupRef(DeclGroupRef DG) { + for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) { + Decl *D = *I; + if (isNotFromSourceFile(D->getLocation())) + return; + + if (isa<ObjCMethodDecl>(D)) + continue; // Wait for the objc container. + + indexDecl(D); + } +} + +void IndexingContext::indexTUDeclsInObjCContainer() { + for (unsigned i = 0, e = TUDeclsInObjCContainer.size(); i != e; ++i) + indexDeclGroupRef(TUDeclsInObjCContainer[i]); + TUDeclsInObjCContainer.clear(); +} |