blob: 107a7817a6fb7fc43664084251edc7bf59c0113d [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
10#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANG_TIDY_DIAGNOSTIC_CONSUMER_H
11#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANG_TIDY_DIAGNOSTIC_CONSUMER_H
12
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"
Alexander Kornienko09952d22014-03-20 09:38:22 +000018#include "llvm/Support/Regex.h"
Daniel Jasperd07c8402013-07-29 08:19:24 +000019
20namespace clang {
21
Alexander Kornienkoad216882014-07-14 14:10:03 +000022class ASTContext;
Daniel Jasperd07c8402013-07-29 08:19:24 +000023class CompilerInstance;
24namespace ast_matchers {
25class MatchFinder;
26}
27namespace tooling {
28class CompilationDatabase;
29}
30
31namespace tidy {
32
Manuel Klimek814f9bd2013-11-14 15:49:44 +000033/// \brief A message from a clang-tidy check.
34///
35/// Note that this is independent of a \c SourceManager.
36struct ClangTidyMessage {
37 ClangTidyMessage(StringRef Message = "");
38 ClangTidyMessage(StringRef Message, const SourceManager &Sources,
39 SourceLocation Loc);
40 std::string Message;
41 std::string FilePath;
42 unsigned FileOffset;
43};
44
45/// \brief A detected error complete with information to display diagnostic and
46/// automatic fix.
47///
48/// This is used as an intermediate format to transport Diagnostics without a
49/// dependency on a SourceManager.
50///
51/// FIXME: Make Diagnostics flexible enough to support this directly.
52struct ClangTidyError {
Alexander Kornienko348cae82014-06-02 20:44:32 +000053 enum Level {
54 Warning = DiagnosticsEngine::Warning,
55 Error = DiagnosticsEngine::Error
56 };
57
58 ClangTidyError(StringRef CheckName, Level DiagLevel);
Manuel Klimek814f9bd2013-11-14 15:49:44 +000059
Alexander Kornienko41bfe8d2014-01-13 10:50:51 +000060 std::string CheckName;
Manuel Klimek814f9bd2013-11-14 15:49:44 +000061 ClangTidyMessage Message;
62 tooling::Replacements Fix;
63 SmallVector<ClangTidyMessage, 1> Notes;
Alexander Kornienko348cae82014-06-02 20:44:32 +000064
65 Level DiagLevel;
Manuel Klimek814f9bd2013-11-14 15:49:44 +000066};
67
Alexander Kornienkob3d331d2014-08-06 11:49:10 +000068/// \brief Read-only set of strings represented as a list of positive and
69/// negative globs. Positive globs add all matched strings to the set, negative
70/// globs remove them in the order of appearance in the list.
71class GlobList {
Alexander Kornienko09952d22014-03-20 09:38:22 +000072public:
Alexander Kornienkoa4695222014-06-05 13:31:45 +000073 /// \brief \p GlobList is a comma-separated list of globs (only '*'
74 /// metacharacter is supported) with optional '-' prefix to denote exclusion.
Alexander Kornienkob3d331d2014-08-06 11:49:10 +000075 GlobList(StringRef Globs);
Alexander Kornienkoa4695222014-06-05 13:31:45 +000076
Alexander Kornienkob3d331d2014-08-06 11:49:10 +000077 /// \brief Returns \c true if the pattern matches \p S. The result is the last
78 /// matching glob's Positive flag.
79 bool contains(StringRef S) { return contains(S, false); }
Alexander Kornienko09952d22014-03-20 09:38:22 +000080
81private:
Alexander Kornienkob3d331d2014-08-06 11:49:10 +000082 bool contains(StringRef S, bool Contains);
Alexander Kornienko23fe9592014-05-15 14:27:36 +000083
84 bool Positive;
85 llvm::Regex Regex;
Alexander Kornienkob3d331d2014-08-06 11:49:10 +000086 std::unique_ptr<GlobList> NextGlob;
Alexander Kornienko09952d22014-03-20 09:38:22 +000087};
88
Alexander Kornienkoa4695222014-06-05 13:31:45 +000089/// \brief Contains displayed and ignored diagnostic counters for a ClangTidy
90/// run.
Alexander Kornienko5d174542014-05-07 09:06:53 +000091struct ClangTidyStats {
92 ClangTidyStats()
93 : ErrorsDisplayed(0), ErrorsIgnoredCheckFilter(0), ErrorsIgnoredNOLINT(0),
Alexander Kornienkodad4acb2014-05-22 16:07:11 +000094 ErrorsIgnoredNonUserCode(0), ErrorsIgnoredLineFilter(0) {}
Alexander Kornienko5d174542014-05-07 09:06:53 +000095
96 unsigned ErrorsDisplayed;
97 unsigned ErrorsIgnoredCheckFilter;
98 unsigned ErrorsIgnoredNOLINT;
99 unsigned ErrorsIgnoredNonUserCode;
Alexander Kornienkodad4acb2014-05-22 16:07:11 +0000100 unsigned ErrorsIgnoredLineFilter;
101
102 unsigned errorsIgnored() const {
103 return ErrorsIgnoredNOLINT + ErrorsIgnoredCheckFilter +
104 ErrorsIgnoredNonUserCode + ErrorsIgnoredLineFilter;
105 }
Alexander Kornienko5d174542014-05-07 09:06:53 +0000106};
107
Manuel Klimek814f9bd2013-11-14 15:49:44 +0000108/// \brief Every \c ClangTidyCheck reports errors through a \c DiagnosticEngine
109/// provided by this context.
110///
111/// A \c ClangTidyCheck always has access to the active context to report
112/// warnings like:
113/// \code
114/// Context->Diag(Loc, "Single-argument constructors must be explicit")
115/// << FixItHint::CreateInsertion(Loc, "explicit ");
116/// \endcode
117class ClangTidyContext {
118public:
Alexander Kornienkoa4695222014-06-05 13:31:45 +0000119 /// \brief Initializes \c ClangTidyContext instance.
120 ///
121 /// Takes ownership of the \c OptionsProvider.
122 ClangTidyContext(ClangTidyOptionsProvider *OptionsProvider);
Manuel Klimek814f9bd2013-11-14 15:49:44 +0000123
124 /// \brief Report any errors detected using this method.
125 ///
126 /// This is still under heavy development and will likely change towards using
127 /// tablegen'd diagnostic IDs.
128 /// FIXME: Figure out a way to manage ID spaces.
Alexander Kornienko41bfe8d2014-01-13 10:50:51 +0000129 DiagnosticBuilder diag(StringRef CheckName, SourceLocation Loc,
Alexander Kornienko54461eb2014-02-06 14:50:10 +0000130 StringRef Message,
131 DiagnosticIDs::Level Level = DiagnosticIDs::Warning);
Manuel Klimek814f9bd2013-11-14 15:49:44 +0000132
Manuel Klimek814f9bd2013-11-14 15:49:44 +0000133 /// \brief Sets the \c SourceManager of the used \c DiagnosticsEngine.
134 ///
135 /// This is called from the \c ClangTidyCheck base class.
136 void setSourceManager(SourceManager *SourceMgr);
137
Alexander Kornienkoa4695222014-06-05 13:31:45 +0000138 /// \brief Should be called when starting to process new translation unit.
139 void setCurrentFile(StringRef File);
140
Alexander Kornienkoad216882014-07-14 14:10:03 +0000141 /// \brief Sets ASTContext for the current translation unit.
142 void setASTContext(ASTContext *Context);
143
Alexander Kornienko41bfe8d2014-01-13 10:50:51 +0000144 /// \brief Returns the name of the clang-tidy check which produced this
145 /// diagnostic ID.
146 StringRef getCheckName(unsigned DiagnosticID) const;
147
Alexander Kornienkoa4695222014-06-05 13:31:45 +0000148 /// \brief Returns check filter for the \c CurrentFile.
Alexander Kornienkob3d331d2014-08-06 11:49:10 +0000149 GlobList &getChecksFilter();
Alexander Kornienkoa4695222014-06-05 13:31:45 +0000150
151 /// \brief Returns global options.
152 const ClangTidyGlobalOptions &getGlobalOptions() const;
153
154 /// \brief Returns options for \c CurrentFile.
155 const ClangTidyOptions &getOptions() const;
156
157 /// \brief Returns \c ClangTidyStats containing issued and ignored diagnostic
158 /// counters.
Alexander Kornienko5d174542014-05-07 09:06:53 +0000159 const ClangTidyStats &getStats() const { return Stats; }
Alexander Kornienkoa4695222014-06-05 13:31:45 +0000160
161 /// \brief Returns all collected errors.
Alexander Kornienko826b5ad2014-05-09 12:24:09 +0000162 const std::vector<ClangTidyError> &getErrors() const { return Errors; }
Alexander Kornienkoa4695222014-06-05 13:31:45 +0000163
164 /// \brief Clears collected errors.
Alexander Kornienkoc0093602014-05-09 15:50:15 +0000165 void clearErrors() { Errors.clear(); }
Alexander Kornienko09952d22014-03-20 09:38:22 +0000166
Manuel Klimek814f9bd2013-11-14 15:49:44 +0000167private:
Alexander Kornienkoa4695222014-06-05 13:31:45 +0000168 // Calls setDiagnosticsEngine() and storeError().
169 friend class ClangTidyDiagnosticConsumer;
Manuel Klimek814f9bd2013-11-14 15:49:44 +0000170
Alexander Kornienkoa4695222014-06-05 13:31:45 +0000171 /// \brief Sets the \c DiagnosticsEngine so that Diagnostics can be generated
172 /// correctly.
173 void setDiagnosticsEngine(DiagnosticsEngine *Engine);
174
175 /// \brief Store an \p Error.
Manuel Klimek814f9bd2013-11-14 15:49:44 +0000176 void storeError(const ClangTidyError &Error);
177
Alexander Kornienko826b5ad2014-05-09 12:24:09 +0000178 std::vector<ClangTidyError> Errors;
NAKAMURA Takumi338eee12014-03-20 10:53:03 +0000179 DiagnosticsEngine *DiagEngine;
Alexander Kornienkoa4695222014-06-05 13:31:45 +0000180 std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider;
181
182 std::string CurrentFile;
Alexander Kornienkob3d331d2014-08-06 11:49:10 +0000183 std::unique_ptr<GlobList> CheckFilter;
Alexander Kornienkoa4695222014-06-05 13:31:45 +0000184
Alexander Kornienko5d174542014-05-07 09:06:53 +0000185 ClangTidyStats Stats;
Alexander Kornienko09952d22014-03-20 09:38:22 +0000186
Alexander Kornienko41bfe8d2014-01-13 10:50:51 +0000187 llvm::DenseMap<unsigned, std::string> CheckNamesByDiagnosticID;
Manuel Klimek814f9bd2013-11-14 15:49:44 +0000188};
189
Daniel Jasperd07c8402013-07-29 08:19:24 +0000190/// \brief A diagnostic consumer that turns each \c Diagnostic into a
191/// \c SourceManager-independent \c ClangTidyError.
192//
193// FIXME: If we move away from unit-tests, this can be moved to a private
194// implementation file.
195class ClangTidyDiagnosticConsumer : public DiagnosticConsumer {
196public:
Alexander Kornienko0ba86b72014-01-09 16:31:25 +0000197 ClangTidyDiagnosticConsumer(ClangTidyContext &Ctx);
Daniel Jasperd07c8402013-07-29 08:19:24 +0000198
199 // FIXME: The concept of converting between FixItHints and Replacements is
200 // more generic and should be pulled out into a more useful Diagnostics
201 // library.
Alexander Kornienkocb9272f2014-02-27 13:14:51 +0000202 void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
Craig Toppera3dbe842014-03-02 10:20:11 +0000203 const Diagnostic &Info) override;
Manuel Klimek814f9bd2013-11-14 15:49:44 +0000204
Alexander Kornienkoa4695222014-06-05 13:31:45 +0000205 /// \brief Sets \c HeaderFilter to the value configured for this file.
206 void BeginSourceFile(const LangOptions &LangOpts,
207 const Preprocessor *PP) override;
208
209 /// \brief Flushes the internal diagnostics buffer to the ClangTidyContext.
Craig Toppera3dbe842014-03-02 10:20:11 +0000210 void finish() override;
Daniel Jasperd07c8402013-07-29 08:19:24 +0000211
212private:
Alexander Kornienko54461eb2014-02-06 14:50:10 +0000213 void finalizeLastError();
Alexander Kornienkoa4695222014-06-05 13:31:45 +0000214
215 /// \brief Updates \c LastErrorRelatesToUserCode and LastErrorPassesLineFilter
216 /// according to the diagnostic \p Location.
Alexander Kornienkodad4acb2014-05-22 16:07:11 +0000217 void checkFilters(SourceLocation Location);
218 bool passesLineFilter(StringRef FileName, unsigned LineNumber) const;
Manuel Klimek814f9bd2013-11-14 15:49:44 +0000219
Daniel Jasperd07c8402013-07-29 08:19:24 +0000220 ClangTidyContext &Context;
Ahmed Charles6a2dc5c2014-03-09 09:24:40 +0000221 std::unique_ptr<DiagnosticsEngine> Diags;
Manuel Klimek814f9bd2013-11-14 15:49:44 +0000222 SmallVector<ClangTidyError, 8> Errors;
Alexander Kornienkoa4695222014-06-05 13:31:45 +0000223 std::unique_ptr<llvm::Regex> HeaderFilter;
Alexander Kornienko54461eb2014-02-06 14:50:10 +0000224 bool LastErrorRelatesToUserCode;
Alexander Kornienkodad4acb2014-05-22 16:07:11 +0000225 bool LastErrorPassesLineFilter;
Daniel Jasperd07c8402013-07-29 08:19:24 +0000226};
227
228} // end namespace tidy
229} // end namespace clang
230
231#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANG_TIDY_DIAGNOSTIC_CONSUMER_H