summaryrefslogtreecommitdiffstats
path: root/include/clang/Tooling/Execution.h
blob: 74f0df5a5b9123377305e85faefbe8bef8489fcc (plain)
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
//===--- Execution.h - Executing clang frontend actions -*- C++ ---------*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
//  This file defines framework for executing clang frontend actions.
//
//  The framework can be extended to support different execution plans including
//  standalone execution on the given TUs or parallel execution on all TUs in
//  the codebase.
//
//  In order to enable multiprocessing execution, tool actions are expected to
//  output result into the ToolResults provided by the executor. The
//  `ToolResults` is an interface that abstracts how results are stored e.g.
//  in-memory for standalone execution or on-disk for large-scale execution.
//
//  New executors can be registered as ToolExecutorPlugins via the
//  `ToolExecutorPluginRegistry`. CLI tools can use
//  `createExecutorFromCommandLineArgs` to create a specific registered executor
//  according to the command-line arguments.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_TOOLING_EXECUTION_H
#define LLVM_CLANG_TOOLING_EXECUTION_H

#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/Registry.h"
#include "llvm/Support/StringSaver.h"

namespace clang {
namespace tooling {

extern llvm::cl::opt<std::string> ExecutorName;

/// An abstraction for the result of a tool execution. For example, the
/// underlying result can be in-memory or on-disk.
///
/// Results should be string key-value pairs. For example, a refactoring tool
/// can use source location as key and a replacement in YAML format as value.
class ToolResults {
public:
  virtual ~ToolResults() = default;
  virtual void addResult(StringRef Key, StringRef Value) = 0;
  virtual std::vector<std::pair<llvm::StringRef, llvm::StringRef>>
  AllKVResults() = 0;
  virtual void forEachResult(
      llvm::function_ref<void(StringRef Key, StringRef Value)> Callback) = 0;
};

/// Stores the key-value results in memory. It maintains the lifetime of
/// the result. Clang tools using this class are expected to generate a small
/// set of different results, or a large set of duplicated results.
class InMemoryToolResults : public ToolResults {
public:
  InMemoryToolResults() : Strings(Arena) {}
  void addResult(StringRef Key, StringRef Value) override;
  std::vector<std::pair<llvm::StringRef, llvm::StringRef>>
  AllKVResults() override;
  void forEachResult(llvm::function_ref<void(StringRef Key, StringRef Value)>
                         Callback) override;

private:
  llvm::BumpPtrAllocator Arena;
  llvm::UniqueStringSaver Strings;

  std::vector<std::pair<llvm::StringRef, llvm::StringRef>> KVResults;
};

/// The context of an execution, including the information about
/// compilation and results.
class ExecutionContext {
public:
  virtual ~ExecutionContext() {}

  /// Initializes a context. This does not take ownership of `Results`.
  explicit ExecutionContext(ToolResults *Results) : Results(Results) {}

  /// Adds a KV pair to the result container of this execution.
  void reportResult(StringRef Key, StringRef Value);

  // Returns the source control system's revision number if applicable.
  // Otherwise returns an empty string.
  virtual std::string getRevision() { return ""; }

  // Returns the corpus being analyzed, e.g. "llvm" for the LLVM codebase, if
  // applicable.
  virtual std::string getCorpus() { return ""; }

  // Returns the currently processed compilation unit if available.
  virtual std::string getCurrentCompilationUnit() { return ""; }

private:
  ToolResults *Results;
};

/// Interface for executing clang frontend actions.
///
/// This can be extended to support running tool actions in different
/// execution mode, e.g. on a specific set of TUs or many TUs in parallel.
///
///  New executors can be registered as ToolExecutorPlugins via the
///  `ToolExecutorPluginRegistry`. CLI tools can use
///  `createExecutorFromCommandLineArgs` to create a specific registered
///  executor according to the command-line arguments.
class ToolExecutor {
public:
  virtual ~ToolExecutor() {}

  /// Returns the name of a specific executor.
  virtual StringRef getExecutorName() const = 0;

  /// Should return true iff executor runs all actions in a single process.
  /// Clients can use this signal to find out if they can collect results
  /// in-memory (e.g. to avoid serialization costs of using ToolResults).
  /// The single-process executors can still run multiple threads, but all
  /// executions are guaranteed to share the same memory.
  virtual bool isSingleProcess() const = 0;

  /// Executes each action with a corresponding arguments adjuster.
  virtual llvm::Error
  execute(llvm::ArrayRef<
          std::pair<std::unique_ptr<FrontendActionFactory>, ArgumentsAdjuster>>
              Actions) = 0;

  /// Convenient functions for the above `execute`.
  llvm::Error execute(std::unique_ptr<FrontendActionFactory> Action);
  /// Executes an action with an argument adjuster.
  llvm::Error execute(std::unique_ptr<FrontendActionFactory> Action,
                      ArgumentsAdjuster Adjuster);

  /// Returns a reference to the execution context.
  ///
  /// This should be passed to tool callbacks, and tool callbacks should report
  /// results via the returned context.
  virtual ExecutionContext *getExecutionContext() = 0;

  /// Returns a reference to the result container.
  ///
  /// NOTE: This should only be used after the execution finishes. Tool
  /// callbacks should report results via `ExecutionContext` instead.
  virtual ToolResults *getToolResults() = 0;

  /// Map a virtual file to be used while running the tool.
  ///
  /// \param FilePath The path at which the content will be mapped.
  /// \param Content A buffer of the file's content.
  virtual void mapVirtualFile(StringRef FilePath, StringRef Content) = 0;
};

/// Interface for factories that create specific executors. This is also
/// used as a plugin to be registered into ToolExecutorPluginRegistry.
class ToolExecutorPlugin {
public:
  virtual ~ToolExecutorPlugin() {}

  /// Create an `ToolExecutor`.
  ///
  /// `OptionsParser` can be consumed (e.g. moved) if the creation succeeds.
  virtual llvm::Expected<std::unique_ptr<ToolExecutor>>
  create(CommonOptionsParser &OptionsParser) = 0;
};

/// This creates a ToolExecutor that is in the global registry based on
/// commandline arguments.
///
/// This picks the right executor based on the `--executor` option. This parses
/// the commandline arguments with `CommonOptionsParser`, so caller does not
/// need to parse again.
///
/// By default, this creates a `StandaloneToolExecutor` ("standalone") if
/// `--executor` is not provided.
llvm::Expected<std::unique_ptr<ToolExecutor>>
createExecutorFromCommandLineArgs(int &argc, const char **argv,
                                  llvm::cl::OptionCategory &Category,
                                  const char *Overview = nullptr);

namespace internal {
llvm::Expected<std::unique_ptr<ToolExecutor>>
createExecutorFromCommandLineArgsImpl(int &argc, const char **argv,
                                      llvm::cl::OptionCategory &Category,
                                      const char *Overview = nullptr);
} // end namespace internal

} // end namespace tooling
} // end namespace clang

#endif // LLVM_CLANG_TOOLING_EXECUTION_H