ClangTidyOptions.h 13 KB

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