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 "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 #include "clang/Serialization/ASTReader.h"
18 using namespace clang;
19 using namespace clang::index;
21 void IndexDataConsumer::_anchor() {}
23 bool IndexDataConsumer::handleDeclOccurence(const Decl *D, SymbolRoleSet Roles,
24 ArrayRef<SymbolRelation> Relations,
25 FileID FID, unsigned Offset,
26 ASTNodeInfo ASTNode) {
30 bool IndexDataConsumer::handleMacroOccurence(const IdentifierInfo *Name,
31 const MacroInfo *MI, SymbolRoleSet Roles,
32 FileID FID, unsigned Offset) {
36 bool IndexDataConsumer::handleModuleOccurence(const ImportDecl *ImportD,
38 FileID FID, unsigned Offset) {
44 class IndexASTConsumer : public ASTConsumer {
45 IndexingContext &IndexCtx;
48 IndexASTConsumer(IndexingContext &IndexCtx)
49 : IndexCtx(IndexCtx) {}
52 void Initialize(ASTContext &Context) override {
53 IndexCtx.setASTContext(Context);
54 IndexCtx.getDataConsumer().initialize(Context);
57 bool HandleTopLevelDecl(DeclGroupRef DG) override {
58 return IndexCtx.indexDeclGroupRef(DG);
61 void HandleInterestingDecl(DeclGroupRef DG) override {
62 // Ignore deserialized decls.
65 void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) override {
66 IndexCtx.indexDeclGroupRef(DG);
69 void HandleTranslationUnit(ASTContext &Ctx) override {
73 class IndexActionBase {
75 std::shared_ptr<IndexDataConsumer> DataConsumer;
76 IndexingContext IndexCtx;
78 IndexActionBase(std::shared_ptr<IndexDataConsumer> dataConsumer,
80 : DataConsumer(std::move(dataConsumer)),
81 IndexCtx(Opts, *DataConsumer) {}
83 std::unique_ptr<IndexASTConsumer> createIndexASTConsumer() {
84 return llvm::make_unique<IndexASTConsumer>(IndexCtx);
88 DataConsumer->finish();
92 class IndexAction : public ASTFrontendAction, IndexActionBase {
94 IndexAction(std::shared_ptr<IndexDataConsumer> DataConsumer,
96 : IndexActionBase(std::move(DataConsumer), Opts) {}
99 std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
100 StringRef InFile) override {
101 return createIndexASTConsumer();
104 void EndSourceFileAction() override {
105 FrontendAction::EndSourceFileAction();
110 class WrappingIndexAction : public WrapperFrontendAction, IndexActionBase {
111 bool IndexActionFailed = false;
114 WrappingIndexAction(std::unique_ptr<FrontendAction> WrappedAction,
115 std::shared_ptr<IndexDataConsumer> DataConsumer,
116 IndexingOptions Opts)
117 : WrapperFrontendAction(std::move(WrappedAction)),
118 IndexActionBase(std::move(DataConsumer), Opts) {}
121 std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
122 StringRef InFile) override;
123 void EndSourceFileAction() override;
126 } // anonymous namespace
128 void WrappingIndexAction::EndSourceFileAction() {
129 // Invoke wrapped action's method.
130 WrapperFrontendAction::EndSourceFileAction();
131 if (!IndexActionFailed)
135 std::unique_ptr<ASTConsumer>
136 WrappingIndexAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
137 auto OtherConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile);
138 if (!OtherConsumer) {
139 IndexActionFailed = true;
143 std::vector<std::unique_ptr<ASTConsumer>> Consumers;
144 Consumers.push_back(std::move(OtherConsumer));
145 Consumers.push_back(createIndexASTConsumer());
146 return llvm::make_unique<MultiplexConsumer>(std::move(Consumers));
149 std::unique_ptr<FrontendAction>
150 index::createIndexingAction(std::shared_ptr<IndexDataConsumer> DataConsumer,
151 IndexingOptions Opts,
152 std::unique_ptr<FrontendAction> WrappedAction) {
154 return llvm::make_unique<WrappingIndexAction>(std::move(WrappedAction),
155 std::move(DataConsumer),
157 return llvm::make_unique<IndexAction>(std::move(DataConsumer), Opts);
161 static bool topLevelDeclVisitor(void *context, const Decl *D) {
162 IndexingContext &IndexCtx = *static_cast<IndexingContext*>(context);
163 return IndexCtx.indexTopLevelDecl(D);
166 static void indexTranslationUnit(ASTUnit &Unit, IndexingContext &IndexCtx) {
167 Unit.visitLocalTopLevelDecls(&IndexCtx, topLevelDeclVisitor);
170 void index::indexASTUnit(ASTUnit &Unit,
171 std::shared_ptr<IndexDataConsumer> DataConsumer,
172 IndexingOptions Opts) {
173 IndexingContext IndexCtx(Opts, *DataConsumer);
174 IndexCtx.setASTContext(Unit.getASTContext());
175 DataConsumer->initialize(Unit.getASTContext());
176 indexTranslationUnit(Unit, IndexCtx);
177 DataConsumer->finish();
180 void index::indexModuleFile(serialization::ModuleFile &Mod,
182 std::shared_ptr<IndexDataConsumer> DataConsumer,
183 IndexingOptions Opts) {
184 ASTContext &Ctx = Reader.getContext();
185 IndexingContext IndexCtx(Opts, *DataConsumer);
186 IndexCtx.setASTContext(Ctx);
187 DataConsumer->initialize(Ctx);
189 for (const Decl *D :Reader.getModuleFileLevelDecls(Mod)) {
190 IndexCtx.indexTopLevelDecl(D);
192 DataConsumer->finish();