Home | History | Annotate | Download | only in Index
      1 //===- IndexingAction.cpp - Frontend index action -------------------------===//
      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 "clang/Index/IndexingAction.h"
     11 #include "clang/Index/IndexDataConsumer.h"
     12 #include "IndexingContext.h"
     13 #include "clang/Frontend/FrontendAction.h"
     14 #include "clang/Frontend/MultiplexConsumer.h"
     15 #include "clang/Lex/Preprocessor.h"
     16 
     17 using namespace clang;
     18 using namespace clang::index;
     19 
     20 void IndexDataConsumer::_anchor() {}
     21 
     22 bool IndexDataConsumer::handleDeclOccurence(const Decl *D, SymbolRoleSet Roles,
     23                                             ArrayRef<SymbolRelation> Relations,
     24                                             FileID FID, unsigned Offset,
     25                                             ASTNodeInfo ASTNode) {
     26   return true;
     27 }
     28 
     29 bool IndexDataConsumer::handleMacroOccurence(const IdentifierInfo *Name,
     30                                              const MacroInfo *MI, SymbolRoleSet Roles,
     31                                              FileID FID, unsigned Offset) {
     32   return true;
     33 }
     34 
     35 bool IndexDataConsumer::handleModuleOccurence(const ImportDecl *ImportD,
     36                                               SymbolRoleSet Roles,
     37                                               FileID FID, unsigned Offset) {
     38   return true;
     39 }
     40 
     41 namespace {
     42 
     43 class IndexASTConsumer : public ASTConsumer {
     44   IndexingContext &IndexCtx;
     45 
     46 public:
     47   IndexASTConsumer(IndexingContext &IndexCtx)
     48     : IndexCtx(IndexCtx) {}
     49 
     50 protected:
     51   void Initialize(ASTContext &Context) override {
     52     IndexCtx.setASTContext(Context);
     53     IndexCtx.getDataConsumer().initialize(Context);
     54   }
     55 
     56   bool HandleTopLevelDecl(DeclGroupRef DG) override {
     57     return IndexCtx.indexDeclGroupRef(DG);
     58   }
     59 
     60   void HandleInterestingDecl(DeclGroupRef DG) override {
     61     // Ignore deserialized decls.
     62   }
     63 
     64   void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) override {
     65     IndexCtx.indexDeclGroupRef(DG);
     66   }
     67 
     68   void HandleTranslationUnit(ASTContext &Ctx) override {
     69   }
     70 };
     71 
     72 class IndexActionBase {
     73 protected:
     74   std::shared_ptr<IndexDataConsumer> DataConsumer;
     75   IndexingContext IndexCtx;
     76 
     77   IndexActionBase(std::shared_ptr<IndexDataConsumer> dataConsumer,
     78                   IndexingOptions Opts)
     79     : DataConsumer(std::move(dataConsumer)),
     80       IndexCtx(Opts, *DataConsumer) {}
     81 
     82   std::unique_ptr<IndexASTConsumer> createIndexASTConsumer() {
     83     return llvm::make_unique<IndexASTConsumer>(IndexCtx);
     84   }
     85 
     86   void finish() {
     87     DataConsumer->finish();
     88   }
     89 };
     90 
     91 class IndexAction : public ASTFrontendAction, IndexActionBase {
     92 public:
     93   IndexAction(std::shared_ptr<IndexDataConsumer> DataConsumer,
     94               IndexingOptions Opts)
     95     : IndexActionBase(std::move(DataConsumer), Opts) {}
     96 
     97 protected:
     98   std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
     99                                                  StringRef InFile) override {
    100     return createIndexASTConsumer();
    101   }
    102 
    103   void EndSourceFileAction() override {
    104     FrontendAction::EndSourceFileAction();
    105     finish();
    106   }
    107 };
    108 
    109 class WrappingIndexAction : public WrapperFrontendAction, IndexActionBase {
    110   bool IndexActionFailed = false;
    111 
    112 public:
    113   WrappingIndexAction(std::unique_ptr<FrontendAction> WrappedAction,
    114                       std::shared_ptr<IndexDataConsumer> DataConsumer,
    115                       IndexingOptions Opts)
    116     : WrapperFrontendAction(std::move(WrappedAction)),
    117       IndexActionBase(std::move(DataConsumer), Opts) {}
    118 
    119 protected:
    120   std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
    121                                                  StringRef InFile) override;
    122   void EndSourceFileAction() override;
    123 };
    124 
    125 } // anonymous namespace
    126 
    127 void WrappingIndexAction::EndSourceFileAction() {
    128   // Invoke wrapped action's method.
    129   WrapperFrontendAction::EndSourceFileAction();
    130   if (!IndexActionFailed)
    131     finish();
    132 }
    133 
    134 std::unique_ptr<ASTConsumer>
    135 WrappingIndexAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
    136   auto OtherConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile);
    137   if (!OtherConsumer) {
    138     IndexActionFailed = true;
    139     return nullptr;
    140   }
    141 
    142   std::vector<std::unique_ptr<ASTConsumer>> Consumers;
    143   Consumers.push_back(std::move(OtherConsumer));
    144   Consumers.push_back(createIndexASTConsumer());
    145   return llvm::make_unique<MultiplexConsumer>(std::move(Consumers));
    146 }
    147 
    148 std::unique_ptr<FrontendAction>
    149 index::createIndexingAction(std::shared_ptr<IndexDataConsumer> DataConsumer,
    150                             IndexingOptions Opts,
    151                             std::unique_ptr<FrontendAction> WrappedAction) {
    152   if (WrappedAction)
    153     return llvm::make_unique<WrappingIndexAction>(std::move(WrappedAction),
    154                                                   std::move(DataConsumer),
    155                                                   Opts);
    156   return llvm::make_unique<IndexAction>(std::move(DataConsumer), Opts);
    157 }
    158 
    159 
    160 static bool topLevelDeclVisitor(void *context, const Decl *D) {
    161   IndexingContext &IndexCtx = *static_cast<IndexingContext*>(context);
    162   return IndexCtx.indexTopLevelDecl(D);
    163 }
    164 
    165 static void indexTranslationUnit(ASTUnit &Unit, IndexingContext &IndexCtx) {
    166   Unit.visitLocalTopLevelDecls(&IndexCtx, topLevelDeclVisitor);
    167 }
    168 
    169 void index::indexASTUnit(ASTUnit &Unit,
    170                          std::shared_ptr<IndexDataConsumer> DataConsumer,
    171                          IndexingOptions Opts) {
    172   IndexingContext IndexCtx(Opts, *DataConsumer);
    173   IndexCtx.setASTContext(Unit.getASTContext());
    174   DataConsumer->initialize(Unit.getASTContext());
    175   indexTranslationUnit(Unit, IndexCtx);
    176 }
    177