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