//===- 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/DataRecursiveASTVisitor.h" using namespace clang; using namespace cxindex; namespace { class TypeIndexer : public DataRecursiveASTVisitor { IndexingContext &IndexCtx; const NamedDecl *Parent; const DeclContext *ParentDC; public: TypeIndexer(IndexingContext &indexCtx, const NamedDecl *parent, const DeclContext *DC) : IndexCtx(indexCtx), Parent(parent), ParentDC(DC) { } bool shouldWalkTypesOfTypeLocs() const { return false; } bool VisitTypedefTypeLoc(TypedefTypeLoc TL) { IndexCtx.handleReference(TL.getTypedefNameDecl(), TL.getNameLoc(), Parent, ParentDC); return true; } bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC); return true; } bool VisitTagTypeLoc(TagTypeLoc TL) { TagDecl *D = TL.getDecl(); if (D->getParentFunctionOrMethod()) return true; if (TL.isDefinition()) { IndexCtx.indexTagDecl(D); return true; } if (D->getLocation() == TL.getNameLoc()) IndexCtx.handleTagDecl(D); else IndexCtx.handleReference(D, TL.getNameLoc(), Parent, ParentDC); return true; } bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { IndexCtx.handleReference(TL.getIFaceDecl(), TL.getNameLoc(), Parent, ParentDC); return true; } bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) { for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) { IndexCtx.handleReference(TL.getProtocol(i), TL.getProtocolLoc(i), Parent, ParentDC); } return true; } bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) { if (const TemplateSpecializationType *T = TL.getTypePtr()) { if (IndexCtx.shouldIndexImplicitTemplateInsts()) { if (CXXRecordDecl *RD = T->getAsCXXRecordDecl()) IndexCtx.handleReference(RD, TL.getTemplateNameLoc(), Parent, ParentDC); } else { if (const TemplateDecl *D = T->getTemplateName().getAsTemplateDecl()) IndexCtx.handleReference(D, TL.getTemplateNameLoc(), Parent, ParentDC); } } return true; } bool TraverseStmt(Stmt *S) { IndexCtx.indexBody(S, Parent, ParentDC); return true; } }; } // anonymous namespace void IndexingContext::indexTypeSourceInfo(TypeSourceInfo *TInfo, const NamedDecl *Parent, const DeclContext *DC) { if (!TInfo || TInfo->getTypeLoc().isNull()) return; indexTypeLoc(TInfo->getTypeLoc(), Parent, DC); } void IndexingContext::indexTypeLoc(TypeLoc TL, const NamedDecl *Parent, const DeclContext *DC) { if (TL.isNull()) return; if (!DC) DC = Parent->getLexicalDeclContext(); TypeIndexer(*this, Parent, DC).TraverseTypeLoc(TL); } void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, const NamedDecl *Parent, const DeclContext *DC) { if (!NNS) return; if (NestedNameSpecifierLoc Prefix = NNS.getPrefix()) indexNestedNameSpecifierLoc(Prefix, Parent, DC); if (!DC) DC = Parent->getLexicalDeclContext(); SourceLocation Loc = NNS.getSourceRange().getBegin(); switch (NNS.getNestedNameSpecifier()->getKind()) { case NestedNameSpecifier::Identifier: case NestedNameSpecifier::Global: case NestedNameSpecifier::Super: break; case NestedNameSpecifier::Namespace: handleReference(NNS.getNestedNameSpecifier()->getAsNamespace(), Loc, Parent, DC); break; case NestedNameSpecifier::NamespaceAlias: handleReference(NNS.getNestedNameSpecifier()->getAsNamespaceAlias(), Loc, Parent, DC); break; case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: indexTypeLoc(NNS.getTypeLoc(), Parent, DC); break; } } void IndexingContext::indexTagDecl(const TagDecl *D) { if (handleTagDecl(D)) { if (D->isThisDeclarationADefinition()) indexDeclContext(D); } }