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