21 #include "clang/Frontend/CompilerInstance.h" 22 #include "clang/Frontend/FrontendActions.h" 23 #include "clang/Index/IndexDataConsumer.h" 24 #include "clang/Index/IndexingAction.h" 25 #include "clang/Tooling/CommonOptionsParser.h" 26 #include "clang/Tooling/Execution.h" 27 #include "clang/Tooling/Tooling.h" 28 #include "llvm/Support/CommandLine.h" 29 #include "llvm/Support/MemoryBuffer.h" 30 #include "llvm/Support/Path.h" 31 #include "llvm/Support/Signals.h" 32 #include "llvm/Support/ThreadPool.h" 33 #include "llvm/Support/YAMLTraits.h" 43 static llvm::cl::opt<std::string> AssumedHeaderDir(
45 llvm::cl::desc(
"The index includes header that a symbol is defined in. " 46 "If the absolute path cannot be determined (e.g. an " 47 "in-memory VFS) then the relative path is resolved against " 48 "this directory, which must be absolute. If this flag is " 49 "not given, such headers will have relative paths."),
52 class SymbolIndexActionFactory :
public tooling::FrontendActionFactory {
54 SymbolIndexActionFactory(tooling::ExecutionContext *
Ctx) : Ctx(Ctx) {}
56 clang::FrontendAction *
create()
override {
59 class WrappedIndexAction :
public WrapperFrontendAction {
61 WrappedIndexAction(std::shared_ptr<SymbolCollector> C,
62 std::unique_ptr<CanonicalIncludes> Includes,
63 const index::IndexingOptions &Opts,
64 tooling::ExecutionContext *
Ctx)
65 : WrapperFrontendAction(
66 index::createIndexingAction(C, Opts, nullptr)),
67 Ctx(Ctx), Collector(C), Includes(std::move(Includes)),
70 std::unique_ptr<ASTConsumer>
71 CreateASTConsumer(CompilerInstance &CI, StringRef InFile)
override {
72 CI.getPreprocessor().addCommentHandler(PragmaHandler.get());
73 return WrapperFrontendAction::CreateASTConsumer(CI, InFile);
76 bool BeginInvocation(CompilerInstance &CI)
override {
78 CI.getLangOpts().CommentOpts.ParseAllComments =
true;
79 return WrapperFrontendAction::BeginInvocation(CI);
82 void EndSourceFileAction()
override {
83 WrapperFrontendAction::EndSourceFileAction();
85 const auto &CI = getCompilerInstance();
86 if (CI.hasDiagnostics() &&
87 CI.getDiagnostics().hasUncompilableErrorOccurred()) {
89 <<
"Found uncompilable errors in the translation unit. Igoring " 90 "collected symbols...\n";
94 auto Symbols = Collector->takeSymbols();
95 for (
const auto &Sym : Symbols) {
101 tooling::ExecutionContext *
Ctx;
102 std::shared_ptr<SymbolCollector> Collector;
103 std::unique_ptr<CanonicalIncludes> Includes;
104 std::unique_ptr<CommentHandler> PragmaHandler;
107 index::IndexingOptions IndexOpts;
108 IndexOpts.SystemSymbolFilter =
109 index::IndexingOptions::SystemSymbolFilterKind::All;
110 IndexOpts.IndexFunctionLocals =
false;
111 auto CollectorOpts = SymbolCollector::Options();
112 CollectorOpts.FallbackDir = AssumedHeaderDir;
113 CollectorOpts.CollectIncludePath =
true;
114 CollectorOpts.CountReferences =
true;
115 CollectorOpts.Origin = SymbolOrigin::Static;
116 auto Includes = llvm::make_unique<CanonicalIncludes>();
118 CollectorOpts.Includes = Includes.get();
119 return new WrappedIndexAction(
120 std::make_shared<SymbolCollector>(std::move(CollectorOpts)),
121 std::move(Includes), IndexOpts,
Ctx);
124 tooling::ExecutionContext *
Ctx;
129 SymbolSlab::Builder UniqueSymbols;
130 llvm::BumpPtrAllocator Arena;
131 Symbol::Details Scratch;
132 Results->forEachResult([&](llvm::StringRef Key, llvm::StringRef Value) {
134 llvm::yaml::Input Yin(Value, &Arena);
138 if (
const auto *Existing = UniqueSymbols.find(ID))
139 UniqueSymbols.insert(
mergeSymbol(*Existing, Sym, &Scratch));
141 UniqueSymbols.insert(Sym);
143 return std::move(UniqueSymbols).build();
150 int main(
int argc,
const char **argv) {
151 llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
153 const char *Overview = R
"( 154 This is an **experimental** tool to generate YAML-format project-wide symbols 155 for clangd (global code completion). It would be changed and deprecated 156 eventually. Don't use it in production code! 158 Example usage for building index for the whole project using CMake compile 161 $ global-symbol-builder --executor=all-TUs compile_commands.json > index.yaml 163 Example usage for file sequence index without flags: 165 $ global-symbol-builder File1.cpp File2.cpp ... FileN.cpp > index.yaml 167 Note: only symbols from header files will be collected. 170 auto Executor = clang::tooling::createExecutorFromCommandLineArgs(
171 argc, argv, cl::GeneralCategory, Overview);
178 if (!clang::clangd::AssumedHeaderDir.empty() &&
179 !llvm::sys::path::is_absolute(clang::clangd::AssumedHeaderDir)) {
180 llvm::errs() <<
"--assume-header-dir must be an absolute path.\n";
185 auto Err = Executor->get()->execute(
186 llvm::make_unique<clang::clangd::SymbolIndexActionFactory>(
187 Executor->get()->getExecutionContext()));
194 clang::clangd::mergeSymbols(Executor->get()->getToolResults());
std::unique_ptr< CommentHandler > collectIWYUHeaderMaps(CanonicalIncludes *Includes)
Returns a CommentHandler that parses pragma comment on include files to determine when we should incl...
Some operations such as code completion produce a set of candidates.
static llvm::StringRef toString(SpecialMemberFunctionsCheck::SpecialMemberFunctionKind K)
std::vector< CodeCompletionResult > Results
int main(int argc, const char **argv)
std::unique_ptr< Iterator > create(PostingListRef Documents)
Returns a document iterator over given PostingList.
void SymbolsToYAML(const SymbolSlab &Symbols, llvm::raw_ostream &OS)
std::string SymbolToYAML(Symbol Sym)
Symbol mergeSymbol(const Symbol &L, const Symbol &R, Symbol::Details *Scratch)
Symbol SymbolFromYAML(llvm::yaml::Input &Input, llvm::BumpPtrAllocator &Arena)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
tooling::ExecutionContext * Ctx
void addSystemHeadersMapping(CanonicalIncludes *Includes)
Adds mapping for system headers and some special symbols (e.g.