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