clang-tools  5.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 
110 
111  /// \brief Report any errors detected using this method.
112  ///
113  /// This is still under heavy development and will likely change towards using
114  /// tablegen'd diagnostic IDs.
115  /// FIXME: Figure out a way to manage ID spaces.
116  DiagnosticBuilder diag(StringRef CheckName, SourceLocation Loc,
117  StringRef Message,
118  DiagnosticIDs::Level Level = DiagnosticIDs::Warning);
119 
120  /// \brief Sets the \c SourceManager of the used \c DiagnosticsEngine.
121  ///
122  /// This is called from the \c ClangTidyCheck base class.
123  void setSourceManager(SourceManager *SourceMgr);
124 
125  /// \brief Should be called when starting to process new translation unit.
126  void setCurrentFile(StringRef File);
127 
128  /// \brief Returns the main file name of the current translation unit.
129  StringRef getCurrentFile() const { return CurrentFile; }
130 
131  /// \brief Sets ASTContext for the current translation unit.
132  void setASTContext(ASTContext *Context);
133 
134  /// \brief Gets the language options from the AST context.
135  const LangOptions &getLangOpts() const { return LangOpts; }
136 
137  /// \brief Returns the name of the clang-tidy check which produced this
138  /// diagnostic ID.
139  StringRef getCheckName(unsigned DiagnosticID) const;
140 
141  /// \brief Returns \c true if the check is enabled for the \c CurrentFile.
142  ///
143  /// The \c CurrentFile can be changed using \c setCurrentFile.
144  bool isCheckEnabled(StringRef CheckName) const;
145 
146  /// \brief Returns \c true if the check should be upgraded to error for the
147  /// \c CurrentFile.
148  bool treatAsError(StringRef CheckName) const;
149 
150  /// \brief Returns global options.
152 
153  /// \brief Returns options for \c CurrentFile.
154  ///
155  /// The \c CurrentFile can be changed using \c setCurrentFile.
156  const ClangTidyOptions &getOptions() const;
157 
158  /// \brief Returns options for \c File. Does not change or depend on
159  /// \c CurrentFile.
160  ClangTidyOptions getOptionsForFile(StringRef File) const;
161 
162  /// \brief Returns \c ClangTidyStats containing issued and ignored diagnostic
163  /// counters.
164  const ClangTidyStats &getStats() const { return Stats; }
165 
166  /// \brief Returns all collected errors.
167  ArrayRef<ClangTidyError> getErrors() const { return Errors; }
168 
169  /// \brief Clears collected errors.
170  void clearErrors() { Errors.clear(); }
171 
172  /// \brief Set the output struct for profile data.
173  ///
174  /// Setting a non-null pointer here will enable profile collection in
175  /// clang-tidy.
176  void setCheckProfileData(ProfileData *Profile);
177  ProfileData *getCheckProfileData() const { return Profile; }
178 
179  /// \brief Should be called when starting to process new translation unit.
180  void setCurrentBuildDirectory(StringRef BuildDirectory) {
181  CurrentBuildDirectory = BuildDirectory;
182  }
183 
184  /// \brief Returns build directory of the current translation unit.
185  const std::string &getCurrentBuildDirectory() {
186  return CurrentBuildDirectory;
187  }
188 
189 private:
190  // Calls setDiagnosticsEngine() and storeError().
192  friend class ClangTidyPluginAction;
193 
194  /// \brief Sets the \c DiagnosticsEngine so that Diagnostics can be generated
195  /// correctly.
196  void setDiagnosticsEngine(DiagnosticsEngine *Engine);
197 
198  /// \brief Store an \p Error.
199  void storeError(const ClangTidyError &Error);
200 
201  std::vector<ClangTidyError> Errors;
202  DiagnosticsEngine *DiagEngine;
203  std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider;
204 
205  std::string CurrentFile;
206  ClangTidyOptions CurrentOptions;
207  class CachedGlobList;
208  std::unique_ptr<CachedGlobList> CheckFilter;
209  std::unique_ptr<CachedGlobList> WarningAsErrorFilter;
210 
211  LangOptions LangOpts;
212 
213  ClangTidyStats Stats;
214 
215  std::string CurrentBuildDirectory;
216 
217  llvm::DenseMap<unsigned, std::string> CheckNamesByDiagnosticID;
218 
219  ProfileData *Profile;
220 };
221 
222 /// \brief A diagnostic consumer that turns each \c Diagnostic into a
223 /// \c SourceManager-independent \c ClangTidyError.
224 //
225 // FIXME: If we move away from unit-tests, this can be moved to a private
226 // implementation file.
228 public:
230  bool RemoveIncompatibleErrors = true);
231 
232  // FIXME: The concept of converting between FixItHints and Replacements is
233  // more generic and should be pulled out into a more useful Diagnostics
234  // library.
235  void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
236  const Diagnostic &Info) override;
237 
238  /// \brief Flushes the internal diagnostics buffer to the ClangTidyContext.
239  void finish() override;
240 
241 private:
242  void finalizeLastError();
243 
244  void removeIncompatibleErrors(SmallVectorImpl<ClangTidyError> &Errors) const;
245 
246  /// \brief Returns the \c HeaderFilter constructed for the options set in the
247  /// context.
248  llvm::Regex *getHeaderFilter();
249 
250  /// \brief Updates \c LastErrorRelatesToUserCode and LastErrorPassesLineFilter
251  /// according to the diagnostic \p Location.
252  void checkFilters(SourceLocation Location);
253  bool passesLineFilter(StringRef FileName, unsigned LineNumber) const;
254 
255  ClangTidyContext &Context;
256  bool RemoveIncompatibleErrors;
257  std::unique_ptr<DiagnosticsEngine> Diags;
258  SmallVector<ClangTidyError, 8> Errors;
259  std::unique_ptr<llvm::Regex> HeaderFilter;
260  bool LastErrorRelatesToUserCode;
261  bool LastErrorPassesLineFilter;
262  bool LastErrorWasIgnored;
263 };
264 
265 } // end namespace tidy
266 } // end namespace clang
267 
268 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYDIAGNOSTICCONSUMER_H
SourceLocation Loc
'#' location in the include directive
LangOptions LangOpts
Definition: ClangTidy.cpp:253
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.
SourceManager SourceMgr
Definition: ClangTidy.cpp:257
ArrayRef< ClangTidyError > getErrors() const
Returns all collected errors.
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...
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.
bool treatAsError(StringRef CheckName) const
Returns true if the check should be upgraded to error for the CurrentFile.
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
ClangTidyDiagnosticConsumer(ClangTidyContext &Ctx, bool RemoveIncompatibleErrors=true)
bool isCheckEnabled(StringRef CheckName) const
Returns true if the check is enabled for the CurrentFile.
Container for clang-tidy profiling data.
const std::string & getCurrentBuildDirectory()
Returns build directory of the current translation unit.