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 "RecursiveASTVisitor.h"
     12 
     13 using namespace clang;
     14 using namespace cxindex;
     15 
     16 namespace {
     17 
     18 class BodyIndexer : public cxindex::RecursiveASTVisitor<BodyIndexer> {
     19   IndexingContext &IndexCtx;
     20   const NamedDecl *Parent;
     21   const DeclContext *ParentDC;
     22 
     23   typedef RecursiveASTVisitor<BodyIndexer> base;
     24 public:
     25   BodyIndexer(IndexingContext &indexCtx,
     26               const NamedDecl *Parent, const DeclContext *DC)
     27     : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { }
     28 
     29   bool shouldWalkTypesOfTypeLocs() const { return false; }
     30 
     31   bool TraverseTypeLoc(TypeLoc TL) {
     32     IndexCtx.indexTypeLoc(TL, 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 VisitDeclRefExpr(DeclRefExpr *E) {
     42     IndexCtx.handleReference(E->getDecl(), E->getLocation(),
     43                              Parent, ParentDC, E);
     44     return true;
     45   }
     46 
     47   bool VisitMemberExpr(MemberExpr *E) {
     48     IndexCtx.handleReference(E->getMemberDecl(), E->getMemberLoc(),
     49                              Parent, ParentDC, E);
     50     return true;
     51   }
     52 
     53   bool VisitDesignatedInitExpr(DesignatedInitExpr *E) {
     54     for (DesignatedInitExpr::reverse_designators_iterator
     55            D = E->designators_rbegin(), DEnd = E->designators_rend();
     56            D != DEnd; ++D) {
     57       if (D->isFieldDesignator())
     58         IndexCtx.handleReference(D->getField(), D->getFieldLoc(),
     59                                  Parent, ParentDC, E);
     60     }
     61     return true;
     62   }
     63 
     64   bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
     65     IndexCtx.handleReference(E->getDecl(), E->getLocation(),
     66                              Parent, ParentDC, E);
     67     return true;
     68   }
     69 
     70   bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
     71     if (TypeSourceInfo *Cls = E->getClassReceiverTypeInfo())
     72       IndexCtx.indexTypeSourceInfo(Cls, Parent, ParentDC);
     73 
     74     if (ObjCMethodDecl *MD = E->getMethodDecl())
     75       IndexCtx.handleReference(MD, E->getSelectorStartLoc(),
     76                                Parent, ParentDC, E,
     77                                E->isImplicit() ? CXIdxEntityRef_Implicit
     78                                                : CXIdxEntityRef_Direct);
     79     return true;
     80   }
     81 
     82   bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
     83     if (E->isExplicitProperty())
     84       IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(),
     85                                Parent, ParentDC, E);
     86 
     87     // No need to do a handleReference for the objc method, because there will
     88     // be a message expr as part of PseudoObjectExpr.
     89     return true;
     90   }
     91 
     92   bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
     93     IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(),
     94                              Parent, ParentDC, E, CXIdxEntityRef_Direct);
     95     return true;
     96   }
     97 
     98   bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
     99     if (ObjCMethodDecl *MD = E->getBoxingMethod())
    100       IndexCtx.handleReference(MD, E->getLocStart(),
    101                                Parent, ParentDC, E, CXIdxEntityRef_Implicit);
    102     return true;
    103   }
    104 
    105   bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
    106     if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod())
    107       IndexCtx.handleReference(MD, E->getLocStart(),
    108                                Parent, ParentDC, E, CXIdxEntityRef_Implicit);
    109     return true;
    110   }
    111 
    112   bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
    113     if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod())
    114       IndexCtx.handleReference(MD, E->getLocStart(),
    115                                Parent, ParentDC, E, CXIdxEntityRef_Implicit);
    116     return true;
    117   }
    118 
    119   bool VisitCXXConstructExpr(CXXConstructExpr *E) {
    120     IndexCtx.handleReference(E->getConstructor(), E->getLocation(),
    121                              Parent, ParentDC, E);
    122     return true;
    123   }
    124 
    125   bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
    126     if (E->getOperatorLoc().isInvalid())
    127       return true; // implicit.
    128     return base::TraverseCXXOperatorCallExpr(E);
    129   }
    130 
    131   bool VisitDeclStmt(DeclStmt *S) {
    132     if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
    133       IndexCtx.indexDeclGroupRef(S->getDeclGroup());
    134       return true;
    135     }
    136 
    137     DeclGroupRef DG = S->getDeclGroup();
    138     for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) {
    139       const Decl *D = *I;
    140       if (!D)
    141         continue;
    142       if (!IndexCtx.isFunctionLocalDecl(D))
    143         IndexCtx.indexTopLevelDecl(D);
    144     }
    145 
    146     return true;
    147   }
    148 
    149   bool TraverseLambdaCapture(LambdaExpr::Capture C) {
    150     if (C.capturesThis())
    151       return true;
    152 
    153     if (IndexCtx.shouldIndexFunctionLocalSymbols())
    154       IndexCtx.handleReference(C.getCapturedVar(), C.getLocation(),
    155                                Parent, ParentDC);
    156     return true;
    157   }
    158 
    159 };
    160 
    161 } // anonymous namespace
    162 
    163 void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent,
    164                                 const DeclContext *DC) {
    165   if (!S)
    166     return;
    167 
    168   if (DC == 0)
    169     DC = Parent->getLexicalDeclContext();
    170   BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast<Stmt*>(S));
    171 }
    172