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