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/DeclVisitor.h"
     12 
     13 using namespace clang;
     14 using namespace cxindex;
     15 
     16 namespace {
     17 
     18 class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
     19   IndexingContext &IndexCtx;
     20 
     21 public:
     22   explicit IndexingDeclVisitor(IndexingContext &indexCtx)
     23     : IndexCtx(indexCtx) { }
     24 
     25   /// \brief Returns true if the given method has been defined explicitly by the
     26   /// user.
     27   static bool hasUserDefined(const ObjCMethodDecl *D,
     28                              const ObjCImplDecl *Container) {
     29     const ObjCMethodDecl *MD = Container->getMethod(D->getSelector(),
     30                                                     D->isInstanceMethod());
     31     return MD && !MD->isImplicit() && MD->isThisDeclarationADefinition();
     32   }
     33 
     34   void handleDeclarator(const DeclaratorDecl *D, const NamedDecl *Parent = 0) {
     35     if (!Parent) Parent = D;
     36 
     37     if (!IndexCtx.shouldIndexFunctionLocalSymbols()) {
     38       IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent);
     39       IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent);
     40     } else {
     41       if (const ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) {
     42         IndexCtx.handleVar(Parm);
     43       } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
     44         for (FunctionDecl::param_const_iterator PI = FD->param_begin(),
     45                                                 PE = FD->param_end();
     46              PI != PE; ++PI) {
     47           IndexCtx.handleVar(*PI);
     48         }
     49       }
     50     }
     51   }
     52 
     53   void handleObjCMethod(const ObjCMethodDecl *D) {
     54     IndexCtx.handleObjCMethod(D);
     55     if (D->isImplicit())
     56       return;
     57 
     58     IndexCtx.indexTypeSourceInfo(D->getResultTypeSourceInfo(), D);
     59     for (ObjCMethodDecl::param_const_iterator I = D->param_begin(),
     60                                               E = D->param_end();
     61          I != E; ++I)
     62       handleDeclarator(*I, D);
     63 
     64     if (D->isThisDeclarationADefinition()) {
     65       const Stmt *Body = D->getBody();
     66       if (Body) {
     67         IndexCtx.indexBody(Body, D, D);
     68       }
     69     }
     70   }
     71 
     72   bool VisitFunctionDecl(const FunctionDecl *D) {
     73     IndexCtx.handleFunction(D);
     74     handleDeclarator(D);
     75 
     76     if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
     77       // Constructor initializers.
     78       for (CXXConstructorDecl::init_const_iterator I = Ctor->init_begin(),
     79                                                    E = Ctor->init_end();
     80            I != E; ++I) {
     81         CXXCtorInitializer *Init = *I;
     82         if (Init->isWritten()) {
     83           IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D);
     84           if (const FieldDecl *Member = Init->getAnyMember())
     85             IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D);
     86           IndexCtx.indexBody(Init->getInit(), D, D);
     87         }
     88       }
     89     }
     90 
     91     if (D->isThisDeclarationADefinition()) {
     92       const Stmt *Body = D->getBody();
     93       if (Body) {
     94         IndexCtx.indexBody(Body, D, D);
     95       }
     96     }
     97     return true;
     98   }
     99 
    100   bool VisitVarDecl(const VarDecl *D) {
    101     IndexCtx.handleVar(D);
    102     handleDeclarator(D);
    103     IndexCtx.indexBody(D->getInit(), D);
    104     return true;
    105   }
    106 
    107   bool VisitFieldDecl(const FieldDecl *D) {
    108     IndexCtx.handleField(D);
    109     handleDeclarator(D);
    110     if (D->isBitField())
    111       IndexCtx.indexBody(D->getBitWidth(), D);
    112     else if (D->hasInClassInitializer())
    113       IndexCtx.indexBody(D->getInClassInitializer(), D);
    114     return true;
    115   }
    116 
    117   bool VisitMSPropertyDecl(const MSPropertyDecl *D) {
    118     handleDeclarator(D);
    119     return true;
    120   }
    121 
    122   bool VisitEnumConstantDecl(const EnumConstantDecl *D) {
    123     IndexCtx.handleEnumerator(D);
    124     IndexCtx.indexBody(D->getInitExpr(), D);
    125     return true;
    126   }
    127 
    128   bool VisitTypedefNameDecl(const TypedefNameDecl *D) {
    129     IndexCtx.handleTypedefName(D);
    130     IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
    131     return true;
    132   }
    133 
    134   bool VisitTagDecl(const TagDecl *D) {
    135     // Non-free standing tags are handled in indexTypeSourceInfo.
    136     if (D->isFreeStanding())
    137       IndexCtx.indexTagDecl(D);
    138     return true;
    139   }
    140 
    141   bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
    142     IndexCtx.handleObjCInterface(D);
    143 
    144     if (D->isThisDeclarationADefinition()) {
    145       IndexCtx.indexTUDeclsInObjCContainer();
    146       IndexCtx.indexDeclContext(D);
    147     }
    148     return true;
    149   }
    150 
    151   bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
    152     IndexCtx.handleObjCProtocol(D);
    153 
    154     if (D->isThisDeclarationADefinition()) {
    155       IndexCtx.indexTUDeclsInObjCContainer();
    156       IndexCtx.indexDeclContext(D);
    157     }
    158     return true;
    159   }
    160 
    161   bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) {
    162     const ObjCInterfaceDecl *Class = D->getClassInterface();
    163     if (!Class)
    164       return true;
    165 
    166     if (Class->isImplicitInterfaceDecl())
    167       IndexCtx.handleObjCInterface(Class);
    168 
    169     IndexCtx.handleObjCImplementation(D);
    170 
    171     IndexCtx.indexTUDeclsInObjCContainer();
    172 
    173     // Index the ivars first to make sure the synthesized ivars are indexed
    174     // before indexing the methods that can reference them.
    175     for (ObjCImplementationDecl::ivar_iterator
    176            IvarI = D->ivar_begin(),
    177            IvarE = D->ivar_end(); IvarI != IvarE; ++IvarI) {
    178       IndexCtx.indexDecl(*IvarI);
    179     }
    180     for (DeclContext::decl_iterator
    181            I = D->decls_begin(), E = D->decls_end(); I != E; ++I) {
    182       if (!isa<ObjCIvarDecl>(*I))
    183         IndexCtx.indexDecl(*I);
    184     }
    185 
    186     return true;
    187   }
    188 
    189   bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
    190     IndexCtx.handleObjCCategory(D);
    191 
    192     IndexCtx.indexTUDeclsInObjCContainer();
    193     IndexCtx.indexDeclContext(D);
    194     return true;
    195   }
    196 
    197   bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
    198     const ObjCCategoryDecl *Cat = D->getCategoryDecl();
    199     if (!Cat)
    200       return true;
    201 
    202     IndexCtx.handleObjCCategoryImpl(D);
    203 
    204     IndexCtx.indexTUDeclsInObjCContainer();
    205     IndexCtx.indexDeclContext(D);
    206     return true;
    207   }
    208 
    209   bool VisitObjCMethodDecl(const ObjCMethodDecl *D) {
    210     // Methods associated with a property, even user-declared ones, are
    211     // handled when we handle the property.
    212     if (D->isPropertyAccessor())
    213       return true;
    214 
    215     handleObjCMethod(D);
    216     return true;
    217   }
    218 
    219   bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
    220     if (ObjCMethodDecl *MD = D->getGetterMethodDecl())
    221       if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
    222         handleObjCMethod(MD);
    223     if (ObjCMethodDecl *MD = D->getSetterMethodDecl())
    224       if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
    225         handleObjCMethod(MD);
    226     IndexCtx.handleObjCProperty(D);
    227     IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
    228     return true;
    229   }
    230 
    231   bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
    232     ObjCPropertyDecl *PD = D->getPropertyDecl();
    233     IndexCtx.handleSynthesizedObjCProperty(D);
    234 
    235     if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
    236       return true;
    237     assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize);
    238 
    239     if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) {
    240       if (!IvarD->getSynthesize())
    241         IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), 0,
    242                                  D->getDeclContext());
    243     }
    244 
    245     if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) {
    246       if (MD->isPropertyAccessor() &&
    247           !hasUserDefined(MD, cast<ObjCImplDecl>(D->getDeclContext())))
    248         IndexCtx.handleSynthesizedObjCMethod(MD, D->getLocation(),
    249                                              D->getLexicalDeclContext());
    250     }
    251     if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) {
    252       if (MD->isPropertyAccessor() &&
    253           !hasUserDefined(MD, cast<ObjCImplDecl>(D->getDeclContext())))
    254         IndexCtx.handleSynthesizedObjCMethod(MD, D->getLocation(),
    255                                              D->getLexicalDeclContext());
    256     }
    257     return true;
    258   }
    259 
    260   bool VisitNamespaceDecl(const NamespaceDecl *D) {
    261     IndexCtx.handleNamespace(D);
    262     IndexCtx.indexDeclContext(D);
    263     return true;
    264   }
    265 
    266   bool VisitUsingDecl(const UsingDecl *D) {
    267     // FIXME: Parent for the following is CXIdxEntity_Unexposed with no USR,
    268     // we should do better.
    269 
    270     IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
    271     for (UsingDecl::shadow_iterator
    272            I = D->shadow_begin(), E = D->shadow_end(); I != E; ++I) {
    273       IndexCtx.handleReference((*I)->getUnderlyingDecl(), D->getLocation(),
    274                                D, D->getLexicalDeclContext());
    275     }
    276     return true;
    277   }
    278 
    279   bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
    280     // FIXME: Parent for the following is CXIdxEntity_Unexposed with no USR,
    281     // we should do better.
    282 
    283     IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
    284     IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(),
    285                              D->getLocation(), D, D->getLexicalDeclContext());
    286     return true;
    287   }
    288 
    289   bool VisitClassTemplateDecl(const ClassTemplateDecl *D) {
    290     IndexCtx.handleClassTemplate(D);
    291     if (D->isThisDeclarationADefinition())
    292       IndexCtx.indexDeclContext(D->getTemplatedDecl());
    293     return true;
    294   }
    295 
    296   bool VisitClassTemplateSpecializationDecl(const
    297                                            ClassTemplateSpecializationDecl *D) {
    298     // FIXME: Notify subsequent callbacks if info comes from implicit
    299     // instantiation.
    300     if (D->isThisDeclarationADefinition() &&
    301         (IndexCtx.shouldIndexImplicitTemplateInsts() ||
    302          !IndexCtx.isTemplateImplicitInstantiation(D)))
    303       IndexCtx.indexTagDecl(D);
    304     return true;
    305   }
    306 
    307   bool VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
    308     IndexCtx.handleFunctionTemplate(D);
    309     FunctionDecl *FD = D->getTemplatedDecl();
    310     handleDeclarator(FD, D);
    311     if (FD->isThisDeclarationADefinition()) {
    312       const Stmt *Body = FD->getBody();
    313       if (Body) {
    314         IndexCtx.indexBody(Body, D, FD);
    315       }
    316     }
    317     return true;
    318   }
    319 
    320   bool VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) {
    321     IndexCtx.handleTypeAliasTemplate(D);
    322     IndexCtx.indexTypeSourceInfo(D->getTemplatedDecl()->getTypeSourceInfo(), D);
    323     return true;
    324   }
    325 
    326   bool VisitImportDecl(const ImportDecl *D) {
    327     IndexCtx.importedModule(D);
    328     return true;
    329   }
    330 };
    331 
    332 } // anonymous namespace
    333 
    334 void IndexingContext::indexDecl(const Decl *D) {
    335   if (D->isImplicit() && shouldIgnoreIfImplicit(D))
    336     return;
    337 
    338   bool Handled = IndexingDeclVisitor(*this).Visit(D);
    339   if (!Handled && isa<DeclContext>(D))
    340     indexDeclContext(cast<DeclContext>(D));
    341 }
    342 
    343 void IndexingContext::indexDeclContext(const DeclContext *DC) {
    344   for (DeclContext::decl_iterator
    345          I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) {
    346     indexDecl(*I);
    347   }
    348 }
    349 
    350 void IndexingContext::indexTopLevelDecl(const Decl *D) {
    351   if (isNotFromSourceFile(D->getLocation()))
    352     return;
    353 
    354   if (isa<ObjCMethodDecl>(D))
    355     return; // Wait for the objc container.
    356 
    357   indexDecl(D);
    358 }
    359 
    360 void IndexingContext::indexDeclGroupRef(DeclGroupRef DG) {
    361   for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
    362     indexTopLevelDecl(*I);
    363 }
    364 
    365 void IndexingContext::indexTUDeclsInObjCContainer() {
    366   while (!TUDeclsInObjCContainer.empty()) {
    367     DeclGroupRef DG = TUDeclsInObjCContainer.front();
    368     TUDeclsInObjCContainer.pop_front();
    369     indexDeclGroupRef(DG);
    370   }
    371 }
    372