llvm-project/clang-tools-extra/clangd/index/IndexAction.cpp

85 lines
3.0 KiB
C++

#include "IndexAction.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Index/IndexDataConsumer.h"
#include "clang/Index/IndexingAction.h"
#include "clang/Tooling/Tooling.h"
using namespace llvm;
namespace clang {
namespace clangd {
namespace {
// Wraps the index action and reports index data after each translation unit.
class IndexAction : public WrapperFrontendAction {
public:
IndexAction(std::shared_ptr<SymbolCollector> C,
std::unique_ptr<CanonicalIncludes> Includes,
const index::IndexingOptions &Opts,
std::function<void(SymbolSlab)> SymbolsCallback,
std::function<void(RefSlab)> RefsCallback)
: WrapperFrontendAction(index::createIndexingAction(C, Opts, nullptr)),
SymbolsCallback(SymbolsCallback), RefsCallback(RefsCallback),
Collector(C), Includes(std::move(Includes)),
PragmaHandler(collectIWYUHeaderMaps(this->Includes.get())) {}
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
StringRef InFile) override {
CI.getPreprocessor().addCommentHandler(PragmaHandler.get());
return WrapperFrontendAction::CreateASTConsumer(CI, InFile);
}
bool BeginInvocation(CompilerInstance &CI) override {
// We want all comments, not just the doxygen ones.
CI.getLangOpts().CommentOpts.ParseAllComments = true;
return WrapperFrontendAction::BeginInvocation(CI);
}
void EndSourceFileAction() override {
WrapperFrontendAction::EndSourceFileAction();
const auto &CI = getCompilerInstance();
if (CI.hasDiagnostics() &&
CI.getDiagnostics().hasUncompilableErrorOccurred()) {
errs() << "Skipping TU due to uncompilable errors\n";
return;
}
SymbolsCallback(Collector->takeSymbols());
if (RefsCallback != nullptr)
RefsCallback(Collector->takeRefs());
}
private:
std::function<void(SymbolSlab)> SymbolsCallback;
std::function<void(RefSlab)> RefsCallback;
std::shared_ptr<SymbolCollector> Collector;
std::unique_ptr<CanonicalIncludes> Includes;
std::unique_ptr<CommentHandler> PragmaHandler;
};
} // namespace
std::unique_ptr<FrontendAction>
createStaticIndexingAction(SymbolCollector::Options Opts,
std::function<void(SymbolSlab)> SymbolsCallback,
std::function<void(RefSlab)> RefsCallback) {
index::IndexingOptions IndexOpts;
IndexOpts.SystemSymbolFilter =
index::IndexingOptions::SystemSymbolFilterKind::All;
Opts.CollectIncludePath = true;
Opts.CountReferences = true;
Opts.Origin = SymbolOrigin::Static;
if (RefsCallback != nullptr) {
Opts.RefFilter = RefKind::All;
Opts.RefsInHeaders = true;
}
auto Includes = llvm::make_unique<CanonicalIncludes>();
addSystemHeadersMapping(Includes.get());
Opts.Includes = Includes.get();
return llvm::make_unique<IndexAction>(
std::make_shared<SymbolCollector>(std::move(Opts)), std::move(Includes),
IndexOpts, SymbolsCallback, RefsCallback);
}
} // namespace clangd
} // namespace clang