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