[AMDGPU][AsmParser][NFC] Translate parsed MIMG instructions to MCInsts automatically.
[llvm-project.git] / clang-tools-extra / clangd / indexer / IndexerMain.cpp
blob2717030e979639d2a4b9d23f801db28298de786b
1 //===--- IndexerMain.cpp -----------------------------------------*- C++-*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // clangd-indexer is a tool to gather index data (symbols, xrefs) from source.
11 //===----------------------------------------------------------------------===//
13 #include "CompileCommands.h"
14 #include "Compiler.h"
15 #include "index/IndexAction.h"
16 #include "index/Merge.h"
17 #include "index/Ref.h"
18 #include "index/Serialization.h"
19 #include "index/Symbol.h"
20 #include "index/SymbolCollector.h"
21 #include "support/Logger.h"
22 #include "clang/Tooling/ArgumentsAdjusters.h"
23 #include "clang/Tooling/Execution.h"
24 #include "clang/Tooling/Tooling.h"
25 #include "llvm/Support/CommandLine.h"
26 #include "llvm/Support/Signals.h"
27 #include <utility>
29 namespace clang {
30 namespace clangd {
31 namespace {
33 static llvm::cl::opt<IndexFileFormat>
34 Format("format", llvm::cl::desc("Format of the index to be written"),
35 llvm::cl::values(clEnumValN(IndexFileFormat::YAML, "yaml",
36 "human-readable YAML format"),
37 clEnumValN(IndexFileFormat::RIFF, "binary",
38 "binary RIFF format")),
39 llvm::cl::init(IndexFileFormat::RIFF));
41 class IndexActionFactory : public tooling::FrontendActionFactory {
42 public:
43 IndexActionFactory(IndexFileIn &Result) : Result(Result) {}
45 std::unique_ptr<FrontendAction> create() override {
46 SymbolCollector::Options Opts;
47 Opts.CountReferences = true;
48 Opts.FileFilter = [&](const SourceManager &SM, FileID FID) {
49 const auto F = SM.getFileEntryRefForID(FID);
50 if (!F)
51 return false; // Skip invalid files.
52 auto AbsPath = getCanonicalPath(*F, SM.getFileManager());
53 if (!AbsPath)
54 return false; // Skip files without absolute path.
55 std::lock_guard<std::mutex> Lock(FilesMu);
56 return Files.insert(*AbsPath).second; // Skip already processed files.
58 return createStaticIndexingAction(
59 Opts,
60 [&](SymbolSlab S) {
61 // Merge as we go.
62 std::lock_guard<std::mutex> Lock(SymbolsMu);
63 for (const auto &Sym : S) {
64 if (const auto *Existing = Symbols.find(Sym.ID))
65 Symbols.insert(mergeSymbol(*Existing, Sym));
66 else
67 Symbols.insert(Sym);
70 [&](RefSlab S) {
71 std::lock_guard<std::mutex> Lock(RefsMu);
72 for (const auto &Sym : S) {
73 // Deduplication happens during insertion.
74 for (const auto &Ref : Sym.second)
75 Refs.insert(Sym.first, Ref);
78 [&](RelationSlab S) {
79 std::lock_guard<std::mutex> Lock(RelsMu);
80 for (const auto &R : S) {
81 Relations.insert(R);
84 /*IncludeGraphCallback=*/nullptr);
87 bool runInvocation(std::shared_ptr<CompilerInvocation> Invocation,
88 FileManager *Files,
89 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
90 DiagnosticConsumer *DiagConsumer) override {
91 disableUnsupportedOptions(*Invocation);
92 return tooling::FrontendActionFactory::runInvocation(
93 std::move(Invocation), Files, std::move(PCHContainerOps), DiagConsumer);
96 // Awkward: we write the result in the destructor, because the executor
97 // takes ownership so it's the easiest way to get our data back out.
98 ~IndexActionFactory() {
99 Result.Symbols = std::move(Symbols).build();
100 Result.Refs = std::move(Refs).build();
101 Result.Relations = std::move(Relations).build();
104 private:
105 IndexFileIn &Result;
106 std::mutex FilesMu;
107 llvm::StringSet<> Files;
108 std::mutex SymbolsMu;
109 SymbolSlab::Builder Symbols;
110 std::mutex RefsMu;
111 RefSlab::Builder Refs;
112 std::mutex RelsMu;
113 RelationSlab::Builder Relations;
116 } // namespace
117 } // namespace clangd
118 } // namespace clang
120 int main(int argc, const char **argv) {
121 llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
123 const char *Overview = R"(
124 Creates an index of symbol information etc in a whole project.
126 Example usage for a project using CMake compile commands:
128 $ clangd-indexer --executor=all-TUs compile_commands.json > clangd.dex
130 Example usage for file sequence index without flags:
132 $ clangd-indexer File1.cpp File2.cpp ... FileN.cpp > clangd.dex
134 Note: only symbols from header files will be indexed.
137 auto Executor = clang::tooling::createExecutorFromCommandLineArgs(
138 argc, argv, llvm::cl::getGeneralCategory(), Overview);
140 if (!Executor) {
141 llvm::errs() << llvm::toString(Executor.takeError()) << "\n";
142 return 1;
145 // Collect symbols found in each translation unit, merging as we go.
146 clang::clangd::IndexFileIn Data;
147 auto Err = Executor->get()->execute(
148 std::make_unique<clang::clangd::IndexActionFactory>(Data),
149 clang::tooling::ArgumentsAdjuster(
150 [Mangler = std::make_shared<clang::clangd::CommandMangler>(
151 clang::clangd::CommandMangler::detect())](
152 const std::vector<std::string> &Args, llvm::StringRef File) {
153 clang::tooling::CompileCommand Cmd;
154 Cmd.CommandLine = Args;
155 Mangler->operator()(Cmd, File);
156 return Cmd.CommandLine;
157 }));
158 if (Err) {
159 clang::clangd::elog("{0}", std::move(Err));
162 // Emit collected data.
163 clang::clangd::IndexFileOut Out(Data);
164 Out.Format = clang::clangd::Format;
165 llvm::outs() << Out;
166 return 0;