forked from OSchip/llvm-project
Add flag --enable-check-profile to clang-tidy.
Summary: Add flag --enable-check-profile to clang-tidy. It turns on per-matcher profiles in MatchFinder and prints a report to stderr at the end. Reviewers: alexfh Subscribers: curdeius, cfe-commits Differential Revision: http://reviews.llvm.org/D5937 llvm-svn: 220491
This commit is contained in:
parent
adffd01498
commit
aedd994560
|
@ -216,8 +216,13 @@ ClangTidyASTConsumerFactory::CreateASTConsumer(
|
|||
std::vector<std::unique_ptr<ClangTidyCheck>> Checks;
|
||||
CheckFactories->createChecks(&Context, Checks);
|
||||
|
||||
ast_matchers::MatchFinder::MatchFinderOptions FinderOptions;
|
||||
if (auto *P = Context.getCheckProfileData())
|
||||
FinderOptions.CheckProfiling.emplace(P->Records);
|
||||
|
||||
std::unique_ptr<ast_matchers::MatchFinder> Finder(
|
||||
new ast_matchers::MatchFinder);
|
||||
new ast_matchers::MatchFinder(std::move(FinderOptions)));
|
||||
|
||||
for (auto &Check : Checks) {
|
||||
Check->registerMatchers(&*Finder);
|
||||
Check->registerPPCallbacks(Compiler);
|
||||
|
@ -356,9 +361,12 @@ ClangTidyStats
|
|||
runClangTidy(std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider,
|
||||
const tooling::CompilationDatabase &Compilations,
|
||||
ArrayRef<std::string> InputFiles,
|
||||
std::vector<ClangTidyError> *Errors) {
|
||||
std::vector<ClangTidyError> *Errors, ProfileData *Profile) {
|
||||
ClangTool Tool(Compilations, InputFiles);
|
||||
clang::tidy::ClangTidyContext Context(std::move(OptionsProvider));
|
||||
if (Profile)
|
||||
Context.setCheckProfileData(Profile);
|
||||
|
||||
ClangTidyDiagnosticConsumer DiagConsumer(Context);
|
||||
|
||||
Tool.setDiagnosticConsumer(&DiagConsumer);
|
||||
|
|
|
@ -152,6 +152,7 @@ public:
|
|||
|
||||
private:
|
||||
void run(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
||||
StringRef getID() const override { return CheckName; }
|
||||
std::string CheckName;
|
||||
ClangTidyContext *Context;
|
||||
|
||||
|
@ -196,11 +197,15 @@ std::vector<std::string> getCheckNames(const ClangTidyOptions &Options);
|
|||
ClangTidyOptions::OptionMap getCheckOptions(const ClangTidyOptions &Options);
|
||||
|
||||
/// \brief Run a set of clang-tidy checks on a set of files.
|
||||
///
|
||||
/// \param Profile if provided, it enables check profile collection in
|
||||
/// MatchFinder, and will contain the result of the profile.
|
||||
ClangTidyStats
|
||||
runClangTidy(std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider,
|
||||
const tooling::CompilationDatabase &Compilations,
|
||||
ArrayRef<std::string> InputFiles,
|
||||
std::vector<ClangTidyError> *Errors);
|
||||
std::vector<ClangTidyError> *Errors,
|
||||
ProfileData *Profile = nullptr);
|
||||
|
||||
// FIXME: This interface will need to be significantly extended to be useful.
|
||||
// FIXME: Implement confidence levels for displaying/fixing errors.
|
||||
|
|
|
@ -162,7 +162,8 @@ bool GlobList::contains(StringRef S, bool Contains) {
|
|||
|
||||
ClangTidyContext::ClangTidyContext(
|
||||
std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider)
|
||||
: DiagEngine(nullptr), OptionsProvider(std::move(OptionsProvider)) {
|
||||
: DiagEngine(nullptr), OptionsProvider(std::move(OptionsProvider)),
|
||||
Profile(nullptr) {
|
||||
// Before the first translation unit we can get errors related to command-line
|
||||
// parsing, use empty string for the file name in this case.
|
||||
setCurrentFile("");
|
||||
|
@ -221,6 +222,10 @@ const ClangTidyOptions &ClangTidyContext::getOptions() const {
|
|||
return CurrentOptions;
|
||||
}
|
||||
|
||||
void ClangTidyContext::setCheckProfileData(ProfileData *P) {
|
||||
Profile = P;
|
||||
}
|
||||
|
||||
GlobList &ClangTidyContext::getChecksFilter() {
|
||||
assert(CheckFilter != nullptr);
|
||||
return *CheckFilter;
|
||||
|
|
|
@ -15,7 +15,9 @@
|
|||
#include "clang/Basic/SourceManager.h"
|
||||
#include "clang/Tooling/Refactoring.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/Support/Regex.h"
|
||||
#include "llvm/Support/Timer.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
|
@ -105,6 +107,11 @@ struct ClangTidyStats {
|
|||
}
|
||||
};
|
||||
|
||||
/// \brief Container for clang-tidy profiling data.
|
||||
struct ProfileData {
|
||||
llvm::StringMap<llvm::TimeRecord> Records;
|
||||
};
|
||||
|
||||
/// \brief Every \c ClangTidyCheck reports errors through a \c DiagnosticEngine
|
||||
/// provided by this context.
|
||||
///
|
||||
|
@ -162,6 +169,13 @@ public:
|
|||
/// \brief Clears collected errors.
|
||||
void clearErrors() { Errors.clear(); }
|
||||
|
||||
/// \brief Set the output struct for profile data.
|
||||
///
|
||||
/// Setting a non-null pointer here will enable profile collection in
|
||||
/// clang-tidy.
|
||||
void setCheckProfileData(ProfileData* Profile);
|
||||
ProfileData* getCheckProfileData() const { return Profile; }
|
||||
|
||||
private:
|
||||
// Calls setDiagnosticsEngine() and storeError().
|
||||
friend class ClangTidyDiagnosticConsumer;
|
||||
|
@ -184,6 +198,8 @@ private:
|
|||
ClangTidyStats Stats;
|
||||
|
||||
llvm::DenseMap<unsigned, std::string> CheckNamesByDiagnosticID;
|
||||
|
||||
ProfileData *Profile;
|
||||
};
|
||||
|
||||
/// \brief A diagnostic consumer that turns each \c Diagnostic into a
|
||||
|
|
|
@ -98,6 +98,11 @@ DumpConfig("dump-config",
|
|||
cl::desc("Dumps configuration in the YAML format to stdout."),
|
||||
cl::init(false), cl::cat(ClangTidyCategory));
|
||||
|
||||
static cl::opt<bool> EnableCheckProfile(
|
||||
"enable-check-profile",
|
||||
cl::desc("Enable per-check timing profiles, and print a report to stderr."),
|
||||
cl::init(false), cl::cat(ClangTidyCategory));
|
||||
|
||||
static cl::opt<bool> AnalyzeTemporaryDtors(
|
||||
"analyze-temporary-dtors",
|
||||
cl::desc("Enable temporary destructor-aware analysis in\n"
|
||||
|
@ -143,6 +148,45 @@ static void printStats(const ClangTidyStats &Stats) {
|
|||
}
|
||||
}
|
||||
|
||||
static void printProfileData(const ProfileData &Profile,
|
||||
llvm::raw_ostream &OS) {
|
||||
// Time is first to allow for sorting by it.
|
||||
std::vector<std::pair<llvm::TimeRecord, StringRef>> Timers;
|
||||
TimeRecord Total;
|
||||
|
||||
for (const auto& P : Profile.Records) {
|
||||
Timers.emplace_back(P.getValue(), P.getKey());
|
||||
Total += P.getValue();
|
||||
}
|
||||
|
||||
std::sort(Timers.begin(), Timers.end());
|
||||
|
||||
std::string Line = "===" + std::string(73, '-') + "===\n";
|
||||
OS << Line;
|
||||
|
||||
if (Total.getUserTime())
|
||||
OS << " ---User Time---";
|
||||
if (Total.getSystemTime())
|
||||
OS << " --System Time--";
|
||||
if (Total.getProcessTime())
|
||||
OS << " --User+System--";
|
||||
OS << " ---Wall Time---";
|
||||
if (Total.getMemUsed())
|
||||
OS << " ---Mem---";
|
||||
OS << " --- Name ---\n";
|
||||
|
||||
// Loop through all of the timing data, printing it out.
|
||||
for (auto I = Timers.rbegin(), E = Timers.rend(); I != E; ++I) {
|
||||
I->first.print(Total, OS);
|
||||
OS << I->second << '\n';
|
||||
}
|
||||
|
||||
Total.print(Total, OS);
|
||||
OS << "Total\n";
|
||||
OS << Line << "\n";
|
||||
OS.flush();
|
||||
}
|
||||
|
||||
std::unique_ptr<ClangTidyOptionsProvider> createOptionsProvider() {
|
||||
ClangTidyGlobalOptions GlobalOptions;
|
||||
if (std::error_code Err = parseLineFilter(LineFilter, GlobalOptions)) {
|
||||
|
@ -220,10 +264,13 @@ int clangTidyMain(int argc, const char **argv) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
ProfileData Profile;
|
||||
|
||||
std::vector<ClangTidyError> Errors;
|
||||
ClangTidyStats Stats =
|
||||
runClangTidy(std::move(OptionsProvider), OptionsParser.getCompilations(),
|
||||
OptionsParser.getSourcePathList(), &Errors);
|
||||
OptionsParser.getSourcePathList(), &Errors,
|
||||
EnableCheckProfile ? &Profile : nullptr);
|
||||
handleErrors(Errors, Fix);
|
||||
|
||||
if (!ExportFixes.empty() && !Errors.empty()) {
|
||||
|
@ -237,6 +284,9 @@ int clangTidyMain(int argc, const char **argv) {
|
|||
}
|
||||
|
||||
printStats(Stats);
|
||||
if (EnableCheckProfile)
|
||||
printProfileData(Profile, llvm::errs());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue