1//===--- ClangTidyOptions.h - clang-tidy ------------------------*- 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#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYOPTIONS_H
10#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYOPTIONS_H
11
12#include "llvm/ADT/IntrusiveRefCntPtr.h"
13#include "llvm/ADT/StringMap.h"
14#include "llvm/ADT/StringRef.h"
15#include "llvm/Support/ErrorOr.h"
16#include "llvm/Support/MemoryBufferRef.h"
17#include "llvm/Support/VirtualFileSystem.h"
18#include <functional>
19#include <optional>
20#include <string>
21#include <system_error>
22#include <utility>
23#include <vector>
24
25namespace clang::tidy {
26
27/// Contains a list of line ranges in a single file.
28struct FileFilter {
29 /// File name.
30 std::string Name;
31
32 /// LineRange is a pair<start, end> (inclusive).
33 typedef std::pair<unsigned, unsigned> LineRange;
34
35 /// A list of line ranges in this file, for which we show warnings.
36 std::vector<LineRange> LineRanges;
37};
38
39/// Global options. These options are neither stored nor read from
40/// configuration files.
41struct ClangTidyGlobalOptions {
42 /// Output warnings from certain line ranges of certain files only.
43 /// If empty, no warnings will be filtered.
44 std::vector<FileFilter> LineFilter;
45};
46
47/// Contains options for clang-tidy. These options may be read from
48/// configuration files, and may be different for different translation units.
49struct ClangTidyOptions {
50 /// These options are used for all settings that haven't been
51 /// overridden by the \c OptionsProvider.
52 ///
53 /// Allow no checks and no headers by default. This method initializes
54 /// check-specific options by calling \c ClangTidyModule::getModuleOptions()
55 /// of each registered \c ClangTidyModule.
56 static ClangTidyOptions getDefaults();
57
58 /// Overwrites all fields in here by the fields of \p Other that have a value.
59 /// \p Order specifies precedence of \p Other option.
60 ClangTidyOptions &mergeWith(const ClangTidyOptions &Other, unsigned Order);
61
62 /// Creates a new \c ClangTidyOptions instance combined from all fields
63 /// of this instance overridden by the fields of \p Other that have a value.
64 /// \p Order specifies precedence of \p Other option.
65 [[nodiscard]] ClangTidyOptions merge(const ClangTidyOptions &Other,
66 unsigned Order) const;
67
68 /// Checks filter.
69 std::optional<std::string> Checks;
70
71 /// WarningsAsErrors filter.
72 std::optional<std::string> WarningsAsErrors;
73
74 /// File extensions to consider to determine if a given diagnostic is located
75 /// in a header file.
76 std::optional<std::vector<std::string>> HeaderFileExtensions;
77
78 /// File extensions to consider to determine if a given diagnostic is located
79 /// is located in an implementation file.
80 std::optional<std::vector<std::string>> ImplementationFileExtensions;
81
82 /// Output warnings from headers matching this filter. Warnings from
83 /// main files will always be displayed.
84 std::optional<std::string> HeaderFilterRegex;
85
86 /// Output warnings from system headers matching \c HeaderFilterRegex.
87 std::optional<bool> SystemHeaders;
88
89 /// Format code around applied fixes with clang-format using this
90 /// style.
91 ///
92 /// Can be one of:
93 /// * 'none' - don't format code around applied fixes;
94 /// * 'llvm', 'google', 'mozilla' or other predefined clang-format style
95 /// names;
96 /// * 'file' - use the .clang-format file in the closest parent directory of
97 /// each source file;
98 /// * '{inline-formatting-style-in-yaml-format}'.
99 ///
100 /// See clang-format documentation for more about configuring format style.
101 std::optional<std::string> FormatStyle;
102
103 /// Specifies the name or e-mail of the user running clang-tidy.
104 ///
105 /// This option is used, for example, to place the correct user name in TODO()
106 /// comments in the relevant check.
107 std::optional<std::string> User;
108
109 /// Helper structure for storing option value with priority of the value.
110 struct ClangTidyValue {
111 ClangTidyValue() = default;
112 ClangTidyValue(const char *Value) : Value(Value) {}
113 ClangTidyValue(llvm::StringRef Value, unsigned Priority = 0)
114 : Value(Value), Priority(Priority) {}
115
116 std::string Value;
117 /// Priority stores relative precedence of the value loaded from config
118 /// files to disambiguate local vs global value from different levels.
119 unsigned Priority = 0;
120 };
121 typedef std::pair<std::string, std::string> StringPair;
122 typedef llvm::StringMap<ClangTidyValue> OptionMap;
123
124 /// Key-value mapping used to store check-specific options.
125 OptionMap CheckOptions;
126
127 typedef std::vector<std::string> ArgList;
128
129 /// Add extra compilation arguments to the end of the list.
130 std::optional<ArgList> ExtraArgs;
131
132 /// Add extra compilation arguments to the start of the list.
133 std::optional<ArgList> ExtraArgsBefore;
134
135 /// Only used in the FileOptionsProvider and ConfigOptionsProvider. If true
136 /// and using a FileOptionsProvider, it will take a configuration file in the
137 /// parent directory (if any exists) and apply this config file on top of the
138 /// parent one. IF true and using a ConfigOptionsProvider, it will apply this
139 /// config on top of any configuration file it finds in the directory using
140 /// the same logic as FileOptionsProvider. If false or missing, only this
141 /// configuration file will be used.
142 std::optional<bool> InheritParentConfig;
143
144 /// Use colors in diagnostics. If missing, it will be auto detected.
145 std::optional<bool> UseColor;
146};
147
148/// Abstract interface for retrieving various ClangTidy options.
149class ClangTidyOptionsProvider {
150public:
151 static const char OptionsSourceTypeDefaultBinary[];
152 static const char OptionsSourceTypeCheckCommandLineOption[];
153 static const char OptionsSourceTypeConfigCommandLineOption[];
154
155 virtual ~ClangTidyOptionsProvider() {}
156
157 /// Returns global options, which are independent of the file.
158 virtual const ClangTidyGlobalOptions &getGlobalOptions() = 0;
159
160 /// ClangTidyOptions and its source.
161 //
162 /// clang-tidy has 3 types of the sources in order of increasing priority:
163 /// * clang-tidy binary.
164 /// * '-config' commandline option or a specific configuration file. If the
165 /// commandline option is specified, clang-tidy will ignore the
166 /// configuration file.
167 /// * '-checks' commandline option.
168 typedef std::pair<ClangTidyOptions, std::string> OptionsSource;
169
170 /// Returns an ordered vector of OptionsSources, in order of increasing
171 /// priority.
172 virtual std::vector<OptionsSource>
173 getRawOptions(llvm::StringRef FileName) = 0;
174
175 /// Returns options applying to a specific translation unit with the
176 /// specified \p FileName.
177 ClangTidyOptions getOptions(llvm::StringRef FileName);
178};
179
180/// Implementation of the \c ClangTidyOptionsProvider interface, which
181/// returns the same options for all files.
182class DefaultOptionsProvider : public ClangTidyOptionsProvider {
183public:
184 DefaultOptionsProvider(ClangTidyGlobalOptions GlobalOptions,
185 ClangTidyOptions Options)
186 : GlobalOptions(std::move(GlobalOptions)),
187 DefaultOptions(std::move(Options)) {}
188 const ClangTidyGlobalOptions &getGlobalOptions() override {
189 return GlobalOptions;
190 }
191 std::vector<OptionsSource> getRawOptions(llvm::StringRef FileName) override;
192
193private:
194 ClangTidyGlobalOptions GlobalOptions;
195 ClangTidyOptions DefaultOptions;
196};
197
198class FileOptionsBaseProvider : public DefaultOptionsProvider {
199protected:
200 // A pair of configuration file base name and a function parsing
201 // configuration from text in the corresponding format.
202 typedef std::pair<std::string, std::function<llvm::ErrorOr<ClangTidyOptions>(
203 llvm::MemoryBufferRef)>>
204 ConfigFileHandler;
205
206 /// Configuration file handlers listed in the order of priority.
207 ///
208 /// Custom configuration file formats can be supported by constructing the
209 /// list of handlers and passing it to the appropriate \c FileOptionsProvider
210 /// constructor. E.g. initialization of a \c FileOptionsProvider with support
211 /// of a custom configuration file format for files named ".my-tidy-config"
212 /// could look similar to this:
213 /// \code
214 /// FileOptionsProvider::ConfigFileHandlers ConfigHandlers;
215 /// ConfigHandlers.emplace_back(".my-tidy-config", parseMyConfigFormat);
216 /// ConfigHandlers.emplace_back(".clang-tidy", parseConfiguration);
217 /// return std::make_unique<FileOptionsProvider>(
218 /// GlobalOptions, DefaultOptions, OverrideOptions, ConfigHandlers);
219 /// \endcode
220 ///
221 /// With the order of handlers shown above, the ".my-tidy-config" file would
222 /// take precedence over ".clang-tidy" if both reside in the same directory.
223 typedef std::vector<ConfigFileHandler> ConfigFileHandlers;
224
225 FileOptionsBaseProvider(ClangTidyGlobalOptions GlobalOptions,
226 ClangTidyOptions DefaultOptions,
227 ClangTidyOptions OverrideOptions,
228 llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS);
229
230 FileOptionsBaseProvider(ClangTidyGlobalOptions GlobalOptions,
231 ClangTidyOptions DefaultOptions,
232 ClangTidyOptions OverrideOptions,
233 ConfigFileHandlers ConfigHandlers);
234
235protected:
236 void addRawFileOptions(llvm::StringRef AbsolutePath,
237 std::vector<OptionsSource> &CurOptions);
238
239 /// Try to read configuration files from \p Directory using registered
240 /// \c ConfigHandlers.
241 std::optional<OptionsSource> tryReadConfigFile(llvm::StringRef Directory);
242
243 llvm::StringMap<OptionsSource> CachedOptions;
244 ClangTidyOptions OverrideOptions;
245 ConfigFileHandlers ConfigHandlers;
246 llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS;
247};
248
249/// Implementation of ClangTidyOptions interface, which is used for
250/// '-config' command-line option.
251class ConfigOptionsProvider : public FileOptionsBaseProvider {
252public:
253 ConfigOptionsProvider(
254 ClangTidyGlobalOptions GlobalOptions, ClangTidyOptions DefaultOptions,
255 ClangTidyOptions ConfigOptions, ClangTidyOptions OverrideOptions,
256 llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS = nullptr);
257 std::vector<OptionsSource> getRawOptions(llvm::StringRef FileName) override;
258
259private:
260 ClangTidyOptions ConfigOptions;
261};
262
263/// Implementation of the \c ClangTidyOptionsProvider interface, which
264/// tries to find a configuration file in the closest parent directory of each
265/// source file.
266///
267/// By default, files named ".clang-tidy" will be considered, and the
268/// \c clang::tidy::parseConfiguration function will be used for parsing, but a
269/// custom set of configuration file names and parsing functions can be
270/// specified using the appropriate constructor.
271class FileOptionsProvider : public FileOptionsBaseProvider {
272public:
273 /// Initializes the \c FileOptionsProvider instance.
274 ///
275 /// \param GlobalOptions are just stored and returned to the caller of
276 /// \c getGlobalOptions.
277 ///
278 /// \param DefaultOptions are used for all settings not specified in a
279 /// configuration file.
280 ///
281 /// If any of the \param OverrideOptions fields are set, they will override
282 /// whatever options are read from the configuration file.
283 FileOptionsProvider(
284 ClangTidyGlobalOptions GlobalOptions, ClangTidyOptions DefaultOptions,
285 ClangTidyOptions OverrideOptions,
286 llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS = nullptr);
287
288 /// Initializes the \c FileOptionsProvider instance with a custom set
289 /// of configuration file handlers.
290 ///
291 /// \param GlobalOptions are just stored and returned to the caller of
292 /// \c getGlobalOptions.
293 ///
294 /// \param DefaultOptions are used for all settings not specified in a
295 /// configuration file.
296 ///
297 /// If any of the \param OverrideOptions fields are set, they will override
298 /// whatever options are read from the configuration file.
299 ///
300 /// \param ConfigHandlers specifies a custom set of configuration file
301 /// handlers. Each handler is a pair of configuration file name and a function
302 /// that can parse configuration from this file type. The configuration files
303 /// in each directory are searched for in the order of appearance in
304 /// \p ConfigHandlers.
305 FileOptionsProvider(ClangTidyGlobalOptions GlobalOptions,
306 ClangTidyOptions DefaultOptions,
307 ClangTidyOptions OverrideOptions,
308 ConfigFileHandlers ConfigHandlers);
309
310 std::vector<OptionsSource> getRawOptions(llvm::StringRef FileName) override;
311};
312
313/// Parses LineFilter from JSON and stores it to the \p Options.
314std::error_code parseLineFilter(llvm::StringRef LineFilter,
315 ClangTidyGlobalOptions &Options);
316
317/// Parses configuration from JSON and returns \c ClangTidyOptions or an
318/// error.
319llvm::ErrorOr<ClangTidyOptions>
320parseConfiguration(llvm::MemoryBufferRef Config);
321
322using DiagCallback = llvm::function_ref<void(const llvm::SMDiagnostic &)>;
323
324llvm::ErrorOr<ClangTidyOptions>
325parseConfigurationWithDiags(llvm::MemoryBufferRef Config, DiagCallback Handler);
326
327/// Serializes configuration to a YAML-encoded string.
328std::string configurationAsText(const ClangTidyOptions &Options);
329
330} // namespace clang::tidy
331
332#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYOPTIONS_H
333