forked from OSchip/llvm-project
194 lines
6.2 KiB
C++
194 lines
6.2 KiB
C++
//===- 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"
|
|
#include "clang/Serialization/ASTReader.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);
|
|
DataConsumer->finish();
|
|
}
|
|
|
|
void index::indexModuleFile(serialization::ModuleFile &Mod,
|
|
ASTReader &Reader,
|
|
std::shared_ptr<IndexDataConsumer> DataConsumer,
|
|
IndexingOptions Opts) {
|
|
ASTContext &Ctx = Reader.getContext();
|
|
IndexingContext IndexCtx(Opts, *DataConsumer);
|
|
IndexCtx.setASTContext(Ctx);
|
|
DataConsumer->initialize(Ctx);
|
|
|
|
for (const Decl *D :Reader.getModuleFileLevelDecls(Mod)) {
|
|
IndexCtx.indexTopLevelDecl(D);
|
|
}
|
|
DataConsumer->finish();
|
|
}
|