//===- IndexingAction.cpp - Frontend index action -------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "clang/Index/IndexingAction.h"
#include "clang/Index/IndexDataConsumer.h"
#include "IndexingContext.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Frontend/MultiplexConsumer.h"
#include "clang/Lex/Preprocessor.h"
using namespace clang;
using namespace clang::index;
void IndexDataConsumer::_anchor() {}
bool IndexDataConsumer::handleDeclOccurence(const Decl *D, SymbolRoleSet Roles,
ArrayRef<SymbolRelation> Relations,
FileID FID, unsigned Offset,
ASTNodeInfo ASTNode) {
return true;
}
bool IndexDataConsumer::handleMacroOccurence(const IdentifierInfo *Name,
const MacroInfo *MI, SymbolRoleSet Roles,
FileID FID, unsigned Offset) {
return true;
}
bool IndexDataConsumer::handleModuleOccurence(const ImportDecl *ImportD,
SymbolRoleSet Roles,
FileID FID, unsigned Offset) {
return true;
}
namespace {
class IndexASTConsumer : public ASTConsumer {
IndexingContext &IndexCtx;
public:
IndexASTConsumer(IndexingContext &IndexCtx)
: IndexCtx(IndexCtx) {}
protected:
void Initialize(ASTContext &Context) override {
IndexCtx.setASTContext(Context);
IndexCtx.getDataConsumer().initialize(Context);
}
bool HandleTopLevelDecl(DeclGroupRef DG) override {
return IndexCtx.indexDeclGroupRef(DG);
}
void HandleInterestingDecl(DeclGroupRef DG) override {
// Ignore deserialized decls.
}
void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) override {
IndexCtx.indexDeclGroupRef(DG);
}
void HandleTranslationUnit(ASTContext &Ctx) override {
}
};
class IndexActionBase {
protected:
std::shared_ptr<IndexDataConsumer> DataConsumer;
IndexingContext IndexCtx;
IndexActionBase(std::shared_ptr<IndexDataConsumer> dataConsumer,
IndexingOptions Opts)
: DataConsumer(std::move(dataConsumer)),
IndexCtx(Opts, *DataConsumer) {}
std::unique_ptr<IndexASTConsumer> createIndexASTConsumer() {
return llvm::make_unique<IndexASTConsumer>(IndexCtx);
}
void finish() {
DataConsumer->finish();
}
};
class IndexAction : public ASTFrontendAction, IndexActionBase {
public:
IndexAction(std::shared_ptr<IndexDataConsumer> DataConsumer,
IndexingOptions Opts)
: IndexActionBase(std::move(DataConsumer), Opts) {}
protected:
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
StringRef InFile) override {
return createIndexASTConsumer();
}
void EndSourceFileAction() override {
FrontendAction::EndSourceFileAction();
finish();
}
};
class WrappingIndexAction : public WrapperFrontendAction, IndexActionBase {
bool IndexActionFailed = false;
public:
WrappingIndexAction(std::unique_ptr<FrontendAction> WrappedAction,
std::shared_ptr<IndexDataConsumer> DataConsumer,
IndexingOptions Opts)
: WrapperFrontendAction(std::move(WrappedAction)),
IndexActionBase(std::move(DataConsumer), Opts) {}
protected:
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
StringRef InFile) override;
void EndSourceFileAction() override;
};
} // anonymous namespace
void WrappingIndexAction::EndSourceFileAction() {
// Invoke wrapped action's method.
WrapperFrontendAction::EndSourceFileAction();
if (!IndexActionFailed)
finish();
}
std::unique_ptr<ASTConsumer>
WrappingIndexAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
auto OtherConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile);
if (!OtherConsumer) {
IndexActionFailed = true;
return nullptr;
}
std::vector<std::unique_ptr<ASTConsumer>> Consumers;
Consumers.push_back(std::move(OtherConsumer));
Consumers.push_back(createIndexASTConsumer());
return llvm::make_unique<MultiplexConsumer>(std::move(Consumers));
}
std::unique_ptr<FrontendAction>
index::createIndexingAction(std::shared_ptr<IndexDataConsumer> DataConsumer,
IndexingOptions Opts,
std::unique_ptr<FrontendAction> WrappedAction) {
if (WrappedAction)
return llvm::make_unique<WrappingIndexAction>(std::move(WrappedAction),
std::move(DataConsumer),
Opts);
return llvm::make_unique<IndexAction>(std::move(DataConsumer), Opts);
}
static bool topLevelDeclVisitor(void *context, const Decl *D) {
IndexingContext &IndexCtx = *static_cast<IndexingContext*>(context);
return IndexCtx.indexTopLevelDecl(D);
}
static void indexTranslationUnit(ASTUnit &Unit, IndexingContext &IndexCtx) {
Unit.visitLocalTopLevelDecls(&IndexCtx, topLevelDeclVisitor);
}
void index::indexASTUnit(ASTUnit &Unit,
std::shared_ptr<IndexDataConsumer> DataConsumer,
IndexingOptions Opts) {
IndexingContext IndexCtx(Opts, *DataConsumer);
IndexCtx.setASTContext(Unit.getASTContext());
DataConsumer->initialize(Unit.getASTContext());
indexTranslationUnit(Unit, IndexCtx);
}