forked from OSchip/llvm-project
126 lines
3.9 KiB
C++
126 lines
3.9 KiB
C++
//===--- IndexerMain.cpp -----------------------------------------*- C++-*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// clangd-indexer is a tool to gather index data (symbols, xrefs) from source.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "index/Index.h"
|
|
#include "index/IndexAction.h"
|
|
#include "index/Merge.h"
|
|
#include "index/Serialization.h"
|
|
#include "index/SymbolCollector.h"
|
|
#include "clang/Tooling/CommonOptionsParser.h"
|
|
#include "clang/Tooling/Execution.h"
|
|
#include "clang/Tooling/Tooling.h"
|
|
#include "llvm/Support/CommandLine.h"
|
|
#include "llvm/Support/Signals.h"
|
|
|
|
using namespace llvm;
|
|
using namespace clang::tooling;
|
|
|
|
namespace clang {
|
|
namespace clangd {
|
|
namespace {
|
|
|
|
static cl::opt<IndexFileFormat>
|
|
Format("format", cl::desc("Format of the index to be written"),
|
|
cl::values(clEnumValN(IndexFileFormat::YAML, "yaml",
|
|
"human-readable YAML format"),
|
|
clEnumValN(IndexFileFormat::RIFF, "binary",
|
|
"binary RIFF format")),
|
|
cl::init(IndexFileFormat::RIFF));
|
|
|
|
class IndexActionFactory : public tooling::FrontendActionFactory {
|
|
public:
|
|
IndexActionFactory(IndexFileIn &Result) : Result(Result) {}
|
|
|
|
clang::FrontendAction *create() override {
|
|
SymbolCollector::Options Opts;
|
|
return createStaticIndexingAction(
|
|
Opts,
|
|
[&](SymbolSlab S) {
|
|
// Merge as we go.
|
|
std::lock_guard<std::mutex> Lock(SymbolsMu);
|
|
for (const auto &Sym : S) {
|
|
if (const auto *Existing = Symbols.find(Sym.ID))
|
|
Symbols.insert(mergeSymbol(*Existing, Sym));
|
|
else
|
|
Symbols.insert(Sym);
|
|
}
|
|
},
|
|
[&](RefSlab S) {
|
|
std::lock_guard<std::mutex> Lock(SymbolsMu);
|
|
for (const auto &Sym : S) {
|
|
// No need to merge as currently all Refs are from main file.
|
|
for (const auto &Ref : Sym.second)
|
|
Refs.insert(Sym.first, Ref);
|
|
}
|
|
})
|
|
.release();
|
|
}
|
|
|
|
// Awkward: we write the result in the destructor, because the executor
|
|
// takes ownership so it's the easiest way to get our data back out.
|
|
~IndexActionFactory() {
|
|
Result.Symbols = std::move(Symbols).build();
|
|
Result.Refs = std::move(Refs).build();
|
|
}
|
|
|
|
private:
|
|
IndexFileIn &Result;
|
|
std::mutex SymbolsMu;
|
|
SymbolSlab::Builder Symbols;
|
|
RefSlab::Builder Refs;
|
|
};
|
|
|
|
} // namespace
|
|
} // namespace clangd
|
|
} // namespace clang
|
|
|
|
int main(int argc, const char **argv) {
|
|
sys::PrintStackTraceOnErrorSignal(argv[0]);
|
|
|
|
const char *Overview = R"(
|
|
Creates an index of symbol information etc in a whole project.
|
|
|
|
Example usage for a project using CMake compile commands:
|
|
|
|
$ clangd-indexer --executor=all-TUs compile_commands.json > clangd.dex
|
|
|
|
Example usage for file sequence index without flags:
|
|
|
|
$ clangd-indexer File1.cpp File2.cpp ... FileN.cpp > clangd.dex
|
|
|
|
Note: only symbols from header files will be indexed.
|
|
)";
|
|
|
|
auto Executor = clang::tooling::createExecutorFromCommandLineArgs(
|
|
argc, argv, cl::GeneralCategory, Overview);
|
|
|
|
if (!Executor) {
|
|
errs() << toString(Executor.takeError()) << "\n";
|
|
return 1;
|
|
}
|
|
|
|
// Collect symbols found in each translation unit, merging as we go.
|
|
clang::clangd::IndexFileIn Data;
|
|
auto Err = Executor->get()->execute(
|
|
llvm::make_unique<clang::clangd::IndexActionFactory>(Data));
|
|
if (Err) {
|
|
errs() << toString(std::move(Err)) << "\n";
|
|
}
|
|
|
|
// Emit collected data.
|
|
clang::clangd::IndexFileOut Out(Data);
|
|
Out.Format = clang::clangd::Format;
|
|
outs() << Out;
|
|
return 0;
|
|
}
|