| Daniel Jasper | d07c840 | 2013-07-29 08:19:24 +0000 | [diff] [blame] | 1 | //===--- ClangTidy.h - clang-tidy -------------------------------*- C++ -*-===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | |
| Alexander Kornienko | 6658055 | 2015-03-09 16:52:33 +0000 | [diff] [blame] | 10 | #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDY_H |
| 11 | #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDY_H |
| Daniel Jasper | d07c840 | 2013-07-29 08:19:24 +0000 | [diff] [blame] | 12 | |
| Chandler Carruth | 85e6e87 | 2014-01-07 20:05:01 +0000 | [diff] [blame] | 13 | #include "ClangTidyDiagnosticConsumer.h" |
| Alexander Kornienko | 33a9bcc | 2014-04-29 15:20:10 +0000 | [diff] [blame] | 14 | #include "ClangTidyOptions.h" |
| Daniel Jasper | d07c840 | 2013-07-29 08:19:24 +0000 | [diff] [blame] | 15 | #include "clang/ASTMatchers/ASTMatchFinder.h" |
| 16 | #include "clang/Basic/Diagnostic.h" |
| 17 | #include "clang/Basic/SourceManager.h" |
| 18 | #include "clang/Tooling/Refactoring.h" |
| Alexander Kornienko | 6e0cbc8 | 2014-09-12 08:53:36 +0000 | [diff] [blame] | 19 | #include "llvm/ADT/StringExtras.h" |
| 20 | #include "llvm/Support/raw_ostream.h" |
| Alexander Kornienko | a469522 | 2014-06-05 13:31:45 +0000 | [diff] [blame] | 21 | #include <memory> |
| Alexander Kornienko | 6e0cbc8 | 2014-09-12 08:53:36 +0000 | [diff] [blame] | 22 | #include <type_traits> |
| Alexander Kornienko | 826b5ad | 2014-05-09 12:24:09 +0000 | [diff] [blame] | 23 | #include <vector> |
| Daniel Jasper | d07c840 | 2013-07-29 08:19:24 +0000 | [diff] [blame] | 24 | |
| 25 | namespace clang { |
| 26 | |
| 27 | class CompilerInstance; |
| Daniel Jasper | d07c840 | 2013-07-29 08:19:24 +0000 | [diff] [blame] | 28 | namespace tooling { |
| 29 | class CompilationDatabase; |
| 30 | } |
| 31 | |
| 32 | namespace tidy { |
| 33 | |
| Alexander Kornienko | 6e0cbc8 | 2014-09-12 08:53:36 +0000 | [diff] [blame] | 34 | /// \brief Provides access to the \c ClangTidyCheck options via check-local |
| 35 | /// names. |
| 36 | /// |
| 37 | /// Methods of this class prepend <tt>CheckName + "."</tt> to translate |
| 38 | /// check-local option names to global option names. |
| 39 | class OptionsView { |
| 40 | public: |
| 41 | /// \brief Initializes the instance using \p CheckName + "." as a prefix. |
| 42 | OptionsView(StringRef CheckName, |
| 43 | const ClangTidyOptions::OptionMap &CheckOptions); |
| 44 | |
| 45 | /// \brief Read a named option from the \c Context. |
| 46 | /// |
| 47 | /// Reads the option with the check-local name \p LocalName from the |
| 48 | /// \c CheckOptions. If the corresponding key is not present, returns |
| 49 | /// \p Default. |
| 50 | std::string get(StringRef LocalName, std::string Default) const; |
| 51 | |
| 52 | /// \brief Read a named option from the \c Context and parse it as an integral |
| 53 | /// type \c T. |
| 54 | /// |
| 55 | /// Reads the option with the check-local name \p LocalName from the |
| 56 | /// \c CheckOptions. If the corresponding key is not present, returns |
| 57 | /// \p Default. |
| 58 | template <typename T> |
| 59 | typename std::enable_if<std::is_integral<T>::value, T>::type |
| 60 | get(StringRef LocalName, T Default) const { |
| 61 | std::string Value = get(LocalName, ""); |
| 62 | T Result = Default; |
| 63 | if (!Value.empty()) |
| 64 | StringRef(Value).getAsInteger(10, Result); |
| 65 | return Result; |
| 66 | } |
| 67 | |
| 68 | /// \brief Stores an option with the check-local name \p LocalName with string |
| 69 | /// value \p Value to \p Options. |
| 70 | void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, |
| 71 | StringRef Value) const; |
| 72 | |
| 73 | /// \brief Stores an option with the check-local name \p LocalName with |
| 74 | /// \c int64_t value \p Value to \p Options. |
| 75 | void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, |
| 76 | int64_t Value) const; |
| 77 | |
| 78 | private: |
| 79 | std::string NamePrefix; |
| 80 | const ClangTidyOptions::OptionMap &CheckOptions; |
| 81 | }; |
| 82 | |
| Daniel Jasper | d07c840 | 2013-07-29 08:19:24 +0000 | [diff] [blame] | 83 | /// \brief Base class for all clang-tidy checks. |
| 84 | /// |
| Alexander Kornienko | 8cef075 | 2015-02-25 13:05:33 +0000 | [diff] [blame] | 85 | /// To implement a \c ClangTidyCheck, write a subclass and override some of the |
| Daniel Jasper | d07c840 | 2013-07-29 08:19:24 +0000 | [diff] [blame] | 86 | /// base class's methods. E.g. to implement a check that validates namespace |
| Alexander Kornienko | 8cef075 | 2015-02-25 13:05:33 +0000 | [diff] [blame] | 87 | /// declarations, override \c registerMatchers: |
| Daniel Jasper | d07c840 | 2013-07-29 08:19:24 +0000 | [diff] [blame] | 88 | /// |
| 89 | /// \code |
| 90 | /// registerMatchers(ast_matchers::MatchFinder *Finder) { |
| 91 | /// Finder->addMatcher(namespaceDecl().bind("namespace"), this); |
| 92 | /// } |
| 93 | /// \endcode |
| 94 | /// |
| Alexander Kornienko | 8cef075 | 2015-02-25 13:05:33 +0000 | [diff] [blame] | 95 | /// and then override \c check(const MatchResult &Result) to do the actual |
| Daniel Jasper | d07c840 | 2013-07-29 08:19:24 +0000 | [diff] [blame] | 96 | /// check for each match. |
| 97 | /// |
| 98 | /// A new \c ClangTidyCheck instance is created per translation unit. |
| 99 | /// |
| 100 | /// FIXME: Figure out whether carrying information from one TU to another is |
| 101 | /// useful/necessary. |
| 102 | class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { |
| 103 | public: |
| Alexander Kornienko | 6e0cbc8 | 2014-09-12 08:53:36 +0000 | [diff] [blame] | 104 | /// \brief Initializes the check with \p CheckName and \p Context. |
| 105 | /// |
| 106 | /// Derived classes must implement the constructor with this signature or |
| 107 | /// delegate it. If a check needs to read options, it can do this in the |
| 108 | /// constructor using the Options.get() methods below. |
| 109 | ClangTidyCheck(StringRef CheckName, ClangTidyContext *Context) |
| 110 | : CheckName(CheckName), Context(Context), |
| 111 | Options(CheckName, Context->getOptions().CheckOptions) { |
| 112 | assert(Context != nullptr); |
| 113 | assert(!CheckName.empty()); |
| 114 | } |
| 115 | |
| Alexander Kornienko | 8cef075 | 2015-02-25 13:05:33 +0000 | [diff] [blame] | 116 | /// \brief Override this to register \c PPCallbacks with \c Compiler. |
| Daniel Jasper | d07c840 | 2013-07-29 08:19:24 +0000 | [diff] [blame] | 117 | /// |
| 118 | /// This should be used for clang-tidy checks that analyze preprocessor- |
| 119 | /// dependent properties, e.g. the order of include directives. |
| 120 | virtual void registerPPCallbacks(CompilerInstance &Compiler) {} |
| 121 | |
| Alexander Kornienko | 8cef075 | 2015-02-25 13:05:33 +0000 | [diff] [blame] | 122 | /// \brief Override this to register ASTMatchers with \p Finder. |
| Daniel Jasper | d07c840 | 2013-07-29 08:19:24 +0000 | [diff] [blame] | 123 | /// |
| 124 | /// This should be used by clang-tidy checks that analyze code properties that |
| 125 | /// dependent on AST knowledge. |
| 126 | /// |
| 127 | /// You can register as many matchers as necessary with \p Finder. Usually, |
| 128 | /// "this" will be used as callback, but you can also specify other callback |
| 129 | /// classes. Thereby, different matchers can trigger different callbacks. |
| 130 | /// |
| 131 | /// If you need to merge information between the different matchers, you can |
| 132 | /// store these as members of the derived class. However, note that all |
| 133 | /// matches occur in the order of the AST traversal. |
| 134 | virtual void registerMatchers(ast_matchers::MatchFinder *Finder) {} |
| 135 | |
| 136 | /// \brief \c ClangTidyChecks that register ASTMatchers should do the actual |
| 137 | /// work in here. |
| 138 | virtual void check(const ast_matchers::MatchFinder::MatchResult &Result) {} |
| 139 | |
| Alexander Kornienko | 41bfe8d | 2014-01-13 10:50:51 +0000 | [diff] [blame] | 140 | /// \brief Add a diagnostic with the check's name. |
| Peter Collingbourne | b17a3b3 | 2014-03-02 23:34:48 +0000 | [diff] [blame] | 141 | DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, |
| 142 | DiagnosticIDs::Level Level = DiagnosticIDs::Warning); |
| Alexander Kornienko | 41bfe8d | 2014-01-13 10:50:51 +0000 | [diff] [blame] | 143 | |
| Alexander Kornienko | 6e0cbc8 | 2014-09-12 08:53:36 +0000 | [diff] [blame] | 144 | /// \brief Should store all options supported by this check with their |
| 145 | /// current values or default values for options that haven't been overridden. |
| 146 | /// |
| 147 | /// The check should use \c Options.store() to store each option it supports |
| 148 | /// whether it has the default value or it has been overridden. |
| 149 | virtual void storeOptions(ClangTidyOptions::OptionMap &Options) {} |
| Daniel Jasper | d07c840 | 2013-07-29 08:19:24 +0000 | [diff] [blame] | 150 | |
| 151 | private: |
| Craig Topper | a3dbe84 | 2014-03-02 10:20:11 +0000 | [diff] [blame] | 152 | void run(const ast_matchers::MatchFinder::MatchResult &Result) override; |
| Samuel Benzaquen | aedd994 | 2014-10-23 17:23:20 +0000 | [diff] [blame] | 153 | StringRef getID() const override { return CheckName; } |
| Alexander Kornienko | 41bfe8d | 2014-01-13 10:50:51 +0000 | [diff] [blame] | 154 | std::string CheckName; |
| Alexander Kornienko | 6e0cbc8 | 2014-09-12 08:53:36 +0000 | [diff] [blame] | 155 | ClangTidyContext *Context; |
| 156 | |
| 157 | protected: |
| 158 | OptionsView Options; |
| Alexander Kornienko | 19bbeaf | 2015-05-21 14:08:56 +0000 | [diff] [blame] | 159 | /// \brief Returns the main file name of the current translation unit. |
| 160 | StringRef getCurrentMainFile() const { return Context->getCurrentFile(); } |
| Aaron Ballman | f36a425 | 2015-08-28 13:20:46 +0000 | [diff] [blame] | 161 | /// \brief Returns the language options from the context. |
| 162 | LangOptions getLangOpts() const { return Context->getLangOpts(); } |
| Daniel Jasper | d07c840 | 2013-07-29 08:19:24 +0000 | [diff] [blame] | 163 | }; |
| 164 | |
| Alexander Kornienko | 175fefb | 2014-01-03 09:31:57 +0000 | [diff] [blame] | 165 | class ClangTidyCheckFactories; |
| 166 | |
| 167 | class ClangTidyASTConsumerFactory { |
| 168 | public: |
| Alexander Kornienko | a469522 | 2014-06-05 13:31:45 +0000 | [diff] [blame] | 169 | ClangTidyASTConsumerFactory(ClangTidyContext &Context); |
| Alexander Kornienko | 175fefb | 2014-01-03 09:31:57 +0000 | [diff] [blame] | 170 | |
| 171 | /// \brief Returns an ASTConsumer that runs the specified clang-tidy checks. |
| David Blaikie | 680c4c8 | 2014-08-10 19:56:59 +0000 | [diff] [blame] | 172 | std::unique_ptr<clang::ASTConsumer> |
| 173 | CreateASTConsumer(clang::CompilerInstance &Compiler, StringRef File); |
| Alexander Kornienko | 175fefb | 2014-01-03 09:31:57 +0000 | [diff] [blame] | 174 | |
| 175 | /// \brief Get the list of enabled checks. |
| Alexander Kornienko | 6e0cbc8 | 2014-09-12 08:53:36 +0000 | [diff] [blame] | 176 | std::vector<std::string> getCheckNames(); |
| 177 | |
| 178 | /// \brief Get the union of options from all checks. |
| 179 | ClangTidyOptions::OptionMap getCheckOptions(); |
| Alexander Kornienko | 175fefb | 2014-01-03 09:31:57 +0000 | [diff] [blame] | 180 | |
| 181 | private: |
| Alexander Kornienko | 6e0cbc8 | 2014-09-12 08:53:36 +0000 | [diff] [blame] | 182 | typedef std::vector<std::pair<std::string, bool>> CheckersList; |
| Alexander Kornienko | b3d331d | 2014-08-06 11:49:10 +0000 | [diff] [blame] | 183 | CheckersList getCheckersControlList(GlobList &Filter); |
| Alexander Kornienko | 175fefb | 2014-01-03 09:31:57 +0000 | [diff] [blame] | 184 | |
| Alexander Kornienko | 175fefb | 2014-01-03 09:31:57 +0000 | [diff] [blame] | 185 | ClangTidyContext &Context; |
| Ahmed Charles | 6a2dc5c | 2014-03-09 09:24:40 +0000 | [diff] [blame] | 186 | std::unique_ptr<ClangTidyCheckFactories> CheckFactories; |
| Alexander Kornienko | 175fefb | 2014-01-03 09:31:57 +0000 | [diff] [blame] | 187 | }; |
| 188 | |
| Alexander Kornienko | fb9e92b | 2013-12-19 19:57:05 +0000 | [diff] [blame] | 189 | /// \brief Fills the list of check names that are enabled when the provided |
| 190 | /// filters are applied. |
| Alexander Kornienko | 33a9bcc | 2014-04-29 15:20:10 +0000 | [diff] [blame] | 191 | std::vector<std::string> getCheckNames(const ClangTidyOptions &Options); |
| Alexander Kornienko | fb9e92b | 2013-12-19 19:57:05 +0000 | [diff] [blame] | 192 | |
| Alexander Kornienko | 6e0cbc8 | 2014-09-12 08:53:36 +0000 | [diff] [blame] | 193 | /// \brief Returns the effective check-specific options. |
| 194 | /// |
| 195 | /// The method configures ClangTidy with the specified \p Options and collects |
| 196 | /// effective options from all created checks. The returned set of options |
| 197 | /// includes default check-specific options for all keys not overridden by \p |
| 198 | /// Options. |
| 199 | ClangTidyOptions::OptionMap getCheckOptions(const ClangTidyOptions &Options); |
| 200 | |
| Daniel Jasper | d07c840 | 2013-07-29 08:19:24 +0000 | [diff] [blame] | 201 | /// \brief Run a set of clang-tidy checks on a set of files. |
| Samuel Benzaquen | aedd994 | 2014-10-23 17:23:20 +0000 | [diff] [blame] | 202 | /// |
| 203 | /// \param Profile if provided, it enables check profile collection in |
| 204 | /// MatchFinder, and will contain the result of the profile. |
| Alexander Kornienko | a469522 | 2014-06-05 13:31:45 +0000 | [diff] [blame] | 205 | ClangTidyStats |
| Alexander Kornienko | d53d268 | 2014-09-04 14:23:36 +0000 | [diff] [blame] | 206 | runClangTidy(std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider, |
| Alexander Kornienko | a469522 | 2014-06-05 13:31:45 +0000 | [diff] [blame] | 207 | const tooling::CompilationDatabase &Compilations, |
| 208 | ArrayRef<std::string> InputFiles, |
| Samuel Benzaquen | aedd994 | 2014-10-23 17:23:20 +0000 | [diff] [blame] | 209 | std::vector<ClangTidyError> *Errors, |
| 210 | ProfileData *Profile = nullptr); |
| Daniel Jasper | d07c840 | 2013-07-29 08:19:24 +0000 | [diff] [blame] | 211 | |
| 212 | // FIXME: This interface will need to be significantly extended to be useful. |
| 213 | // FIXME: Implement confidence levels for displaying/fixing errors. |
| 214 | // |
| 215 | /// \brief Displays the found \p Errors to the users. If \p Fix is true, \p |
| 216 | /// Errors containing fixes are automatically applied. |
| Alexander Kornienko | 826b5ad | 2014-05-09 12:24:09 +0000 | [diff] [blame] | 217 | void handleErrors(const std::vector<ClangTidyError> &Errors, bool Fix); |
| Daniel Jasper | d07c840 | 2013-07-29 08:19:24 +0000 | [diff] [blame] | 218 | |
| Benjamin Kramer | fb98b74 | 2014-09-04 10:31:23 +0000 | [diff] [blame] | 219 | /// \brief Serializes replacements into YAML and writes them to the specified |
| 220 | /// output stream. |
| 221 | void exportReplacements(const std::vector<ClangTidyError> &Errors, |
| 222 | raw_ostream &OS); |
| 223 | |
| Daniel Jasper | d07c840 | 2013-07-29 08:19:24 +0000 | [diff] [blame] | 224 | } // end namespace tidy |
| 225 | } // end namespace clang |
| 226 | |
| Alexander Kornienko | 6658055 | 2015-03-09 16:52:33 +0000 | [diff] [blame] | 227 | #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDY_H |