2013-07-29 16:19:24 +08:00
|
|
|
//===--- ClangTidyDiagnosticConsumer.h - clang-tidy -------------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2015-03-10 00:52:33 +08:00
|
|
|
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYDIAGNOSTICCONSUMER_H
|
|
|
|
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYDIAGNOSTICCONSUMER_H
|
2013-07-29 16:19:24 +08:00
|
|
|
|
2014-05-05 22:54:47 +08:00
|
|
|
#include "ClangTidyOptions.h"
|
2013-07-29 16:19:24 +08:00
|
|
|
#include "clang/Basic/Diagnostic.h"
|
|
|
|
#include "clang/Basic/SourceManager.h"
|
|
|
|
#include "clang/Tooling/Refactoring.h"
|
2014-01-13 18:50:51 +08:00
|
|
|
#include "llvm/ADT/DenseMap.h"
|
2014-10-24 01:23:20 +08:00
|
|
|
#include "llvm/ADT/StringMap.h"
|
2014-03-20 17:38:22 +08:00
|
|
|
#include "llvm/Support/Regex.h"
|
2014-10-24 01:23:20 +08:00
|
|
|
#include "llvm/Support/Timer.h"
|
2013-07-29 16:19:24 +08:00
|
|
|
|
|
|
|
namespace clang {
|
|
|
|
|
2014-07-14 22:10:03 +08:00
|
|
|
class ASTContext;
|
2013-07-29 16:19:24 +08:00
|
|
|
class CompilerInstance;
|
|
|
|
namespace ast_matchers {
|
|
|
|
class MatchFinder;
|
|
|
|
}
|
|
|
|
namespace tooling {
|
|
|
|
class CompilationDatabase;
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace tidy {
|
|
|
|
|
2013-11-14 23:49:44 +08:00
|
|
|
/// \brief A message from a clang-tidy check.
|
|
|
|
///
|
|
|
|
/// Note that this is independent of a \c SourceManager.
|
|
|
|
struct ClangTidyMessage {
|
|
|
|
ClangTidyMessage(StringRef Message = "");
|
|
|
|
ClangTidyMessage(StringRef Message, const SourceManager &Sources,
|
|
|
|
SourceLocation Loc);
|
|
|
|
std::string Message;
|
|
|
|
std::string FilePath;
|
|
|
|
unsigned FileOffset;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// \brief A detected error complete with information to display diagnostic and
|
|
|
|
/// automatic fix.
|
|
|
|
///
|
|
|
|
/// This is used as an intermediate format to transport Diagnostics without a
|
|
|
|
/// dependency on a SourceManager.
|
|
|
|
///
|
|
|
|
/// FIXME: Make Diagnostics flexible enough to support this directly.
|
|
|
|
struct ClangTidyError {
|
2014-06-03 04:44:32 +08:00
|
|
|
enum Level {
|
|
|
|
Warning = DiagnosticsEngine::Warning,
|
|
|
|
Error = DiagnosticsEngine::Error
|
|
|
|
};
|
|
|
|
|
2016-02-26 17:19:33 +08:00
|
|
|
ClangTidyError(StringRef CheckName, Level DiagLevel, bool IsWarningAsError,
|
|
|
|
StringRef BuildDirectory);
|
2013-11-14 23:49:44 +08:00
|
|
|
|
2014-01-13 18:50:51 +08:00
|
|
|
std::string CheckName;
|
2013-11-14 23:49:44 +08:00
|
|
|
ClangTidyMessage Message;
|
|
|
|
tooling::Replacements Fix;
|
|
|
|
SmallVector<ClangTidyMessage, 1> Notes;
|
2014-06-03 04:44:32 +08:00
|
|
|
|
2016-02-26 17:19:33 +08:00
|
|
|
// A build directory of the diagnostic source file.
|
|
|
|
//
|
|
|
|
// It's an absolute path which is `directory` field of the source file in
|
|
|
|
// compilation database. If users don't specify the compilation database
|
|
|
|
// directory, it is the current directory where clang-tidy runs.
|
|
|
|
//
|
|
|
|
// Note: it is empty in unittest.
|
|
|
|
std::string BuildDirectory;
|
|
|
|
|
2014-06-03 04:44:32 +08:00
|
|
|
Level DiagLevel;
|
2016-01-14 01:36:41 +08:00
|
|
|
bool IsWarningAsError;
|
2013-11-14 23:49:44 +08:00
|
|
|
};
|
|
|
|
|
2014-08-06 19:49:10 +08:00
|
|
|
/// \brief Read-only set of strings represented as a list of positive and
|
|
|
|
/// negative globs. Positive globs add all matched strings to the set, negative
|
|
|
|
/// globs remove them in the order of appearance in the list.
|
|
|
|
class GlobList {
|
2014-03-20 17:38:22 +08:00
|
|
|
public:
|
2014-06-05 21:31:45 +08:00
|
|
|
/// \brief \p GlobList is a comma-separated list of globs (only '*'
|
|
|
|
/// metacharacter is supported) with optional '-' prefix to denote exclusion.
|
2014-08-06 19:49:10 +08:00
|
|
|
GlobList(StringRef Globs);
|
2014-06-05 21:31:45 +08:00
|
|
|
|
2014-08-06 19:49:10 +08:00
|
|
|
/// \brief Returns \c true if the pattern matches \p S. The result is the last
|
|
|
|
/// matching glob's Positive flag.
|
|
|
|
bool contains(StringRef S) { return contains(S, false); }
|
2014-03-20 17:38:22 +08:00
|
|
|
|
|
|
|
private:
|
2014-08-06 19:49:10 +08:00
|
|
|
bool contains(StringRef S, bool Contains);
|
Change the behavior of clang-tidy -checks=, remove -disable-checks.
Summary:
Make checks filtering more intuitive and easy to use. Remove
-disable-checks and change the format of -checks= to a comma-separated list of
globs with optional '-' prefix to denote exclusion. The -checks= option is now
cumulative, so it modifies defaults, not overrides them. Each glob adds or
removes to the current set of checks, so the filter can be refined or overriden
by adding globs.
Example:
The default value for -checks= is
'*,-clang-analyzer-alpha*,-llvm-include-order,-llvm-namespace-comment,-google-*',
which allows all checks except for the ones named clang-analyzer-alpha* and
others specified with the leading '-'. To allow all google-* checks one can
write:
clang-tidy -checks=google-* ...
If one needs only google-* checks, we first need to remove everything (-*):
clang-tidy -checks=-*,google-*
etc.
I'm not sure if we need to change something here, so I didn't touch the docs
yet.
Reviewers: klimek, alexfh
Reviewed By: alexfh
Subscribers: cfe-commits
Differential Revision: http://reviews.llvm.org/D3770
llvm-svn: 208883
2014-05-15 22:27:36 +08:00
|
|
|
|
|
|
|
bool Positive;
|
|
|
|
llvm::Regex Regex;
|
2014-08-06 19:49:10 +08:00
|
|
|
std::unique_ptr<GlobList> NextGlob;
|
2014-03-20 17:38:22 +08:00
|
|
|
};
|
|
|
|
|
2014-06-05 21:31:45 +08:00
|
|
|
/// \brief Contains displayed and ignored diagnostic counters for a ClangTidy
|
|
|
|
/// run.
|
2014-05-07 17:06:53 +08:00
|
|
|
struct ClangTidyStats {
|
|
|
|
ClangTidyStats()
|
|
|
|
: ErrorsDisplayed(0), ErrorsIgnoredCheckFilter(0), ErrorsIgnoredNOLINT(0),
|
2014-05-23 00:07:11 +08:00
|
|
|
ErrorsIgnoredNonUserCode(0), ErrorsIgnoredLineFilter(0) {}
|
2014-05-07 17:06:53 +08:00
|
|
|
|
|
|
|
unsigned ErrorsDisplayed;
|
|
|
|
unsigned ErrorsIgnoredCheckFilter;
|
|
|
|
unsigned ErrorsIgnoredNOLINT;
|
|
|
|
unsigned ErrorsIgnoredNonUserCode;
|
2014-05-23 00:07:11 +08:00
|
|
|
unsigned ErrorsIgnoredLineFilter;
|
|
|
|
|
|
|
|
unsigned errorsIgnored() const {
|
|
|
|
return ErrorsIgnoredNOLINT + ErrorsIgnoredCheckFilter +
|
|
|
|
ErrorsIgnoredNonUserCode + ErrorsIgnoredLineFilter;
|
|
|
|
}
|
2014-05-07 17:06:53 +08:00
|
|
|
};
|
|
|
|
|
2014-10-24 01:23:20 +08:00
|
|
|
/// \brief Container for clang-tidy profiling data.
|
|
|
|
struct ProfileData {
|
|
|
|
llvm::StringMap<llvm::TimeRecord> Records;
|
|
|
|
};
|
|
|
|
|
2014-12-19 23:37:02 +08:00
|
|
|
/// \brief Every \c ClangTidyCheck reports errors through a \c DiagnosticsEngine
|
2013-11-14 23:49:44 +08:00
|
|
|
/// provided by this context.
|
|
|
|
///
|
|
|
|
/// A \c ClangTidyCheck always has access to the active context to report
|
|
|
|
/// warnings like:
|
|
|
|
/// \code
|
|
|
|
/// Context->Diag(Loc, "Single-argument constructors must be explicit")
|
|
|
|
/// << FixItHint::CreateInsertion(Loc, "explicit ");
|
|
|
|
/// \endcode
|
|
|
|
class ClangTidyContext {
|
|
|
|
public:
|
2014-06-05 21:31:45 +08:00
|
|
|
/// \brief Initializes \c ClangTidyContext instance.
|
2014-09-04 22:23:36 +08:00
|
|
|
ClangTidyContext(std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider);
|
2013-11-14 23:49:44 +08:00
|
|
|
|
|
|
|
/// \brief Report any errors detected using this method.
|
|
|
|
///
|
|
|
|
/// This is still under heavy development and will likely change towards using
|
|
|
|
/// tablegen'd diagnostic IDs.
|
|
|
|
/// FIXME: Figure out a way to manage ID spaces.
|
2014-01-13 18:50:51 +08:00
|
|
|
DiagnosticBuilder diag(StringRef CheckName, SourceLocation Loc,
|
2014-02-06 22:50:10 +08:00
|
|
|
StringRef Message,
|
|
|
|
DiagnosticIDs::Level Level = DiagnosticIDs::Warning);
|
2013-11-14 23:49:44 +08:00
|
|
|
|
|
|
|
/// \brief Sets the \c SourceManager of the used \c DiagnosticsEngine.
|
|
|
|
///
|
|
|
|
/// This is called from the \c ClangTidyCheck base class.
|
|
|
|
void setSourceManager(SourceManager *SourceMgr);
|
|
|
|
|
2014-06-05 21:31:45 +08:00
|
|
|
/// \brief Should be called when starting to process new translation unit.
|
|
|
|
void setCurrentFile(StringRef File);
|
|
|
|
|
2015-05-21 22:08:56 +08:00
|
|
|
/// \brief Returns the main file name of the current translation unit.
|
|
|
|
StringRef getCurrentFile() const { return CurrentFile; }
|
|
|
|
|
2014-07-14 22:10:03 +08:00
|
|
|
/// \brief Sets ASTContext for the current translation unit.
|
|
|
|
void setASTContext(ASTContext *Context);
|
|
|
|
|
2015-11-10 00:28:11 +08:00
|
|
|
/// \brief Gets the language options from the AST context.
|
2016-02-26 07:57:23 +08:00
|
|
|
const LangOptions &getLangOpts() const { return LangOpts; }
|
2015-08-28 21:20:46 +08:00
|
|
|
|
2014-01-13 18:50:51 +08:00
|
|
|
/// \brief Returns the name of the clang-tidy check which produced this
|
|
|
|
/// diagnostic ID.
|
|
|
|
StringRef getCheckName(unsigned DiagnosticID) const;
|
|
|
|
|
2014-06-05 21:31:45 +08:00
|
|
|
/// \brief Returns check filter for the \c CurrentFile.
|
2015-11-10 00:28:11 +08:00
|
|
|
///
|
|
|
|
/// The \c CurrentFile can be changed using \c setCurrentFile.
|
2014-08-06 19:49:10 +08:00
|
|
|
GlobList &getChecksFilter();
|
2014-06-05 21:31:45 +08:00
|
|
|
|
2016-01-08 23:50:51 +08:00
|
|
|
/// \brief Returns true if the check name is enabled for the \c CurrentFile.
|
|
|
|
bool isCheckEnabled(StringRef CheckName) const;
|
|
|
|
|
2016-01-14 01:36:41 +08:00
|
|
|
/// \brief Returns check filter for the \c CurrentFile which
|
|
|
|
/// selects checks for upgrade to error.
|
|
|
|
GlobList &getWarningAsErrorFilter();
|
|
|
|
|
2014-06-05 21:31:45 +08:00
|
|
|
/// \brief Returns global options.
|
|
|
|
const ClangTidyGlobalOptions &getGlobalOptions() const;
|
|
|
|
|
|
|
|
/// \brief Returns options for \c CurrentFile.
|
2015-11-10 00:28:11 +08:00
|
|
|
///
|
|
|
|
/// The \c CurrentFile can be changed using \c setCurrentFile.
|
2014-06-05 21:31:45 +08:00
|
|
|
const ClangTidyOptions &getOptions() const;
|
|
|
|
|
2015-11-10 00:28:11 +08:00
|
|
|
/// \brief Returns options for \c File. Does not change or depend on
|
|
|
|
/// \c CurrentFile.
|
|
|
|
ClangTidyOptions getOptionsForFile(StringRef File) const;
|
|
|
|
|
2014-06-05 21:31:45 +08:00
|
|
|
/// \brief Returns \c ClangTidyStats containing issued and ignored diagnostic
|
|
|
|
/// counters.
|
2014-05-07 17:06:53 +08:00
|
|
|
const ClangTidyStats &getStats() const { return Stats; }
|
2014-06-05 21:31:45 +08:00
|
|
|
|
|
|
|
/// \brief Returns all collected errors.
|
2014-05-09 20:24:09 +08:00
|
|
|
const std::vector<ClangTidyError> &getErrors() const { return Errors; }
|
2014-06-05 21:31:45 +08:00
|
|
|
|
|
|
|
/// \brief Clears collected errors.
|
2014-05-09 23:50:15 +08:00
|
|
|
void clearErrors() { Errors.clear(); }
|
2014-03-20 17:38:22 +08:00
|
|
|
|
2014-10-24 01:23:20 +08:00
|
|
|
/// \brief Set the output struct for profile data.
|
|
|
|
///
|
|
|
|
/// Setting a non-null pointer here will enable profile collection in
|
|
|
|
/// clang-tidy.
|
2015-10-16 19:43:49 +08:00
|
|
|
void setCheckProfileData(ProfileData *Profile);
|
|
|
|
ProfileData *getCheckProfileData() const { return Profile; }
|
2014-10-24 01:23:20 +08:00
|
|
|
|
2016-02-26 17:19:33 +08:00
|
|
|
/// \brief Should be called when starting to process new translation unit.
|
|
|
|
void setCurrentBuildDirectory(StringRef BuildDirectory) {
|
|
|
|
CurrentBuildDirectory = BuildDirectory;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Returns build directory of the current translation unit.
|
|
|
|
const std::string &getCurrentBuildDirectory() {
|
|
|
|
return CurrentBuildDirectory;
|
|
|
|
}
|
|
|
|
|
2013-11-14 23:49:44 +08:00
|
|
|
private:
|
2014-06-05 21:31:45 +08:00
|
|
|
// Calls setDiagnosticsEngine() and storeError().
|
|
|
|
friend class ClangTidyDiagnosticConsumer;
|
2016-03-03 16:58:12 +08:00
|
|
|
friend class ClangTidyPluginAction;
|
2013-11-14 23:49:44 +08:00
|
|
|
|
2014-06-05 21:31:45 +08:00
|
|
|
/// \brief Sets the \c DiagnosticsEngine so that Diagnostics can be generated
|
|
|
|
/// correctly.
|
|
|
|
void setDiagnosticsEngine(DiagnosticsEngine *Engine);
|
|
|
|
|
|
|
|
/// \brief Store an \p Error.
|
2013-11-14 23:49:44 +08:00
|
|
|
void storeError(const ClangTidyError &Error);
|
|
|
|
|
2014-05-09 20:24:09 +08:00
|
|
|
std::vector<ClangTidyError> Errors;
|
2014-03-20 18:53:03 +08:00
|
|
|
DiagnosticsEngine *DiagEngine;
|
2014-06-05 21:31:45 +08:00
|
|
|
std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider;
|
|
|
|
|
|
|
|
std::string CurrentFile;
|
2014-09-04 22:23:36 +08:00
|
|
|
ClangTidyOptions CurrentOptions;
|
2014-08-06 19:49:10 +08:00
|
|
|
std::unique_ptr<GlobList> CheckFilter;
|
2016-01-14 01:36:41 +08:00
|
|
|
std::unique_ptr<GlobList> WarningAsErrorFilter;
|
2014-06-05 21:31:45 +08:00
|
|
|
|
2015-08-28 21:20:46 +08:00
|
|
|
LangOptions LangOpts;
|
|
|
|
|
2014-05-07 17:06:53 +08:00
|
|
|
ClangTidyStats Stats;
|
2014-03-20 17:38:22 +08:00
|
|
|
|
2016-02-26 17:19:33 +08:00
|
|
|
std::string CurrentBuildDirectory;
|
|
|
|
|
2014-01-13 18:50:51 +08:00
|
|
|
llvm::DenseMap<unsigned, std::string> CheckNamesByDiagnosticID;
|
2014-10-24 01:23:20 +08:00
|
|
|
|
|
|
|
ProfileData *Profile;
|
2013-11-14 23:49:44 +08:00
|
|
|
};
|
|
|
|
|
2013-07-29 16:19:24 +08:00
|
|
|
/// \brief A diagnostic consumer that turns each \c Diagnostic into a
|
|
|
|
/// \c SourceManager-independent \c ClangTidyError.
|
|
|
|
//
|
|
|
|
// FIXME: If we move away from unit-tests, this can be moved to a private
|
|
|
|
// implementation file.
|
|
|
|
class ClangTidyDiagnosticConsumer : public DiagnosticConsumer {
|
|
|
|
public:
|
2014-01-10 00:31:25 +08:00
|
|
|
ClangTidyDiagnosticConsumer(ClangTidyContext &Ctx);
|
2013-07-29 16:19:24 +08:00
|
|
|
|
|
|
|
// FIXME: The concept of converting between FixItHints and Replacements is
|
|
|
|
// more generic and should be pulled out into a more useful Diagnostics
|
|
|
|
// library.
|
2014-02-27 21:14:51 +08:00
|
|
|
void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
|
2014-03-02 18:20:11 +08:00
|
|
|
const Diagnostic &Info) override;
|
2013-11-14 23:49:44 +08:00
|
|
|
|
2014-06-05 21:31:45 +08:00
|
|
|
/// \brief Flushes the internal diagnostics buffer to the ClangTidyContext.
|
2014-03-02 18:20:11 +08:00
|
|
|
void finish() override;
|
2013-11-14 23:49:44 +08:00
|
|
|
|
|
|
|
private:
|
2014-02-06 22:50:10 +08:00
|
|
|
void finalizeLastError();
|
2014-06-05 21:31:45 +08:00
|
|
|
|
2015-10-16 19:43:49 +08:00
|
|
|
void removeIncompatibleErrors(SmallVectorImpl<ClangTidyError> &Errors) const;
|
|
|
|
|
2015-08-12 21:16:41 +08:00
|
|
|
/// \brief Returns the \c HeaderFilter constructed for the options set in the
|
|
|
|
/// context.
|
2015-10-16 19:43:49 +08:00
|
|
|
llvm::Regex *getHeaderFilter();
|
2015-08-12 21:16:41 +08:00
|
|
|
|
2014-06-05 21:31:45 +08:00
|
|
|
/// \brief Updates \c LastErrorRelatesToUserCode and LastErrorPassesLineFilter
|
|
|
|
/// according to the diagnostic \p Location.
|
2014-05-23 00:07:11 +08:00
|
|
|
void checkFilters(SourceLocation Location);
|
|
|
|
bool passesLineFilter(StringRef FileName, unsigned LineNumber) const;
|
2013-07-29 16:19:24 +08:00
|
|
|
|
|
|
|
ClangTidyContext &Context;
|
2014-03-09 17:24:40 +08:00
|
|
|
std::unique_ptr<DiagnosticsEngine> Diags;
|
2013-11-14 23:49:44 +08:00
|
|
|
SmallVector<ClangTidyError, 8> Errors;
|
2014-06-05 21:31:45 +08:00
|
|
|
std::unique_ptr<llvm::Regex> HeaderFilter;
|
2014-02-06 22:50:10 +08:00
|
|
|
bool LastErrorRelatesToUserCode;
|
2014-05-23 00:07:11 +08:00
|
|
|
bool LastErrorPassesLineFilter;
|
2013-07-29 16:19:24 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
} // end namespace tidy
|
|
|
|
} // end namespace clang
|
|
|
|
|
2015-03-10 00:52:33 +08:00
|
|
|
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYDIAGNOSTICCONSUMER_H
|