clang-tools  4.0.0
ClangTidyDiagnosticConsumer.h
Go to the documentation of this file.
1 //===--- 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_CLANGTIDYDIAGNOSTICCONSUMER_H
11 #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYDIAGNOSTICCONSUMER_H
12 
13 #include "ClangTidyOptions.h"
14 #include "clang/Basic/Diagnostic.h"
15 #include "clang/Basic/SourceManager.h"
16 #include "clang/Tooling/Core/Diagnostic.h"
17 #include "clang/Tooling/Refactoring.h"
18 #include "llvm/ADT/DenseMap.h"
19 #include "llvm/ADT/StringMap.h"
20 #include "llvm/Support/Regex.h"
21 #include "llvm/Support/Timer.h"
22 
23 namespace clang {
24 
25 class ASTContext;
26 class CompilerInstance;
27 namespace ast_matchers {
28 class MatchFinder;
29 }
30 namespace tooling {
31 class CompilationDatabase;
32 }
33 
34 namespace tidy {
35 
36 /// \brief A detected error complete with information to display diagnostic and
37 /// automatic fix.
38 ///
39 /// This is used as an intermediate format to transport Diagnostics without a
40 /// dependency on a SourceManager.
41 ///
42 /// FIXME: Make Diagnostics flexible enough to support this directly.
43 struct ClangTidyError : tooling::Diagnostic {
44  ClangTidyError(StringRef CheckName, Level DiagLevel, StringRef BuildDirectory,
45  bool IsWarningAsError);
46 
48 };
49 
50 /// \brief Read-only set of strings represented as a list of positive and
51 /// negative globs. Positive globs add all matched strings to the set, negative
52 /// globs remove them in the order of appearance in the list.
53 class GlobList {
54 public:
55  /// \brief \p GlobList is a comma-separated list of globs (only '*'
56  /// metacharacter is supported) with optional '-' prefix to denote exclusion.
57  GlobList(StringRef Globs);
58 
59  /// \brief Returns \c true if the pattern matches \p S. The result is the last
60  /// matching glob's Positive flag.
61  bool contains(StringRef S) { return contains(S, false); }
62 
63 private:
64  bool contains(StringRef S, bool Contains);
65 
66  bool Positive;
67  llvm::Regex Regex;
68  std::unique_ptr<GlobList> NextGlob;
69 };
70 
71 /// \brief Contains displayed and ignored diagnostic counters for a ClangTidy
72 /// run.
77 
78  unsigned ErrorsDisplayed;
83 
84  unsigned errorsIgnored() const {
87  }
88 };
89 
90 /// \brief Container for clang-tidy profiling data.
91 struct ProfileData {
92  llvm::StringMap<llvm::TimeRecord> Records;
93 };
94 
95 /// \brief Every \c ClangTidyCheck reports errors through a \c DiagnosticsEngine
96 /// provided by this context.
97 ///
98 /// A \c ClangTidyCheck always has access to the active context to report
99 /// warnings like:
100 /// \code
101 /// Context->Diag(Loc, "Single-argument constructors must be explicit")
102 /// << FixItHint::CreateInsertion(Loc, "explicit ");
103 /// \endcode
105 public:
106  /// \brief Initializes \c ClangTidyContext instance.
107  ClangTidyContext(std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider);
108 
109  /// \brief Report any errors detected using this method.
110  ///
111  /// This is still under heavy development and will likely change towards using
112  /// tablegen'd diagnostic IDs.
113  /// FIXME: Figure out a way to manage ID spaces.
114  DiagnosticBuilder diag(StringRef CheckName, SourceLocation Loc,
115  StringRef Message,
116  DiagnosticIDs::Level Level = DiagnosticIDs::Warning);
117 
118  /// \brief Sets the \c SourceManager of the used \c DiagnosticsEngine.
119  ///
120  /// This is called from the \c ClangTidyCheck base class.
121  void setSourceManager(SourceManager *SourceMgr);
122 
123  /// \brief Should be called when starting to process new translation unit.
124  void setCurrentFile(StringRef File);
125 
126  /// \brief Returns the main file name of the current translation unit.
127  StringRef getCurrentFile() const { return CurrentFile; }
128 
129  /// \brief Sets ASTContext for the current translation unit.
130  void setASTContext(ASTContext *Context);
131 
132  /// \brief Gets the language options from the AST context.
133  const LangOptions &getLangOpts() const { return LangOpts; }
134 
135  /// \brief Returns the name of the clang-tidy check which produced this
136  /// diagnostic ID.
137  StringRef getCheckName(unsigned DiagnosticID) const;
138 
139  /// \brief Returns check filter for the \c CurrentFile.
140  ///
141  /// The \c CurrentFile can be changed using \c setCurrentFile.
143 
144  /// \brief Returns check filter for the \c CurrentFile which
145  /// selects checks for upgrade to error.
147 
148  /// \brief Returns global options.
150 
151  /// \brief Returns options for \c CurrentFile.
152  ///
153  /// The \c CurrentFile can be changed using \c setCurrentFile.
154  const ClangTidyOptions &getOptions() const;
155 
156  /// \brief Returns options for \c File. Does not change or depend on
157  /// \c CurrentFile.
158  ClangTidyOptions getOptionsForFile(StringRef File) const;
159 
160  /// \brief Returns \c ClangTidyStats containing issued and ignored diagnostic
161  /// counters.
162  const ClangTidyStats &getStats() const { return Stats; }
163 
164  /// \brief Returns all collected errors.
165  const std::vector<ClangTidyError> &getErrors() const { return Errors; }
166 
167  /// \brief Clears collected errors.
168  void clearErrors() { Errors.clear(); }
169 
170  /// \brief Set the output struct for profile data.
171  ///
172  /// Setting a non-null pointer here will enable profile collection in
173  /// clang-tidy.
174  void setCheckProfileData(ProfileData *Profile);
175  ProfileData *getCheckProfileData() const { return Profile; }
176 
177  /// \brief Should be called when starting to process new translation unit.
178  void setCurrentBuildDirectory(StringRef BuildDirectory) {
179  CurrentBuildDirectory = BuildDirectory;
180  }
181 
182  /// \brief Returns build directory of the current translation unit.
183  const std::string &getCurrentBuildDirectory() {
184  return CurrentBuildDirectory;
185  }
186 
187 private:
188  // Calls setDiagnosticsEngine() and storeError().
190  friend class ClangTidyPluginAction;
191 
192  /// \brief Sets the \c DiagnosticsEngine so that Diagnostics can be generated
193  /// correctly.
194  void setDiagnosticsEngine(DiagnosticsEngine *Engine);
195 
196  /// \brief Store an \p Error.
197  void storeError(const ClangTidyError &Error);
198 
199  std::vector<ClangTidyError> Errors;
200  DiagnosticsEngine *DiagEngine;
201  std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider;
202 
203  std::string CurrentFile;
204  ClangTidyOptions CurrentOptions;
205  std::unique_ptr<GlobList> CheckFilter;
206  std::unique_ptr<GlobList> WarningAsErrorFilter;
207 
208  LangOptions LangOpts;
209 
210  ClangTidyStats Stats;
211 
212  std::string CurrentBuildDirectory;
213 
214  llvm::DenseMap<unsigned, std::string> CheckNamesByDiagnosticID;
215 
216  ProfileData *Profile;
217 };
218 
219 /// \brief A diagnostic consumer that turns each \c Diagnostic into a
220 /// \c SourceManager-independent \c ClangTidyError.
221 //
222 // FIXME: If we move away from unit-tests, this can be moved to a private
223 // implementation file.
225 public:
227 
228  // FIXME: The concept of converting between FixItHints and Replacements is
229  // more generic and should be pulled out into a more useful Diagnostics
230  // library.
231  void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
232  const Diagnostic &Info) override;
233 
234  /// \brief Flushes the internal diagnostics buffer to the ClangTidyContext.
235  void finish() override;
236 
237 private:
238  void finalizeLastError();
239 
240  void removeIncompatibleErrors(SmallVectorImpl<ClangTidyError> &Errors) const;
241 
242  /// \brief Returns the \c HeaderFilter constructed for the options set in the
243  /// context.
244  llvm::Regex *getHeaderFilter();
245 
246  /// \brief Updates \c LastErrorRelatesToUserCode and LastErrorPassesLineFilter
247  /// according to the diagnostic \p Location.
248  void checkFilters(SourceLocation Location);
249  bool passesLineFilter(StringRef FileName, unsigned LineNumber) const;
250 
251  ClangTidyContext &Context;
252  std::unique_ptr<DiagnosticsEngine> Diags;
253  SmallVector<ClangTidyError, 8> Errors;
254  std::unique_ptr<llvm::Regex> HeaderFilter;
255  bool LastErrorRelatesToUserCode;
256  bool LastErrorPassesLineFilter;
257  bool LastErrorWasIgnored;
258 };
259 
260 } // end namespace tidy
261 } // end namespace clang
262 
263 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYDIAGNOSTICCONSUMER_H
SourceLocation Loc
'#' location in the include directive
LangOptions LangOpts
Definition: ClangTidy.cpp:240
Read-only set of strings represented as a list of positive and negative globs.
GlobList(StringRef Globs)
GlobList is a comma-separated list of globs (only '*' metacharacter is supported) with optional '-' p...
HeaderHandle File
void finish() override
Flushes the internal diagnostics buffer to the ClangTidyContext.
bool contains(StringRef S)
Returns true if the pattern matches S.
Contains options for clang-tidy.
llvm::StringMap< llvm::TimeRecord > Records
StringRef getCurrentFile() const
Returns the main file name of the current translation unit.
const std::vector< ClangTidyError > & getErrors() const
Returns all collected errors.
SourceManager SourceMgr
Definition: ClangTidy.cpp:244
ClangTidyOptions getOptionsForFile(StringRef File) const
Returns options for File.
void setCurrentFile(StringRef File)
Should be called when starting to process new translation unit.
const ClangTidyOptions & getOptions() const
Returns options for CurrentFile.
DiagnosticBuilder diag(StringRef CheckName, SourceLocation Loc, StringRef Message, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Report any errors detected using this method.
void setCheckProfileData(ProfileData *Profile)
Set the output struct for profile data.
ClangTidyContext(std::unique_ptr< ClangTidyOptionsProvider > OptionsProvider)
Initializes ClangTidyContext instance.
ClangTidyError(StringRef CheckName, Level DiagLevel, StringRef BuildDirectory, bool IsWarningAsError)
void setASTContext(ASTContext *Context)
Sets ASTContext for the current translation unit.
A diagnostic consumer that turns each Diagnostic into a SourceManager-independent ClangTidyError...
GlobList & getWarningAsErrorFilter()
Returns check filter for the CurrentFile which selects checks for upgrade to error.
const ClangTidyGlobalOptions & getGlobalOptions() const
Returns global options.
const LangOptions & getLangOpts() const
Gets the language options from the AST context.
void setSourceManager(SourceManager *SourceMgr)
Sets the SourceManager of the used DiagnosticsEngine.
void clearErrors()
Clears collected errors.
const ClangTidyStats & getStats() const
Returns ClangTidyStats containing issued and ignored diagnostic counters.
StringRef getCheckName(unsigned DiagnosticID) const
Returns the name of the clang-tidy check which produced this diagnostic ID.
A detected error complete with information to display diagnostic and automatic fix.
Contains displayed and ignored diagnostic counters for a ClangTidy run.
ClangTidyContext & Context
Definition: ClangTidy.cpp:87
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
The core clang tidy plugin action.
void setCurrentBuildDirectory(StringRef BuildDirectory)
Should be called when starting to process new translation unit.
void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) override
GlobList & getChecksFilter()
Returns check filter for the CurrentFile.
Container for clang-tidy profiling data.
const std::string & getCurrentBuildDirectory()
Returns build directory of the current translation unit.