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