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