clang-tools  14.0.0git
IndexerMain.cpp
Go to the documentation of this file.
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.
10 //
11 //===----------------------------------------------------------------------===//
12 
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/CommonOptionsParser.h"
24 #include "clang/Tooling/Execution.h"
25 #include "clang/Tooling/Tooling.h"
26 #include "llvm/Support/CommandLine.h"
27 #include "llvm/Support/Signals.h"
28 #include <utility>
29 
30 namespace clang {
31 namespace clangd {
32 namespace {
33 
34 static llvm::cl::opt<IndexFileFormat>
35  Format("format", llvm::cl::desc("Format of the index to be written"),
36  llvm::cl::values(clEnumValN(IndexFileFormat::YAML, "yaml",
37  "human-readable YAML format"),
38  clEnumValN(IndexFileFormat::RIFF, "binary",
39  "binary RIFF format")),
40  llvm::cl::init(IndexFileFormat::RIFF));
41 
42 class IndexActionFactory : public tooling::FrontendActionFactory {
43 public:
44  IndexActionFactory(IndexFileIn &Result) : Result(Result) {}
45 
46  std::unique_ptr<FrontendAction> create() override {
47  SymbolCollector::Options Opts;
48  Opts.CountReferences = true;
49  Opts.FileFilter = [&](const SourceManager &SM, FileID FID) {
50  const auto *F = SM.getFileEntryForID(FID);
51  if (!F)
52  return false; // Skip invalid files.
53  auto AbsPath = getCanonicalPath(F, SM);
54  if (!AbsPath)
55  return false; // Skip files without absolute path.
56  std::lock_guard<std::mutex> Lock(FilesMu);
57  return Files.insert(*AbsPath).second; // Skip already processed files.
58  };
60  Opts,
61  [&](SymbolSlab S) {
62  // Merge as we go.
63  std::lock_guard<std::mutex> Lock(SymbolsMu);
64  for (const auto &Sym : S) {
65  if (const auto *Existing = Symbols.find(Sym.ID))
66  Symbols.insert(mergeSymbol(*Existing, Sym));
67  else
68  Symbols.insert(Sym);
69  }
70  },
71  [&](RefSlab S) {
72  std::lock_guard<std::mutex> Lock(RefsMu);
73  for (const auto &Sym : S) {
74  // Deduplication happens during insertion.
75  for (const auto &Ref : Sym.second)
76  Refs.insert(Sym.first, Ref);
77  }
78  },
79  [&](RelationSlab S) {
80  std::lock_guard<std::mutex> Lock(RelsMu);
81  for (const auto &R : S) {
82  Relations.insert(R);
83  }
84  },
85  /*IncludeGraphCallback=*/nullptr);
86  }
87 
88  bool runInvocation(std::shared_ptr<CompilerInvocation> Invocation,
89  FileManager *Files,
90  std::shared_ptr<PCHContainerOperations> PCHContainerOps,
91  DiagnosticConsumer *DiagConsumer) override {
92  disableUnsupportedOptions(*Invocation);
93  return tooling::FrontendActionFactory::runInvocation(
94  std::move(Invocation), Files, std::move(PCHContainerOps), DiagConsumer);
95  }
96 
97  // Awkward: we write the result in the destructor, because the executor
98  // takes ownership so it's the easiest way to get our data back out.
99  ~IndexActionFactory() {
100  Result.Symbols = std::move(Symbols).build();
101  Result.Refs = std::move(Refs).build();
102  Result.Relations = std::move(Relations).build();
103  }
104 
105 private:
106  IndexFileIn &Result;
107  std::mutex FilesMu;
108  llvm::StringSet<> Files;
109  std::mutex SymbolsMu;
110  SymbolSlab::Builder Symbols;
111  std::mutex RefsMu;
113  std::mutex RelsMu;
114  RelationSlab::Builder Relations;
115 };
116 
117 } // namespace
118 } // namespace clangd
119 } // namespace clang
120 
121 int main(int argc, const char **argv) {
122  llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
123 
124  const char *Overview = R"(
125  Creates an index of symbol information etc in a whole project.
126 
127  Example usage for a project using CMake compile commands:
128 
129  $ clangd-indexer --executor=all-TUs compile_commands.json > clangd.dex
130 
131  Example usage for file sequence index without flags:
132 
133  $ clangd-indexer File1.cpp File2.cpp ... FileN.cpp > clangd.dex
134 
135  Note: only symbols from header files will be indexed.
136  )";
137 
138  auto Executor = clang::tooling::createExecutorFromCommandLineArgs(
139  argc, argv, llvm::cl::getGeneralCategory(), Overview);
140 
141  if (!Executor) {
142  llvm::errs() << llvm::toString(Executor.takeError()) << "\n";
143  return 1;
144  }
145 
146  // Collect symbols found in each translation unit, merging as we go.
148  auto Err = Executor->get()->execute(
149  std::make_unique<clang::clangd::IndexActionFactory>(Data),
150  clang::tooling::ArgumentsAdjuster(
152  if (Err) {
153  clang::clangd::elog("{0}", std::move(Err));
154  }
155 
156  // Emit collected data.
158  Out.Format = clang::clangd::Format;
159  llvm::outs() << Out;
160  return 0;
161 }
clang::clangd::IndexFileFormat::YAML
@ YAML
IndexAction.h
Refs
RefSlab Refs
Definition: SymbolCollectorTests.cpp:311
clang::clangd::IndexFileFormat::RIFF
@ RIFF
clang::clangd::IndexFileIn
Definition: Serialization.h:42
DiagnosticConsumer
clang::clangd::disableUnsupportedOptions
void disableUnsupportedOptions(CompilerInvocation &CI)
Clears CI from options that are not supported by clangd, like codegen or plugins.
Definition: Compiler.cpp:45
main
int main(int argc, const char **argv)
Definition: IndexerMain.cpp:121
clang::clangd::IndexFileOut
Definition: Serialization.h:55
clang::clangd::getCanonicalPath
llvm::Optional< std::string > getCanonicalPath(const FileEntry *F, const SourceManager &SourceMgr)
Get the canonical path of F.
Definition: SourceCode.cpp:514
clang::clangd::CommandMangler::detect
static CommandMangler detect()
Definition: CompileCommands.cpp:188
Builder
CodeCompletionBuilder Builder
Definition: CodeCompletionStringsTests.cpp:36
CompileCommands.h
Logger.h
clang::clangd::mergeSymbol
Symbol mergeSymbol(const Symbol &L, const Symbol &R)
Definition: Merge.cpp:213
Serialization.h
Files
llvm::DenseSet< FileID > Files
Definition: IncludeCleaner.cpp:106
Symbol.h
Compiler.h
Ref.h
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
clang::tidy::cppcoreguidelines::toString
static llvm::StringRef toString(SpecialMemberFunctionsCheck::SpecialMemberFunctionKind K)
Definition: SpecialMemberFunctionsCheck.cpp:55
SM
const SourceManager & SM
Definition: IncludeCleaner.cpp:108
SymbolCollector.h
Merge.h
Out
CompiledFragmentImpl & Out
Definition: ConfigCompile.cpp:100
clang::clangd::elog
void elog(const char *Fmt, Ts &&... Vals)
Definition: Logger.h:62
clang::clangd::createStaticIndexingAction
std::unique_ptr< FrontendAction > createStaticIndexingAction(SymbolCollector::Options Opts, std::function< void(SymbolSlab)> SymbolsCallback, std::function< void(RefSlab)> RefsCallback, std::function< void(RelationSlab)> RelationsCallback, std::function< void(IncludeGraph)> IncludeGraphCallback)
Definition: IndexAction.cpp:214