1 //===- IndexingAction.cpp - Frontend index action -------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "clang/Index/IndexingAction.h"
11 #include "IndexingContext.h"
12 #include "clang/Frontend/CompilerInstance.h"
13 #include "clang/Frontend/FrontendAction.h"
14 #include "clang/Frontend/MultiplexConsumer.h"
15 #include "clang/Index/IndexDataConsumer.h"
16 #include "clang/Lex/Preprocessor.h"
17 #include "clang/Serialization/ASTReader.h"
19 using namespace clang;
20 using namespace clang::index;
22 void IndexDataConsumer::_anchor() {}
24 bool IndexDataConsumer::handleDeclOccurence(const Decl *D, SymbolRoleSet Roles,
25 ArrayRef<SymbolRelation> Relations,
26 FileID FID, unsigned Offset,
27 ASTNodeInfo ASTNode) {
31 bool IndexDataConsumer::handleMacroOccurence(const IdentifierInfo *Name,
32 const MacroInfo *MI, SymbolRoleSet Roles,
33 FileID FID, unsigned Offset) {
37 bool IndexDataConsumer::handleModuleOccurence(const ImportDecl *ImportD,
39 FileID FID, unsigned Offset) {
45 class IndexASTConsumer : public ASTConsumer {
46 std::shared_ptr<Preprocessor> PP;
47 IndexingContext &IndexCtx;
50 IndexASTConsumer(std::shared_ptr<Preprocessor> PP, IndexingContext &IndexCtx)
51 : PP(std::move(PP)), IndexCtx(IndexCtx) {}
54 void Initialize(ASTContext &Context) override {
55 IndexCtx.setASTContext(Context);
56 IndexCtx.getDataConsumer().initialize(Context);
57 IndexCtx.getDataConsumer().setPreprocessor(PP);
60 bool HandleTopLevelDecl(DeclGroupRef DG) override {
61 return IndexCtx.indexDeclGroupRef(DG);
64 void HandleInterestingDecl(DeclGroupRef DG) override {
65 // Ignore deserialized decls.
68 void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) override {
69 IndexCtx.indexDeclGroupRef(DG);
72 void HandleTranslationUnit(ASTContext &Ctx) override {
76 class IndexActionBase {
78 std::shared_ptr<IndexDataConsumer> DataConsumer;
79 IndexingContext IndexCtx;
81 IndexActionBase(std::shared_ptr<IndexDataConsumer> dataConsumer,
83 : DataConsumer(std::move(dataConsumer)),
84 IndexCtx(Opts, *DataConsumer) {}
86 std::unique_ptr<IndexASTConsumer>
87 createIndexASTConsumer(CompilerInstance &CI) {
88 return llvm::make_unique<IndexASTConsumer>(CI.getPreprocessorPtr(),
93 DataConsumer->finish();
97 class IndexAction : public ASTFrontendAction, IndexActionBase {
99 IndexAction(std::shared_ptr<IndexDataConsumer> DataConsumer,
100 IndexingOptions Opts)
101 : IndexActionBase(std::move(DataConsumer), Opts) {}
104 std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
105 StringRef InFile) override {
106 return createIndexASTConsumer(CI);
109 void EndSourceFileAction() override {
110 FrontendAction::EndSourceFileAction();
115 class WrappingIndexAction : public WrapperFrontendAction, IndexActionBase {
116 bool IndexActionFailed = false;
119 WrappingIndexAction(std::unique_ptr<FrontendAction> WrappedAction,
120 std::shared_ptr<IndexDataConsumer> DataConsumer,
121 IndexingOptions Opts)
122 : WrapperFrontendAction(std::move(WrappedAction)),
123 IndexActionBase(std::move(DataConsumer), Opts) {}
126 std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
127 StringRef InFile) override;
128 void EndSourceFileAction() override;
131 } // anonymous namespace
133 void WrappingIndexAction::EndSourceFileAction() {
134 // Invoke wrapped action's method.
135 WrapperFrontendAction::EndSourceFileAction();
136 if (!IndexActionFailed)
140 std::unique_ptr<ASTConsumer>
141 WrappingIndexAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
142 auto OtherConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile);
143 if (!OtherConsumer) {
144 IndexActionFailed = true;
148 std::vector<std::unique_ptr<ASTConsumer>> Consumers;
149 Consumers.push_back(std::move(OtherConsumer));
150 Consumers.push_back(createIndexASTConsumer(CI));
151 return llvm::make_unique<MultiplexConsumer>(std::move(Consumers));
154 std::unique_ptr<FrontendAction>
155 index::createIndexingAction(std::shared_ptr<IndexDataConsumer> DataConsumer,
156 IndexingOptions Opts,
157 std::unique_ptr<FrontendAction> WrappedAction) {
159 return llvm::make_unique<WrappingIndexAction>(std::move(WrappedAction),
160 std::move(DataConsumer),
162 return llvm::make_unique<IndexAction>(std::move(DataConsumer), Opts);
166 static bool topLevelDeclVisitor(void *context, const Decl *D) {
167 IndexingContext &IndexCtx = *static_cast<IndexingContext*>(context);
168 return IndexCtx.indexTopLevelDecl(D);
171 static void indexTranslationUnit(ASTUnit &Unit, IndexingContext &IndexCtx) {
172 Unit.visitLocalTopLevelDecls(&IndexCtx, topLevelDeclVisitor);
175 void index::indexASTUnit(ASTUnit &Unit,
176 std::shared_ptr<IndexDataConsumer> DataConsumer,
177 IndexingOptions Opts) {
178 IndexingContext IndexCtx(Opts, *DataConsumer);
179 IndexCtx.setASTContext(Unit.getASTContext());
180 DataConsumer->initialize(Unit.getASTContext());
181 DataConsumer->setPreprocessor(Unit.getPreprocessorPtr());
182 indexTranslationUnit(Unit, IndexCtx);
183 DataConsumer->finish();
186 void index::indexTopLevelDecls(ASTContext &Ctx, ArrayRef<const Decl *> Decls,
187 std::shared_ptr<IndexDataConsumer> DataConsumer,
188 IndexingOptions Opts) {
189 IndexingContext IndexCtx(Opts, *DataConsumer);
190 IndexCtx.setASTContext(Ctx);
192 DataConsumer->initialize(Ctx);
193 for (const Decl *D : Decls)
194 IndexCtx.indexTopLevelDecl(D);
195 DataConsumer->finish();
198 void index::indexModuleFile(serialization::ModuleFile &Mod,
200 std::shared_ptr<IndexDataConsumer> DataConsumer,
201 IndexingOptions Opts) {
202 ASTContext &Ctx = Reader.getContext();
203 IndexingContext IndexCtx(Opts, *DataConsumer);
204 IndexCtx.setASTContext(Ctx);
205 DataConsumer->initialize(Ctx);
207 for (const Decl *D : Reader.getModuleFileLevelDecls(Mod)) {
208 IndexCtx.indexTopLevelDecl(D);
210 DataConsumer->finish();