• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
_anchor()20 void IndexDataConsumer::_anchor() {}
21 
handleDeclOccurence(const Decl * D,SymbolRoleSet Roles,ArrayRef<SymbolRelation> Relations,FileID FID,unsigned Offset,ASTNodeInfo ASTNode)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 
handleMacroOccurence(const IdentifierInfo * Name,const MacroInfo * MI,SymbolRoleSet Roles,FileID FID,unsigned Offset)29 bool IndexDataConsumer::handleMacroOccurence(const IdentifierInfo *Name,
30                                              const MacroInfo *MI, SymbolRoleSet Roles,
31                                              FileID FID, unsigned Offset) {
32   return true;
33 }
34 
handleModuleOccurence(const ImportDecl * ImportD,SymbolRoleSet Roles,FileID FID,unsigned Offset)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:
IndexASTConsumer(IndexingContext & IndexCtx)47   IndexASTConsumer(IndexingContext &IndexCtx)
48     : IndexCtx(IndexCtx) {}
49 
50 protected:
Initialize(ASTContext & Context)51   void Initialize(ASTContext &Context) override {
52     IndexCtx.setASTContext(Context);
53     IndexCtx.getDataConsumer().initialize(Context);
54   }
55 
HandleTopLevelDecl(DeclGroupRef DG)56   bool HandleTopLevelDecl(DeclGroupRef DG) override {
57     return IndexCtx.indexDeclGroupRef(DG);
58   }
59 
HandleInterestingDecl(DeclGroupRef DG)60   void HandleInterestingDecl(DeclGroupRef DG) override {
61     // Ignore deserialized decls.
62   }
63 
HandleTopLevelDeclInObjCContainer(DeclGroupRef DG)64   void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) override {
65     IndexCtx.indexDeclGroupRef(DG);
66   }
67 
HandleTranslationUnit(ASTContext & Ctx)68   void HandleTranslationUnit(ASTContext &Ctx) override {
69   }
70 };
71 
72 class IndexActionBase {
73 protected:
74   std::shared_ptr<IndexDataConsumer> DataConsumer;
75   IndexingContext IndexCtx;
76 
IndexActionBase(std::shared_ptr<IndexDataConsumer> dataConsumer,IndexingOptions Opts)77   IndexActionBase(std::shared_ptr<IndexDataConsumer> dataConsumer,
78                   IndexingOptions Opts)
79     : DataConsumer(std::move(dataConsumer)),
80       IndexCtx(Opts, *DataConsumer) {}
81 
createIndexASTConsumer()82   std::unique_ptr<IndexASTConsumer> createIndexASTConsumer() {
83     return llvm::make_unique<IndexASTConsumer>(IndexCtx);
84   }
85 
finish()86   void finish() {
87     DataConsumer->finish();
88   }
89 };
90 
91 class IndexAction : public ASTFrontendAction, IndexActionBase {
92 public:
IndexAction(std::shared_ptr<IndexDataConsumer> DataConsumer,IndexingOptions Opts)93   IndexAction(std::shared_ptr<IndexDataConsumer> DataConsumer,
94               IndexingOptions Opts)
95     : IndexActionBase(std::move(DataConsumer), Opts) {}
96 
97 protected:
CreateASTConsumer(CompilerInstance & CI,StringRef InFile)98   std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
99                                                  StringRef InFile) override {
100     return createIndexASTConsumer();
101   }
102 
EndSourceFileAction()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:
WrappingIndexAction(std::unique_ptr<FrontendAction> WrappedAction,std::shared_ptr<IndexDataConsumer> DataConsumer,IndexingOptions Opts)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 
EndSourceFileAction()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>
CreateASTConsumer(CompilerInstance & CI,StringRef InFile)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>
createIndexingAction(std::shared_ptr<IndexDataConsumer> DataConsumer,IndexingOptions Opts,std::unique_ptr<FrontendAction> WrappedAction)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 
topLevelDeclVisitor(void * context,const Decl * D)160 static bool topLevelDeclVisitor(void *context, const Decl *D) {
161   IndexingContext &IndexCtx = *static_cast<IndexingContext*>(context);
162   return IndexCtx.indexTopLevelDecl(D);
163 }
164 
indexTranslationUnit(ASTUnit & Unit,IndexingContext & IndexCtx)165 static void indexTranslationUnit(ASTUnit &Unit, IndexingContext &IndexCtx) {
166   Unit.visitLocalTopLevelDecls(&IndexCtx, topLevelDeclVisitor);
167 }
168 
indexASTUnit(ASTUnit & Unit,std::shared_ptr<IndexDataConsumer> DataConsumer,IndexingOptions Opts)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