Home | History | Annotate | Download | only in libclang
      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 "clang/AST/DataRecursiveASTVisitor.h"
     12 
     13 using namespace clang;
     14 using namespace cxindex;
     15 
     16 namespace {
     17 
     18 class TypeIndexer : public DataRecursiveASTVisitor<TypeIndexer> {
     19   IndexingContext &IndexCtx;
     20   const NamedDecl *Parent;
     21   const DeclContext *ParentDC;
     22 
     23 public:
     24   TypeIndexer(IndexingContext &indexCtx, const NamedDecl *parent,
     25               const DeclContext *DC)
     26     : IndexCtx(indexCtx), Parent(parent), ParentDC(DC) { }
     27 
     28   bool shouldWalkTypesOfTypeLocs() const { return false; }
     29 
     30   bool VisitTypedefTypeLoc(TypedefTypeLoc TL) {
     31     IndexCtx.handleReference(TL.getTypedefNameDecl(), TL.getNameLoc(),
     32                              Parent, ParentDC);
     33     return true;
     34   }
     35 
     36   bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
     37     IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
     38     return true;
     39   }
     40 
     41   bool VisitTagTypeLoc(TagTypeLoc TL) {
     42     TagDecl *D = TL.getDecl();
     43     if (D->getParentFunctionOrMethod())
     44       return true;
     45 
     46     if (TL.isDefinition()) {
     47       IndexCtx.indexTagDecl(D);
     48       return true;
     49     }
     50 
     51     if (D->getLocation() == TL.getNameLoc())
     52       IndexCtx.handleTagDecl(D);
     53     else
     54       IndexCtx.handleReference(D, TL.getNameLoc(),
     55                                Parent, ParentDC);
     56     return true;
     57   }
     58 
     59   bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
     60     IndexCtx.handleReference(TL.getIFaceDecl(), TL.getNameLoc(),
     61                              Parent, ParentDC);
     62     return true;
     63   }
     64 
     65   bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
     66     for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) {
     67       IndexCtx.handleReference(TL.getProtocol(i), TL.getProtocolLoc(i),
     68                                Parent, ParentDC);
     69     }
     70     return true;
     71   }
     72 
     73   bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
     74     if (const TemplateSpecializationType *T = TL.getTypePtr()) {
     75       if (IndexCtx.shouldIndexImplicitTemplateInsts()) {
     76         if (CXXRecordDecl *RD = T->getAsCXXRecordDecl())
     77           IndexCtx.handleReference(RD, TL.getTemplateNameLoc(),
     78                                    Parent, ParentDC);
     79       } else {
     80         if (const TemplateDecl *D = T->getTemplateName().getAsTemplateDecl())
     81           IndexCtx.handleReference(D, TL.getTemplateNameLoc(),
     82                                    Parent, ParentDC);
     83       }
     84     }
     85     return true;
     86   }
     87 
     88   bool TraverseStmt(Stmt *S) {
     89     IndexCtx.indexBody(S, Parent, ParentDC);
     90     return true;
     91   }
     92 };
     93 
     94 } // anonymous namespace
     95 
     96 void IndexingContext::indexTypeSourceInfo(TypeSourceInfo *TInfo,
     97                                           const NamedDecl *Parent,
     98                                           const DeclContext *DC) {
     99   if (!TInfo || TInfo->getTypeLoc().isNull())
    100     return;
    101 
    102   indexTypeLoc(TInfo->getTypeLoc(), Parent, DC);
    103 }
    104 
    105 void IndexingContext::indexTypeLoc(TypeLoc TL,
    106                                    const NamedDecl *Parent,
    107                                    const DeclContext *DC) {
    108   if (TL.isNull())
    109     return;
    110 
    111   if (!DC)
    112     DC = Parent->getLexicalDeclContext();
    113   TypeIndexer(*this, Parent, DC).TraverseTypeLoc(TL);
    114 }
    115 
    116 void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
    117                                                   const NamedDecl *Parent,
    118                                                   const DeclContext *DC) {
    119   if (!NNS)
    120     return;
    121 
    122   if (NestedNameSpecifierLoc Prefix = NNS.getPrefix())
    123     indexNestedNameSpecifierLoc(Prefix, Parent, DC);
    124 
    125   if (!DC)
    126     DC = Parent->getLexicalDeclContext();
    127   SourceLocation Loc = NNS.getSourceRange().getBegin();
    128 
    129   switch (NNS.getNestedNameSpecifier()->getKind()) {
    130   case NestedNameSpecifier::Identifier:
    131   case NestedNameSpecifier::Global:
    132     break;
    133 
    134   case NestedNameSpecifier::Namespace:
    135     handleReference(NNS.getNestedNameSpecifier()->getAsNamespace(),
    136                     Loc, Parent, DC);
    137     break;
    138   case NestedNameSpecifier::NamespaceAlias:
    139     handleReference(NNS.getNestedNameSpecifier()->getAsNamespaceAlias(),
    140                     Loc, Parent, DC);
    141     break;
    142 
    143   case NestedNameSpecifier::TypeSpec:
    144   case NestedNameSpecifier::TypeSpecWithTemplate:
    145     indexTypeLoc(NNS.getTypeLoc(), Parent, DC);
    146     break;
    147   }
    148 }
    149 
    150 void IndexingContext::indexTagDecl(const TagDecl *D) {
    151   if (handleTagDecl(D)) {
    152     if (D->isThisDeclarationADefinition())
    153       indexDeclContext(D);
    154   }
    155 }
    156