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