Line data Source code
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 Read a named option from the ``Context`` and parse it as an
77 : /// integral type ``T``.
78 : ///
79 : /// Reads the option with the check-local name \p LocalName from local or
80 : /// global ``CheckOptions``. Gets local option first. If local is not present,
81 : /// falls back to get global option. If global option is not present either,
82 : /// returns Default.
83 : template <typename T>
84 : typename std::enable_if<std::is_integral<T>::value, T>::type
85 : getLocalOrGlobal(StringRef LocalName, T Default) const {
86 : std::string Value = getLocalOrGlobal(LocalName, "");
87 : T Result = Default;
88 : if (!Value.empty())
89 : StringRef(Value).getAsInteger(10, Result);
90 : return Result;
91 : }
92 :
93 : /// \brief Stores an option with the check-local name \p LocalName with string
94 : /// value \p Value to \p Options.
95 : void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName,
96 : StringRef Value) const;
97 :
98 : /// \brief Stores an option with the check-local name \p LocalName with
99 : /// ``int64_t`` value \p Value to \p Options.
100 : void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName,
101 : int64_t Value) const;
102 :
103 : private:
104 : std::string NamePrefix;
105 : const ClangTidyOptions::OptionMap &CheckOptions;
106 : };
107 :
108 : /// \brief Base class for all clang-tidy checks.
109 : ///
110 : /// To implement a ``ClangTidyCheck``, write a subclass and override some of the
111 : /// base class's methods. E.g. to implement a check that validates namespace
112 : /// declarations, override ``registerMatchers``:
113 : ///
114 : /// ~~~{.cpp}
115 : /// void registerMatchers(ast_matchers::MatchFinder *Finder) override {
116 : /// Finder->addMatcher(namespaceDecl().bind("namespace"), this);
117 : /// }
118 : /// ~~~
119 : ///
120 : /// and then override ``check(const MatchResult &Result)`` to do the actual
121 : /// check for each match.
122 : ///
123 : /// A new ``ClangTidyCheck`` instance is created per translation unit.
124 : ///
125 : /// FIXME: Figure out whether carrying information from one TU to another is
126 : /// useful/necessary.
127 : class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
128 : public:
129 : /// \brief Initializes the check with \p CheckName and \p Context.
130 : ///
131 : /// Derived classes must implement the constructor with this signature or
132 : /// delegate it. If a check needs to read options, it can do this in the
133 : /// constructor using the Options.get() methods below.
134 67 : ClangTidyCheck(StringRef CheckName, ClangTidyContext *Context)
135 67 : : CheckName(CheckName), Context(Context),
136 134 : Options(CheckName, Context->getOptions().CheckOptions) {
137 : assert(Context != nullptr);
138 : assert(!CheckName.empty());
139 67 : }
140 :
141 : /// \brief Override this to register ``PPCallbacks`` with ``Compiler``.
142 : ///
143 : /// This should be used for clang-tidy checks that analyze preprocessor-
144 : /// dependent properties, e.g. the order of include directives.
145 115 : virtual void registerPPCallbacks(CompilerInstance &Compiler) {}
146 :
147 : /// \brief Override this to register AST matchers with \p Finder.
148 : ///
149 : /// This should be used by clang-tidy checks that analyze code properties that
150 : /// dependent on AST knowledge.
151 : ///
152 : /// You can register as many matchers as necessary with \p Finder. Usually,
153 : /// "this" will be used as callback, but you can also specify other callback
154 : /// classes. Thereby, different matchers can trigger different callbacks.
155 : ///
156 : /// If you need to merge information between the different matchers, you can
157 : /// store these as members of the derived class. However, note that all
158 : /// matches occur in the order of the AST traversal.
159 16 : virtual void registerMatchers(ast_matchers::MatchFinder *Finder) {}
160 :
161 : /// \brief ``ClangTidyChecks`` that register ASTMatchers should do the actual
162 : /// work in here.
163 0 : virtual void check(const ast_matchers::MatchFinder::MatchResult &Result) {}
164 :
165 : /// \brief Add a diagnostic with the check's name.
166 : DiagnosticBuilder diag(SourceLocation Loc, StringRef Description,
167 : DiagnosticIDs::Level Level = DiagnosticIDs::Warning);
168 :
169 : /// \brief Should store all options supported by this check with their
170 : /// current values or default values for options that haven't been overridden.
171 : ///
172 : /// The check should use ``Options.store()`` to store each option it supports
173 : /// whether it has the default value or it has been overridden.
174 0 : virtual void storeOptions(ClangTidyOptions::OptionMap &Options) {}
175 :
176 : private:
177 : void run(const ast_matchers::MatchFinder::MatchResult &Result) override;
178 0 : StringRef getID() const override { return CheckName; }
179 : std::string CheckName;
180 : ClangTidyContext *Context;
181 :
182 : protected:
183 : OptionsView Options;
184 : /// \brief Returns the main file name of the current translation unit.
185 : StringRef getCurrentMainFile() const { return Context->getCurrentFile(); }
186 : /// \brief Returns the language options from the context.
187 : LangOptions getLangOpts() const { return Context->getLangOpts(); }
188 : };
189 :
190 : class ClangTidyCheckFactories;
191 :
192 : class ClangTidyASTConsumerFactory {
193 : public:
194 : ClangTidyASTConsumerFactory(ClangTidyContext &Context);
195 :
196 : /// \brief Returns an ASTConsumer that runs the specified clang-tidy checks.
197 : std::unique_ptr<clang::ASTConsumer>
198 : CreateASTConsumer(clang::CompilerInstance &Compiler, StringRef File);
199 :
200 : /// \brief Get the list of enabled checks.
201 : std::vector<std::string> getCheckNames();
202 :
203 : /// \brief Get the union of options from all checks.
204 : ClangTidyOptions::OptionMap getCheckOptions();
205 :
206 : private:
207 : ClangTidyContext &Context;
208 : std::unique_ptr<ClangTidyCheckFactories> CheckFactories;
209 : };
210 :
211 : /// \brief Fills the list of check names that are enabled when the provided
212 : /// filters are applied.
213 : std::vector<std::string> getCheckNames(const ClangTidyOptions &Options,
214 : bool AllowEnablingAnalyzerAlphaCheckers);
215 :
216 : /// \brief Returns the effective check-specific options.
217 : ///
218 : /// The method configures ClangTidy with the specified \p Options and collects
219 : /// effective options from all created checks. The returned set of options
220 : /// includes default check-specific options for all keys not overridden by \p
221 : /// Options.
222 : ClangTidyOptions::OptionMap
223 : getCheckOptions(const ClangTidyOptions &Options,
224 : bool AllowEnablingAnalyzerAlphaCheckers);
225 :
226 : /// \brief Run a set of clang-tidy checks on a set of files.
227 : ///
228 : /// \param EnableCheckProfile If provided, it enables check profile collection
229 : /// in MatchFinder, and will contain the result of the profile.
230 : /// \param StoreCheckProfile If provided, and EnableCheckProfile is true,
231 : /// the profile will not be output to stderr, but will instead be stored
232 : /// as a JSON file in the specified directory.
233 : void runClangTidy(clang::tidy::ClangTidyContext &Context,
234 : const tooling::CompilationDatabase &Compilations,
235 : ArrayRef<std::string> InputFiles,
236 : llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS,
237 : bool EnableCheckProfile = false,
238 : llvm::StringRef StoreCheckProfile = StringRef());
239 :
240 : // FIXME: This interface will need to be significantly extended to be useful.
241 : // FIXME: Implement confidence levels for displaying/fixing errors.
242 : //
243 : /// \brief Displays the found \p Errors to the users. If \p Fix is true, \p
244 : /// Errors containing fixes are automatically applied and reformatted. If no
245 : /// clang-format configuration file is found, the given \P FormatStyle is used.
246 : void handleErrors(ClangTidyContext &Context, bool Fix,
247 : unsigned &WarningsAsErrorsCount,
248 : llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS);
249 :
250 : /// \brief Serializes replacements into YAML and writes them to the specified
251 : /// output stream.
252 : void exportReplacements(StringRef MainFilePath,
253 : const std::vector<ClangTidyError> &Errors,
254 : raw_ostream &OS);
255 :
256 : } // end namespace tidy
257 : } // end namespace clang
258 :
259 : #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDY_H
|