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"
17 using namespace clang;
18 using namespace clang::index;
20 void IndexDataConsumer::_anchor() {}
22 bool IndexDataConsumer::handleDeclOccurence(const Decl *D, SymbolRoleSet Roles,
23 ArrayRef<SymbolRelation> Relations,
24 FileID FID, unsigned Offset,
25 ASTNodeInfo ASTNode) {
29 bool IndexDataConsumer::handleMacroOccurence(const IdentifierInfo *Name,
30 const MacroInfo *MI, SymbolRoleSet Roles,
31 FileID FID, unsigned Offset) {
35 bool IndexDataConsumer::handleModuleOccurence(const ImportDecl *ImportD,
37 FileID FID, unsigned Offset) {
43 class IndexASTConsumer : public ASTConsumer {
44 IndexingContext &IndexCtx;
47 IndexASTConsumer(IndexingContext &IndexCtx)
48 : IndexCtx(IndexCtx) {}
51 void Initialize(ASTContext &Context) override {
52 IndexCtx.setASTContext(Context);
53 IndexCtx.getDataConsumer().initialize(Context);
56 bool HandleTopLevelDecl(DeclGroupRef DG) override {
57 return IndexCtx.indexDeclGroupRef(DG);
60 void HandleInterestingDecl(DeclGroupRef DG) override {
61 // Ignore deserialized decls.
64 void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) override {
65 IndexCtx.indexDeclGroupRef(DG);
68 void HandleTranslationUnit(ASTContext &Ctx) override {
72 class IndexActionBase {
74 std::shared_ptr<IndexDataConsumer> DataConsumer;
75 IndexingContext IndexCtx;
77 IndexActionBase(std::shared_ptr<IndexDataConsumer> dataConsumer,
79 : DataConsumer(std::move(dataConsumer)),
80 IndexCtx(Opts, *DataConsumer) {}
82 std::unique_ptr<IndexASTConsumer> createIndexASTConsumer() {
83 return llvm::make_unique<IndexASTConsumer>(IndexCtx);
87 DataConsumer->finish();
91 class IndexAction : public ASTFrontendAction, IndexActionBase {
93 IndexAction(std::shared_ptr<IndexDataConsumer> DataConsumer,
95 : IndexActionBase(std::move(DataConsumer), Opts) {}
98 std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
99 StringRef InFile) override {
100 return createIndexASTConsumer();
103 void EndSourceFileAction() override {
104 FrontendAction::EndSourceFileAction();
109 class WrappingIndexAction : public WrapperFrontendAction, IndexActionBase {
110 bool IndexActionFailed = false;
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) {}
120 std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
121 StringRef InFile) override;
122 void EndSourceFileAction() override;
125 } // anonymous namespace
127 void WrappingIndexAction::EndSourceFileAction() {
128 // Invoke wrapped action's method.
129 WrapperFrontendAction::EndSourceFileAction();
130 if (!IndexActionFailed)
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;
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));
148 std::unique_ptr<FrontendAction>
149 index::createIndexingAction(std::shared_ptr<IndexDataConsumer> DataConsumer,
150 IndexingOptions Opts,
151 std::unique_ptr<FrontendAction> WrappedAction) {
153 return llvm::make_unique<WrappingIndexAction>(std::move(WrappedAction),
154 std::move(DataConsumer),
156 return llvm::make_unique<IndexAction>(std::move(DataConsumer), Opts);
160 static bool topLevelDeclVisitor(void *context, const Decl *D) {
161 IndexingContext &IndexCtx = *static_cast<IndexingContext*>(context);
162 return IndexCtx.indexTopLevelDecl(D);
165 static void indexTranslationUnit(ASTUnit &Unit, IndexingContext &IndexCtx) {
166 Unit.visitLocalTopLevelDecls(&IndexCtx, topLevelDeclVisitor);
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);