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