File: GlobalSymbolBuilderMain.cpp

package info (click to toggle)
llvm-toolchain-6.0 1%3A6.0.1-10
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 598,080 kB
  • sloc: cpp: 3,046,253; ansic: 595,057; asm: 271,965; python: 128,926; objc: 106,554; sh: 21,906; lisp: 10,191; pascal: 6,094; ml: 5,544; perl: 5,265; makefile: 2,227; cs: 2,027; xml: 686; php: 212; csh: 117
file content (110 lines) | stat: -rw-r--r-- 4,079 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
//===--- GlobalSymbolBuilderMain.cpp -----------------------------*- C++-*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// GlobalSymbolBuilder is a tool to generate YAML-format symbols across the
// whole project. This tools is for **experimental** only. Don't use it in
// production code.
//
//===---------------------------------------------------------------------===//

#include "index/Index.h"
#include "index/SymbolCollector.h"
#include "index/SymbolYAML.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Index/IndexingAction.h"
#include "clang/Index/IndexDataConsumer.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ThreadPool.h"

using namespace llvm;
using namespace clang::tooling;
using clang::clangd::SymbolSlab;

namespace clang {
namespace clangd {

class SymbolIndexActionFactory : public tooling::FrontendActionFactory {
public:
  SymbolIndexActionFactory() = default;

  clang::FrontendAction *create() override {
    index::IndexingOptions IndexOpts;
    IndexOpts.SystemSymbolFilter =
        index::IndexingOptions::SystemSymbolFilterKind::All;
    IndexOpts.IndexFunctionLocals = false;
    Collector = std::make_shared<SymbolCollector>();
    return index::createIndexingAction(Collector, IndexOpts, nullptr).release();
  }

  std::shared_ptr<SymbolCollector> Collector;
};

} // namespace clangd
} // namespace clang

int main(int argc, const char **argv) {
  llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);

  const char* Overview =
      "This is an **experimental** tool to generate YAML-format "
      "project-wide symbols for clangd (global code completion). It would be "
      "changed and deprecated eventually. Don't use it in production code!";
  CommonOptionsParser OptionsParser(argc, argv, cl::GeneralCategory,
                                    /*Overview=*/Overview);

  // No compilation database found, fallback to single TU analysis, this is
  // mainly for debugging purpose:
  //   global-symbol-buidler /tmp/t.cc -- -std=c++11.
  if (OptionsParser.getCompilations().getAllFiles().empty()) {
    llvm::errs() << "No compilation database found, processing individual "
                    "files with flags from command-line\n.";
    ClangTool Tool(OptionsParser.getCompilations(),
                   OptionsParser.getSourcePathList());
    clang::clangd::SymbolIndexActionFactory IndexAction;
    Tool.run(&IndexAction);
    llvm::outs() << SymbolToYAML(IndexAction.Collector->takeSymbols());
    return 0;
  }

  // Found compilation database, we iterate all TUs from database to get all
  // symbols, and then merge them into a single SymbolSlab.
  SymbolSlab::Builder GlobalSymbols;
  std::mutex SymbolMutex;
  auto AddSymbols = [&](const SymbolSlab& NewSymbols) {
    // Synchronize set accesses.
    std::unique_lock<std::mutex> LockGuard(SymbolMutex);
    for (auto Sym : NewSymbols) {
      // FIXME: Better handling the overlap symbols, currently we overwrite it
      // with the latest one, but we always want to good declarations (class
      // definitions, instead of forward declarations).
      GlobalSymbols.insert(Sym);
    }
  };

  {
    llvm::ThreadPool Pool;
    for (auto& file : OptionsParser.getCompilations().getAllFiles()) {
      Pool.async([&OptionsParser, &AddSymbols](llvm::StringRef Path) {
        ClangTool Tool(OptionsParser.getCompilations(), {Path});
        clang::clangd::SymbolIndexActionFactory IndexAction;
        Tool.run(&IndexAction);
        AddSymbols(IndexAction.Collector->takeSymbols());
      }, file);
    }
  }

  llvm::outs() << SymbolToYAML(std::move(GlobalSymbols).build());
  return 0;
}