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 BodyIndexer : public DataRecursiveASTVisitor<BodyIndexer> {
     19   IndexingContext &IndexCtx;
     20   const NamedDecl *Parent;
     21   const DeclContext *ParentDC;
     22 
     23   typedef DataRecursiveASTVisitor<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 (ObjCMethodDecl *MD = E->getMethodDecl())
     72       IndexCtx.handleReference(MD, E->getSelectorStartLoc(),
     73                                Parent, ParentDC, E,
     74                                E->isImplicit() ? CXIdxEntityRef_Implicit
     75                                                : CXIdxEntityRef_Direct);
     76     return true;
     77   }
     78 
     79   bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
     80     if (E->isExplicitProperty())
     81       IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(),
     82                                Parent, ParentDC, E);
     83 
     84     // No need to do a handleReference for the objc method, because there will
     85     // be a message expr as part of PseudoObjectExpr.
     86     return true;
     87   }
     88 
     89   bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) {
     90     IndexCtx.handleReference(E->getPropertyDecl(), E->getMemberLoc(), Parent,
     91                              ParentDC, E, CXIdxEntityRef_Direct);
     92     return true;
     93   }
     94 
     95   bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
     96     IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(),
     97                              Parent, ParentDC, E, CXIdxEntityRef_Direct);
     98     return true;
     99   }
    100 
    101   bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
    102     if (ObjCMethodDecl *MD = E->getBoxingMethod())
    103       IndexCtx.handleReference(MD, E->getLocStart(),
    104                                Parent, ParentDC, E, CXIdxEntityRef_Implicit);
    105     return true;
    106   }
    107 
    108   bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
    109     if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod())
    110       IndexCtx.handleReference(MD, E->getLocStart(),
    111                                Parent, ParentDC, E, CXIdxEntityRef_Implicit);
    112     return true;
    113   }
    114 
    115   bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
    116     if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod())
    117       IndexCtx.handleReference(MD, E->getLocStart(),
    118                                Parent, ParentDC, E, CXIdxEntityRef_Implicit);
    119     return true;
    120   }
    121 
    122   bool VisitCXXConstructExpr(CXXConstructExpr *E) {
    123     IndexCtx.handleReference(E->getConstructor(), E->getLocation(),
    124                              Parent, ParentDC, E);
    125     return true;
    126   }
    127 
    128   bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
    129     if (E->getOperatorLoc().isInvalid())
    130       return true; // implicit.
    131     return base::TraverseCXXOperatorCallExpr(E);
    132   }
    133 
    134   bool VisitDeclStmt(DeclStmt *S) {
    135     if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
    136       IndexCtx.indexDeclGroupRef(S->getDeclGroup());
    137       return true;
    138     }
    139 
    140     DeclGroupRef DG = S->getDeclGroup();
    141     for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) {
    142       const Decl *D = *I;
    143       if (!D)
    144         continue;
    145       if (!IndexCtx.isFunctionLocalDecl(D))
    146         IndexCtx.indexTopLevelDecl(D);
    147     }
    148 
    149     return true;
    150   }
    151 
    152   bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C) {
    153     if (C->capturesThis())
    154       return true;
    155 
    156     if (C->capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols())
    157       IndexCtx.handleReference(C->getCapturedVar(), C->getLocation(), Parent,
    158                                ParentDC);
    159 
    160     // FIXME: Lambda init-captures.
    161     return true;
    162   }
    163 
    164 };
    165 
    166 } // anonymous namespace
    167 
    168 void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent,
    169                                 const DeclContext *DC) {
    170   if (!S)
    171     return;
    172 
    173   if (!DC)
    174     DC = Parent->getLexicalDeclContext();
    175   BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast<Stmt*>(S));
    176 }
    177