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