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/DeclVisitor.h"
     13 
     14 using namespace clang;
     15 using namespace cxindex;
     16 
     17 namespace {
     18 
     19 class IndexingDeclVisitor : public DeclVisitor<IndexingDeclVisitor, bool> {
     20   IndexingContext &IndexCtx;
     21 
     22 public:
     23   explicit IndexingDeclVisitor(IndexingContext &indexCtx)
     24     : IndexCtx(indexCtx) { }
     25 
     26   bool VisitFunctionDecl(FunctionDecl *D) {
     27     IndexCtx.handleFunction(D);
     28     IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
     29     if (D->isThisDeclarationADefinition()) {
     30       const Stmt *Body = D->getBody();
     31       if (Body) {
     32         IndexCtx.invokeStartedStatementBody(D, D);
     33         IndexCtx.indexBody(Body, D);
     34         IndexCtx.invokeEndedContainer(D);
     35       }
     36     }
     37     return true;
     38   }
     39 
     40   bool VisitVarDecl(VarDecl *D) {
     41     IndexCtx.handleVar(D);
     42     IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
     43     return true;
     44   }
     45 
     46   bool VisitFieldDecl(FieldDecl *D) {
     47     IndexCtx.handleField(D);
     48     IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
     49     return true;
     50   }
     51 
     52   bool VisitEnumConstantDecl(EnumConstantDecl *D) {
     53     IndexCtx.handleEnumerator(D);
     54     return true;
     55   }
     56 
     57   bool VisitTypedefDecl(TypedefDecl *D) {
     58     IndexCtx.handleTypedef(D);
     59     IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
     60     return true;
     61   }
     62 
     63   bool VisitTagDecl(TagDecl *D) {
     64     // Non-free standing tags are handled in indexTypeSourceInfo.
     65     if (D->isFreeStanding())
     66       IndexCtx.indexTagDecl(D);
     67     return true;
     68   }
     69 
     70   bool VisitObjCClassDecl(ObjCClassDecl *D) {
     71     ObjCClassDecl::ObjCClassRef *Ref = D->getForwardDecl();
     72     if (Ref->getInterface()->getLocation() == Ref->getLocation()) {
     73       IndexCtx.handleObjCInterface(Ref->getInterface());
     74     } else {
     75       IndexCtx.handleReference(Ref->getInterface(),
     76                                Ref->getLocation(),
     77                                0,
     78                                Ref->getInterface()->getDeclContext());
     79     }
     80     return true;
     81   }
     82 
     83   bool VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) {
     84     ObjCForwardProtocolDecl::protocol_loc_iterator LI = D->protocol_loc_begin();
     85     for (ObjCForwardProtocolDecl::protocol_iterator
     86            I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I, ++LI) {
     87       SourceLocation Loc = *LI;
     88       ObjCProtocolDecl *PD = *I;
     89 
     90       if (PD->getLocation() == Loc) {
     91         IndexCtx.handleObjCProtocol(PD);
     92       } else {
     93         IndexCtx.handleReference(PD, Loc, 0, PD->getDeclContext());
     94       }
     95     }
     96     return true;
     97   }
     98 
     99   bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
    100     // Only definitions are handled here.
    101     if (D->isForwardDecl())
    102       return true;
    103 
    104     if (!D->isInitiallyForwardDecl())
    105       IndexCtx.handleObjCInterface(D);
    106 
    107     IndexCtx.indexTUDeclsInObjCContainer();
    108     IndexCtx.invokeStartedObjCContainer(D);
    109     IndexCtx.defineObjCInterface(D);
    110     IndexCtx.indexDeclContext(D);
    111     IndexCtx.invokeEndedContainer(D);
    112     return true;
    113   }
    114 
    115   bool VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
    116     // Only definitions are handled here.
    117     if (D->isForwardDecl())
    118       return true;
    119 
    120     if (!D->isInitiallyForwardDecl())
    121       IndexCtx.handleObjCProtocol(D);
    122 
    123     IndexCtx.indexTUDeclsInObjCContainer();
    124     IndexCtx.invokeStartedObjCContainer(D);
    125     IndexCtx.indexDeclContext(D);
    126     IndexCtx.invokeEndedContainer(D);
    127     return true;
    128   }
    129 
    130   bool VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
    131     ObjCInterfaceDecl *Class = D->getClassInterface();
    132     if (Class->isImplicitInterfaceDecl())
    133       IndexCtx.handleObjCInterface(Class);
    134 
    135     IndexCtx.indexTUDeclsInObjCContainer();
    136     IndexCtx.invokeStartedObjCContainer(D);
    137     IndexCtx.indexDeclContext(D);
    138     IndexCtx.invokeEndedContainer(D);
    139     return true;
    140   }
    141 
    142   bool VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
    143     if (!D->IsClassExtension())
    144       IndexCtx.handleObjCCategory(D);
    145 
    146     IndexCtx.indexTUDeclsInObjCContainer();
    147     IndexCtx.invokeStartedObjCContainer(D);
    148     IndexCtx.indexDeclContext(D);
    149     IndexCtx.invokeEndedContainer(D);
    150     return true;
    151   }
    152 
    153   bool VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
    154     IndexCtx.indexTUDeclsInObjCContainer();
    155     IndexCtx.invokeStartedObjCContainer(D);
    156     IndexCtx.indexDeclContext(D);
    157     IndexCtx.invokeEndedContainer(D);
    158     return true;
    159   }
    160 
    161   bool VisitObjCMethodDecl(ObjCMethodDecl *D) {
    162     IndexCtx.handleObjCMethod(D);
    163     IndexCtx.indexTypeSourceInfo(D->getResultTypeSourceInfo(), D);
    164     for (ObjCMethodDecl::param_iterator
    165            I = D->param_begin(), E = D->param_end(); I != E; ++I)
    166       IndexCtx.indexTypeSourceInfo((*I)->getTypeSourceInfo(), D);
    167 
    168     if (D->isThisDeclarationADefinition()) {
    169       const Stmt *Body = D->getBody();
    170       if (Body) {
    171         IndexCtx.invokeStartedStatementBody(D, D);
    172         IndexCtx.indexBody(Body, D);
    173         IndexCtx.invokeEndedContainer(D);
    174       }
    175     }
    176     return true;
    177   }
    178 
    179   bool VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
    180     IndexCtx.handleObjCProperty(D);
    181     IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
    182     return true;
    183   }
    184 };
    185 
    186 } // anonymous namespace
    187 
    188 void IndexingContext::indexDecl(const Decl *D) {
    189   bool Handled = IndexingDeclVisitor(*this).Visit(const_cast<Decl*>(D));
    190   if (!Handled && isa<DeclContext>(D))
    191     indexDeclContext(cast<DeclContext>(D));
    192 }
    193 
    194 void IndexingContext::indexDeclContext(const DeclContext *DC) {
    195   for (DeclContext::decl_iterator
    196          I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) {
    197     indexDecl(*I);
    198   }
    199 }
    200 
    201 void IndexingContext::indexDeclGroupRef(DeclGroupRef DG) {
    202   for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) {
    203     Decl *D = *I;
    204     if (isNotFromSourceFile(D->getLocation()))
    205       return;
    206 
    207     if (isa<ObjCMethodDecl>(D))
    208       continue; // Wait for the objc container.
    209 
    210     indexDecl(D);
    211   }
    212 }
    213 
    214 void IndexingContext::indexTUDeclsInObjCContainer() {
    215   for (unsigned i = 0, e = TUDeclsInObjCContainer.size(); i != e; ++i)
    216     indexDeclGroupRef(TUDeclsInObjCContainer[i]);
    217   TUDeclsInObjCContainer.clear();
    218 }
    219