Home | History | Annotate | Download | only in libclang
      1 //===- CursorVisitor.h - CursorVisitor interface ----------------*- C++ -*-===//
      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 #ifndef LLVM_CLANG_TOOLS_LIBCLANG_CURSORVISITOR_H
     11 #define LLVM_CLANG_TOOLS_LIBCLANG_CURSORVISITOR_H
     12 
     13 #include "CXCursor.h"
     14 #include "CXTranslationUnit.h"
     15 #include "Index_Internal.h"
     16 #include "clang/AST/DeclVisitor.h"
     17 #include "clang/AST/TypeLocVisitor.h"
     18 
     19 namespace clang {
     20   class PreprocessingRecord;
     21   class ASTUnit;
     22 
     23 namespace cxcursor {
     24 
     25 class VisitorJob {
     26 public:
     27   enum Kind { DeclVisitKind, StmtVisitKind, MemberExprPartsKind,
     28               TypeLocVisitKind, OverloadExprPartsKind,
     29               DeclRefExprPartsKind, LabelRefVisitKind,
     30               ExplicitTemplateArgsVisitKind,
     31               NestedNameSpecifierLocVisitKind,
     32               DeclarationNameInfoVisitKind,
     33               MemberRefVisitKind, SizeOfPackExprPartsKind,
     34               LambdaExprPartsKind, PostChildrenVisitKind };
     35 protected:
     36   const void *data[3];
     37   CXCursor parent;
     38   Kind K;
     39   VisitorJob(CXCursor C, Kind k, const void *d1, const void *d2 = nullptr,
     40              const void *d3 = nullptr)
     41     : parent(C), K(k) {
     42     data[0] = d1;
     43     data[1] = d2;
     44     data[2] = d3;
     45   }
     46 public:
     47   Kind getKind() const { return K; }
     48   const CXCursor &getParent() const { return parent; }
     49 };
     50 
     51 typedef SmallVector<VisitorJob, 10> VisitorWorkList;
     52 
     53 // Cursor visitor.
     54 class CursorVisitor : public DeclVisitor<CursorVisitor, bool>,
     55                       public TypeLocVisitor<CursorVisitor, bool>
     56 {
     57 public:
     58   /// \brief Callback called after child nodes of a cursor have been visited.
     59   /// Return true to break visitation or false to continue.
     60   typedef bool (*PostChildrenVisitorTy)(CXCursor cursor,
     61                                         CXClientData client_data);
     62 
     63 private:
     64   /// \brief The translation unit we are traversing.
     65   CXTranslationUnit TU;
     66   ASTUnit *AU;
     67 
     68   /// \brief The parent cursor whose children we are traversing.
     69   CXCursor Parent;
     70 
     71   /// \brief The declaration that serves at the parent of any statement or
     72   /// expression nodes.
     73   const Decl *StmtParent;
     74 
     75   /// \brief The visitor function.
     76   CXCursorVisitor Visitor;
     77 
     78   PostChildrenVisitorTy PostChildrenVisitor;
     79 
     80   /// \brief The opaque client data, to be passed along to the visitor.
     81   CXClientData ClientData;
     82 
     83   /// \brief Whether we should visit the preprocessing record entries last,
     84   /// after visiting other declarations.
     85   bool VisitPreprocessorLast;
     86 
     87   /// \brief Whether we should visit declarations or preprocessing record
     88   /// entries that are #included inside the \arg RegionOfInterest.
     89   bool VisitIncludedEntities;
     90 
     91   /// \brief When valid, a source range to which the cursor should restrict
     92   /// its search.
     93   SourceRange RegionOfInterest;
     94 
     95   /// \brief Whether we should only visit declarations and not preprocessing
     96   /// record entries.
     97   bool VisitDeclsOnly;
     98 
     99   // FIXME: Eventually remove.  This part of a hack to support proper
    100   // iteration over all Decls contained lexically within an ObjC container.
    101   DeclContext::decl_iterator *DI_current;
    102   DeclContext::decl_iterator DE_current;
    103   SmallVectorImpl<Decl *>::iterator *FileDI_current;
    104   SmallVectorImpl<Decl *>::iterator FileDE_current;
    105 
    106   // Cache of pre-allocated worklists for data-recursion walk of Stmts.
    107   SmallVector<VisitorWorkList*, 5> WorkListFreeList;
    108   SmallVector<VisitorWorkList*, 5> WorkListCache;
    109 
    110   using DeclVisitor<CursorVisitor, bool>::Visit;
    111   using TypeLocVisitor<CursorVisitor, bool>::Visit;
    112 
    113   /// \brief Determine whether this particular source range comes before, comes
    114   /// after, or overlaps the region of interest.
    115   ///
    116   /// \param R a half-open source range retrieved from the abstract syntax tree.
    117   RangeComparisonResult CompareRegionOfInterest(SourceRange R);
    118 
    119   bool visitDeclsFromFileRegion(FileID File, unsigned Offset, unsigned Length);
    120 
    121   class SetParentRAII {
    122     CXCursor &Parent;
    123     const Decl *&StmtParent;
    124     CXCursor OldParent;
    125 
    126   public:
    127     SetParentRAII(CXCursor &Parent, const Decl *&StmtParent,
    128                   CXCursor NewParent)
    129       : Parent(Parent), StmtParent(StmtParent), OldParent(Parent)
    130     {
    131       Parent = NewParent;
    132       if (clang_isDeclaration(Parent.kind))
    133         StmtParent = getCursorDecl(Parent);
    134     }
    135 
    136     ~SetParentRAII() {
    137       Parent = OldParent;
    138       if (clang_isDeclaration(Parent.kind))
    139         StmtParent = getCursorDecl(Parent);
    140     }
    141   };
    142 
    143 public:
    144   CursorVisitor(CXTranslationUnit TU, CXCursorVisitor Visitor,
    145                 CXClientData ClientData,
    146                 bool VisitPreprocessorLast,
    147                 bool VisitIncludedPreprocessingEntries = false,
    148                 SourceRange RegionOfInterest = SourceRange(),
    149                 bool VisitDeclsOnly = false,
    150                 PostChildrenVisitorTy PostChildrenVisitor = nullptr)
    151     : TU(TU), AU(cxtu::getASTUnit(TU)),
    152       Visitor(Visitor), PostChildrenVisitor(PostChildrenVisitor),
    153       ClientData(ClientData),
    154       VisitPreprocessorLast(VisitPreprocessorLast),
    155       VisitIncludedEntities(VisitIncludedPreprocessingEntries),
    156       RegionOfInterest(RegionOfInterest),
    157       VisitDeclsOnly(VisitDeclsOnly),
    158       DI_current(nullptr), FileDI_current(nullptr)
    159   {
    160     Parent.kind = CXCursor_NoDeclFound;
    161     Parent.data[0] = nullptr;
    162     Parent.data[1] = nullptr;
    163     Parent.data[2] = nullptr;
    164     StmtParent = nullptr;
    165   }
    166 
    167   ~CursorVisitor() {
    168     // Free the pre-allocated worklists for data-recursion.
    169     for (SmallVectorImpl<VisitorWorkList*>::iterator
    170           I = WorkListCache.begin(), E = WorkListCache.end(); I != E; ++I) {
    171       delete *I;
    172     }
    173   }
    174 
    175   ASTUnit *getASTUnit() const { return AU; }
    176   CXTranslationUnit getTU() const { return TU; }
    177 
    178   bool Visit(CXCursor Cursor, bool CheckedRegionOfInterest = false);
    179 
    180   /// \brief Visit declarations and preprocessed entities for the file region
    181   /// designated by \see RegionOfInterest.
    182   bool visitFileRegion();
    183 
    184   bool visitPreprocessedEntitiesInRegion();
    185 
    186   bool shouldVisitIncludedEntities() const {
    187     return VisitIncludedEntities;
    188   }
    189 
    190   template<typename InputIterator>
    191   bool visitPreprocessedEntities(InputIterator First, InputIterator Last,
    192                                  PreprocessingRecord &PPRec,
    193                                  FileID FID = FileID());
    194 
    195   bool VisitChildren(CXCursor Parent);
    196 
    197   // Declaration visitors
    198   bool VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D);
    199   bool VisitTypeAliasDecl(TypeAliasDecl *D);
    200   bool VisitAttributes(Decl *D);
    201   bool VisitBlockDecl(BlockDecl *B);
    202   bool VisitCXXRecordDecl(CXXRecordDecl *D);
    203   Optional<bool> shouldVisitCursor(CXCursor C);
    204   bool VisitDeclContext(DeclContext *DC);
    205   bool VisitTranslationUnitDecl(TranslationUnitDecl *D);
    206   bool VisitTypedefDecl(TypedefDecl *D);
    207   bool VisitTagDecl(TagDecl *D);
    208   bool VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *D);
    209   bool VisitClassTemplatePartialSpecializationDecl(
    210                                      ClassTemplatePartialSpecializationDecl *D);
    211   bool VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
    212   bool VisitEnumConstantDecl(EnumConstantDecl *D);
    213   bool VisitDeclaratorDecl(DeclaratorDecl *DD);
    214   bool VisitFunctionDecl(FunctionDecl *ND);
    215   bool VisitFieldDecl(FieldDecl *D);
    216   bool VisitVarDecl(VarDecl *);
    217   bool VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
    218   bool VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
    219   bool VisitClassTemplateDecl(ClassTemplateDecl *D);
    220   bool VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
    221   bool VisitObjCTypeParamDecl(ObjCTypeParamDecl *D);
    222   bool VisitObjCMethodDecl(ObjCMethodDecl *ND);
    223   bool VisitObjCContainerDecl(ObjCContainerDecl *D);
    224   bool VisitObjCCategoryDecl(ObjCCategoryDecl *ND);
    225   bool VisitObjCProtocolDecl(ObjCProtocolDecl *PID);
    226   bool VisitObjCPropertyDecl(ObjCPropertyDecl *PD);
    227   bool VisitObjCTypeParamList(ObjCTypeParamList *typeParamList);
    228   bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
    229   bool VisitObjCImplDecl(ObjCImplDecl *D);
    230   bool VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
    231   bool VisitObjCImplementationDecl(ObjCImplementationDecl *D);
    232   // FIXME: ObjCCompatibleAliasDecl requires aliased-class locations.
    233   bool VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PD);
    234   bool VisitLinkageSpecDecl(LinkageSpecDecl *D);
    235   bool VisitNamespaceDecl(NamespaceDecl *D);
    236   bool VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
    237   bool VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
    238   bool VisitUsingDecl(UsingDecl *D);
    239   bool VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
    240   bool VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
    241 
    242   // Name visitor
    243   bool VisitDeclarationNameInfo(DeclarationNameInfo Name);
    244   bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS, SourceRange Range);
    245   bool VisitNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
    246 
    247   // Template visitors
    248   bool VisitTemplateParameters(const TemplateParameterList *Params);
    249   bool VisitTemplateName(TemplateName Name, SourceLocation Loc);
    250   bool VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL);
    251 
    252   // Type visitors
    253 #define ABSTRACT_TYPELOC(CLASS, PARENT)
    254 #define TYPELOC(CLASS, PARENT) \
    255   bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc);
    256 #include "clang/AST/TypeLocNodes.def"
    257 
    258   bool VisitTagTypeLoc(TagTypeLoc TL);
    259   bool VisitArrayTypeLoc(ArrayTypeLoc TL);
    260   bool VisitFunctionTypeLoc(FunctionTypeLoc TL, bool SkipResultType = false);
    261 
    262   // Data-recursive visitor functions.
    263   bool IsInRegionOfInterest(CXCursor C);
    264   bool RunVisitorWorkList(VisitorWorkList &WL);
    265   void EnqueueWorkList(VisitorWorkList &WL, const Stmt *S);
    266   LLVM_ATTRIBUTE_NOINLINE bool Visit(const Stmt *S);
    267 };
    268 
    269 }
    270 }
    271 
    272 #endif
    273 
    274