blob: 374331c5ef6ea0eacab337f1702a082ff4b0b25d [file] [log] [blame]
Daniel Jasperd07c8402013-07-29 08:19:24 +00001//===--- ClangTidyDiagnosticConsumer.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 Kornienko66580552015-03-09 16:52:33 +000010#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYDIAGNOSTICCONSUMER_H
11#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYDIAGNOSTICCONSUMER_H
Daniel Jasperd07c8402013-07-29 08:19:24 +000012
Alexander Kornienko9ff5b6f2014-05-05 14:54:47 +000013#include "ClangTidyOptions.h"
Daniel Jasperd07c8402013-07-29 08:19:24 +000014#include "clang/Basic/Diagnostic.h"
15#include "clang/Basic/SourceManager.h"
16#include "clang/Tooling/Refactoring.h"
Alexander Kornienko41bfe8d2014-01-13 10:50:51 +000017#include "llvm/ADT/DenseMap.h"
Samuel Benzaquenaedd9942014-10-23 17:23:20 +000018#include "llvm/ADT/StringMap.h"
Alexander Kornienko09952d22014-03-20 09:38:22 +000019#include "llvm/Support/Regex.h"
Samuel Benzaquenaedd9942014-10-23 17:23:20 +000020#include "llvm/Support/Timer.h"
Daniel Jasperd07c8402013-07-29 08:19:24 +000021
22namespace clang {
23
Alexander Kornienkoad216882014-07-14 14:10:03 +000024class ASTContext;
Daniel Jasperd07c8402013-07-29 08:19:24 +000025class CompilerInstance;
26namespace ast_matchers {
27class MatchFinder;
28}
29namespace tooling {
30class CompilationDatabase;
31}
32
33namespace tidy {
34
Manuel Klimek814f9bd2013-11-14 15:49:44 +000035/// \brief A message from a clang-tidy check.
36///
37/// Note that this is independent of a \c SourceManager.
38struct ClangTidyMessage {
39 ClangTidyMessage(StringRef Message = "");
40 ClangTidyMessage(StringRef Message, const SourceManager &Sources,
41 SourceLocation Loc);
42 std::string Message;
43 std::string FilePath;
44 unsigned FileOffset;
45};
46
47/// \brief A detected error complete with information to display diagnostic and
48/// automatic fix.
49///
50/// This is used as an intermediate format to transport Diagnostics without a
51/// dependency on a SourceManager.
52///
53/// FIXME: Make Diagnostics flexible enough to support this directly.
54struct ClangTidyError {
Alexander Kornienko348cae82014-06-02 20:44:32 +000055 enum Level {
56 Warning = DiagnosticsEngine::Warning,
57 Error = DiagnosticsEngine::Error
58 };
59
Haojian Wuf7692a22016-02-26 09:19:33 +000060 ClangTidyError(StringRef CheckName, Level DiagLevel, bool IsWarningAsError,
61 StringRef BuildDirectory);
Manuel Klimek814f9bd2013-11-14 15:49:44 +000062
Alexander Kornienko41bfe8d2014-01-13 10:50:51 +000063 std::string CheckName;
Manuel Klimek814f9bd2013-11-14 15:49:44 +000064 ClangTidyMessage Message;
Eric Liu7e544522016-08-09 07:54:49 +000065 // Fixes grouped by file path.
66 llvm::StringMap<tooling::Replacements> Fix;
Manuel Klimek814f9bd2013-11-14 15:49:44 +000067 SmallVector<ClangTidyMessage, 1> Notes;
Alexander Kornienko348cae82014-06-02 20:44:32 +000068
Haojian Wuf7692a22016-02-26 09:19:33 +000069 // A build directory of the diagnostic source file.
70 //
71 // It's an absolute path which is `directory` field of the source file in
72 // compilation database. If users don't specify the compilation database
73 // directory, it is the current directory where clang-tidy runs.
74 //
75 // Note: it is empty in unittest.
76 std::string BuildDirectory;
77
Alexander Kornienko348cae82014-06-02 20:44:32 +000078 Level DiagLevel;
Jonathan Roelofsd60388a2016-01-13 17:36:41 +000079 bool IsWarningAsError;
Manuel Klimek814f9bd2013-11-14 15:49:44 +000080};
81
Alexander Kornienkob3d331d2014-08-06 11:49:10 +000082/// \brief Read-only set of strings represented as a list of positive and
83/// negative globs. Positive globs add all matched strings to the set, negative
84/// globs remove them in the order of appearance in the list.
85class GlobList {
Alexander Kornienko09952d22014-03-20 09:38:22 +000086public:
Alexander Kornienkoa4695222014-06-05 13:31:45 +000087 /// \brief \p GlobList is a comma-separated list of globs (only '*'
88 /// metacharacter is supported) with optional '-' prefix to denote exclusion.
Alexander Kornienkob3d331d2014-08-06 11:49:10 +000089 GlobList(StringRef Globs);
Alexander Kornienkoa4695222014-06-05 13:31:45 +000090
Alexander Kornienkob3d331d2014-08-06 11:49:10 +000091 /// \brief Returns \c true if the pattern matches \p S. The result is the last
92 /// matching glob's Positive flag.
93 bool contains(StringRef S) { return contains(S, false); }
Alexander Kornienko09952d22014-03-20 09:38:22 +000094
95private:
Alexander Kornienkob3d331d2014-08-06 11:49:10 +000096 bool contains(StringRef S, bool Contains);
Alexander Kornienko23fe9592014-05-15 14:27:36 +000097
98 bool Positive;
99 llvm::Regex Regex;
Alexander Kornienkob3d331d2014-08-06 11:49:10 +0000100 std::unique_ptr<GlobList> NextGlob;
Alexander Kornienko09952d22014-03-20 09:38:22 +0000101};
102
Alexander Kornienkoa4695222014-06-05 13:31:45 +0000103/// \brief Contains displayed and ignored diagnostic counters for a ClangTidy
104/// run.
Alexander Kornienko5d174542014-05-07 09:06:53 +0000105struct ClangTidyStats {
106 ClangTidyStats()
107 : ErrorsDisplayed(0), ErrorsIgnoredCheckFilter(0), ErrorsIgnoredNOLINT(0),
Alexander Kornienkodad4acb2014-05-22 16:07:11 +0000108 ErrorsIgnoredNonUserCode(0), ErrorsIgnoredLineFilter(0) {}
Alexander Kornienko5d174542014-05-07 09:06:53 +0000109
110 unsigned ErrorsDisplayed;
111 unsigned ErrorsIgnoredCheckFilter;
112 unsigned ErrorsIgnoredNOLINT;
113 unsigned ErrorsIgnoredNonUserCode;
Alexander Kornienkodad4acb2014-05-22 16:07:11 +0000114 unsigned ErrorsIgnoredLineFilter;
115
116 unsigned errorsIgnored() const {
117 return ErrorsIgnoredNOLINT + ErrorsIgnoredCheckFilter +
118 ErrorsIgnoredNonUserCode + ErrorsIgnoredLineFilter;
119 }
Alexander Kornienko5d174542014-05-07 09:06:53 +0000120};
121
Samuel Benzaquenaedd9942014-10-23 17:23:20 +0000122/// \brief Container for clang-tidy profiling data.
123struct ProfileData {
124 llvm::StringMap<llvm::TimeRecord> Records;
125};
126
Alexander Kornienko284c2492014-12-19 15:37:02 +0000127/// \brief Every \c ClangTidyCheck reports errors through a \c DiagnosticsEngine
Manuel Klimek814f9bd2013-11-14 15:49:44 +0000128/// provided by this context.
129///
130/// A \c ClangTidyCheck always has access to the active context to report
131/// warnings like:
132/// \code
133/// Context->Diag(Loc, "Single-argument constructors must be explicit")
134/// << FixItHint::CreateInsertion(Loc, "explicit ");
135/// \endcode
136class ClangTidyContext {
137public:
Alexander Kornienkoa4695222014-06-05 13:31:45 +0000138 /// \brief Initializes \c ClangTidyContext instance.
Alexander Kornienkod53d2682014-09-04 14:23:36 +0000139 ClangTidyContext(std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider);
Manuel Klimek814f9bd2013-11-14 15:49:44 +0000140
141 /// \brief Report any errors detected using this method.
142 ///
143 /// This is still under heavy development and will likely change towards using
144 /// tablegen'd diagnostic IDs.
145 /// FIXME: Figure out a way to manage ID spaces.
Alexander Kornienko41bfe8d2014-01-13 10:50:51 +0000146 DiagnosticBuilder diag(StringRef CheckName, SourceLocation Loc,
Alexander Kornienko54461eb2014-02-06 14:50:10 +0000147 StringRef Message,
148 DiagnosticIDs::Level Level = DiagnosticIDs::Warning);
Manuel Klimek814f9bd2013-11-14 15:49:44 +0000149
Manuel Klimek814f9bd2013-11-14 15:49:44 +0000150 /// \brief Sets the \c SourceManager of the used \c DiagnosticsEngine.
151 ///
152 /// This is called from the \c ClangTidyCheck base class.
153 void setSourceManager(SourceManager *SourceMgr);
154
Alexander Kornienkoa4695222014-06-05 13:31:45 +0000155 /// \brief Should be called when starting to process new translation unit.
156 void setCurrentFile(StringRef File);
157
Alexander Kornienko19bbeaf2015-05-21 14:08:56 +0000158 /// \brief Returns the main file name of the current translation unit.
159 StringRef getCurrentFile() const { return CurrentFile; }
160
Alexander Kornienkoad216882014-07-14 14:10:03 +0000161 /// \brief Sets ASTContext for the current translation unit.
162 void setASTContext(ASTContext *Context);
163
Alexander Kornienko64956b52015-11-09 16:28:11 +0000164 /// \brief Gets the language options from the AST context.
Alexander Kornienko1612fa02016-02-25 23:57:23 +0000165 const LangOptions &getLangOpts() const { return LangOpts; }
Aaron Ballmanf36a4252015-08-28 13:20:46 +0000166
Alexander Kornienko41bfe8d2014-01-13 10:50:51 +0000167 /// \brief Returns the name of the clang-tidy check which produced this
168 /// diagnostic ID.
169 StringRef getCheckName(unsigned DiagnosticID) const;
170
Alexander Kornienkoa4695222014-06-05 13:31:45 +0000171 /// \brief Returns check filter for the \c CurrentFile.
Alexander Kornienko64956b52015-11-09 16:28:11 +0000172 ///
173 /// The \c CurrentFile can be changed using \c setCurrentFile.
Alexander Kornienkob3d331d2014-08-06 11:49:10 +0000174 GlobList &getChecksFilter();
Alexander Kornienkoa4695222014-06-05 13:31:45 +0000175
Jonathan Roelofsd60388a2016-01-13 17:36:41 +0000176 /// \brief Returns check filter for the \c CurrentFile which
177 /// selects checks for upgrade to error.
178 GlobList &getWarningAsErrorFilter();
179
Alexander Kornienkoa4695222014-06-05 13:31:45 +0000180 /// \brief Returns global options.
181 const ClangTidyGlobalOptions &getGlobalOptions() const;
182
183 /// \brief Returns options for \c CurrentFile.
Alexander Kornienko64956b52015-11-09 16:28:11 +0000184 ///
185 /// The \c CurrentFile can be changed using \c setCurrentFile.
Alexander Kornienkoa4695222014-06-05 13:31:45 +0000186 const ClangTidyOptions &getOptions() const;
187
Alexander Kornienko64956b52015-11-09 16:28:11 +0000188 /// \brief Returns options for \c File. Does not change or depend on
189 /// \c CurrentFile.
190 ClangTidyOptions getOptionsForFile(StringRef File) const;
191
Alexander Kornienkoa4695222014-06-05 13:31:45 +0000192 /// \brief Returns \c ClangTidyStats containing issued and ignored diagnostic
193 /// counters.
Alexander Kornienko5d174542014-05-07 09:06:53 +0000194 const ClangTidyStats &getStats() const { return Stats; }
Alexander Kornienkoa4695222014-06-05 13:31:45 +0000195
196 /// \brief Returns all collected errors.
Alexander Kornienko826b5ad2014-05-09 12:24:09 +0000197 const std::vector<ClangTidyError> &getErrors() const { return Errors; }
Alexander Kornienkoa4695222014-06-05 13:31:45 +0000198
199 /// \brief Clears collected errors.
Alexander Kornienkoc0093602014-05-09 15:50:15 +0000200 void clearErrors() { Errors.clear(); }
Alexander Kornienko09952d22014-03-20 09:38:22 +0000201
Samuel Benzaquenaedd9942014-10-23 17:23:20 +0000202 /// \brief Set the output struct for profile data.
203 ///
204 /// Setting a non-null pointer here will enable profile collection in
205 /// clang-tidy.
Angel Garcia Gomez16693572015-10-16 11:43:49 +0000206 void setCheckProfileData(ProfileData *Profile);
207 ProfileData *getCheckProfileData() const { return Profile; }
Samuel Benzaquenaedd9942014-10-23 17:23:20 +0000208
Haojian Wuf7692a22016-02-26 09:19:33 +0000209 /// \brief Should be called when starting to process new translation unit.
210 void setCurrentBuildDirectory(StringRef BuildDirectory) {
211 CurrentBuildDirectory = BuildDirectory;
212 }
213
214 /// \brief Returns build directory of the current translation unit.
215 const std::string &getCurrentBuildDirectory() {
216 return CurrentBuildDirectory;
217 }
218
Manuel Klimek814f9bd2013-11-14 15:49:44 +0000219private:
Alexander Kornienkoa4695222014-06-05 13:31:45 +0000220 // Calls setDiagnosticsEngine() and storeError().
221 friend class ClangTidyDiagnosticConsumer;
Benjamin Kramer8f5eb562016-03-03 08:58:12 +0000222 friend class ClangTidyPluginAction;
Manuel Klimek814f9bd2013-11-14 15:49:44 +0000223
Alexander Kornienkoa4695222014-06-05 13:31:45 +0000224 /// \brief Sets the \c DiagnosticsEngine so that Diagnostics can be generated
225 /// correctly.
226 void setDiagnosticsEngine(DiagnosticsEngine *Engine);
227
228 /// \brief Store an \p Error.
Manuel Klimek814f9bd2013-11-14 15:49:44 +0000229 void storeError(const ClangTidyError &Error);
230
Alexander Kornienko826b5ad2014-05-09 12:24:09 +0000231 std::vector<ClangTidyError> Errors;
NAKAMURA Takumi338eee12014-03-20 10:53:03 +0000232 DiagnosticsEngine *DiagEngine;
Alexander Kornienkoa4695222014-06-05 13:31:45 +0000233 std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider;
234
235 std::string CurrentFile;
Alexander Kornienkod53d2682014-09-04 14:23:36 +0000236 ClangTidyOptions CurrentOptions;
Alexander Kornienkob3d331d2014-08-06 11:49:10 +0000237 std::unique_ptr<GlobList> CheckFilter;
Jonathan Roelofsd60388a2016-01-13 17:36:41 +0000238 std::unique_ptr<GlobList> WarningAsErrorFilter;
Alexander Kornienkoa4695222014-06-05 13:31:45 +0000239
Aaron Ballmanf36a4252015-08-28 13:20:46 +0000240 LangOptions LangOpts;
241
Alexander Kornienko5d174542014-05-07 09:06:53 +0000242 ClangTidyStats Stats;
Alexander Kornienko09952d22014-03-20 09:38:22 +0000243
Haojian Wuf7692a22016-02-26 09:19:33 +0000244 std::string CurrentBuildDirectory;
245
Alexander Kornienko41bfe8d2014-01-13 10:50:51 +0000246 llvm::DenseMap<unsigned, std::string> CheckNamesByDiagnosticID;
Samuel Benzaquenaedd9942014-10-23 17:23:20 +0000247
248 ProfileData *Profile;
Manuel Klimek814f9bd2013-11-14 15:49:44 +0000249};
250
Daniel Jasperd07c8402013-07-29 08:19:24 +0000251/// \brief A diagnostic consumer that turns each \c Diagnostic into a
252/// \c SourceManager-independent \c ClangTidyError.
253//
254// FIXME: If we move away from unit-tests, this can be moved to a private
255// implementation file.
256class ClangTidyDiagnosticConsumer : public DiagnosticConsumer {
257public:
Alexander Kornienko0ba86b72014-01-09 16:31:25 +0000258 ClangTidyDiagnosticConsumer(ClangTidyContext &Ctx);
Daniel Jasperd07c8402013-07-29 08:19:24 +0000259
260 // FIXME: The concept of converting between FixItHints and Replacements is
261 // more generic and should be pulled out into a more useful Diagnostics
262 // library.
Alexander Kornienkocb9272f2014-02-27 13:14:51 +0000263 void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
Craig Toppera3dbe842014-03-02 10:20:11 +0000264 const Diagnostic &Info) override;
Manuel Klimek814f9bd2013-11-14 15:49:44 +0000265
Alexander Kornienkoa4695222014-06-05 13:31:45 +0000266 /// \brief Flushes the internal diagnostics buffer to the ClangTidyContext.
Craig Toppera3dbe842014-03-02 10:20:11 +0000267 void finish() override;
Daniel Jasperd07c8402013-07-29 08:19:24 +0000268
269private:
Alexander Kornienko54461eb2014-02-06 14:50:10 +0000270 void finalizeLastError();
Alexander Kornienkoa4695222014-06-05 13:31:45 +0000271
Angel Garcia Gomez16693572015-10-16 11:43:49 +0000272 void removeIncompatibleErrors(SmallVectorImpl<ClangTidyError> &Errors) const;
273
Daniel Jasper4d871f92015-08-12 13:16:41 +0000274 /// \brief Returns the \c HeaderFilter constructed for the options set in the
275 /// context.
Angel Garcia Gomez16693572015-10-16 11:43:49 +0000276 llvm::Regex *getHeaderFilter();
Daniel Jasper4d871f92015-08-12 13:16:41 +0000277
Alexander Kornienkoa4695222014-06-05 13:31:45 +0000278 /// \brief Updates \c LastErrorRelatesToUserCode and LastErrorPassesLineFilter
279 /// according to the diagnostic \p Location.
Alexander Kornienkodad4acb2014-05-22 16:07:11 +0000280 void checkFilters(SourceLocation Location);
281 bool passesLineFilter(StringRef FileName, unsigned LineNumber) const;
Manuel Klimek814f9bd2013-11-14 15:49:44 +0000282
Daniel Jasperd07c8402013-07-29 08:19:24 +0000283 ClangTidyContext &Context;
Ahmed Charles6a2dc5c2014-03-09 09:24:40 +0000284 std::unique_ptr<DiagnosticsEngine> Diags;
Manuel Klimek814f9bd2013-11-14 15:49:44 +0000285 SmallVector<ClangTidyError, 8> Errors;
Alexander Kornienkoa4695222014-06-05 13:31:45 +0000286 std::unique_ptr<llvm::Regex> HeaderFilter;
Alexander Kornienko54461eb2014-02-06 14:50:10 +0000287 bool LastErrorRelatesToUserCode;
Alexander Kornienkodad4acb2014-05-22 16:07:11 +0000288 bool LastErrorPassesLineFilter;
Malcolm Parsonscb2e7492016-11-02 21:14:22 +0000289 bool LastErrorWasIgnored;
Daniel Jasperd07c8402013-07-29 08:19:24 +0000290};
291
292} // end namespace tidy
293} // end namespace clang
294
Alexander Kornienko66580552015-03-09 16:52:33 +0000295#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYDIAGNOSTICCONSUMER_H