CppCheckExecutor: extracted logging instance related code into separate implementation class (#5658)

This commit is contained in:
Oliver Stöneberg 2023-11-16 10:35:43 +01:00 committed by GitHub
parent 81a03e7341
commit 8b69ccadd4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 119 additions and 109 deletions

View File

@ -653,10 +653,10 @@ cli/cmdlineparser.o: cli/cmdlineparser.cpp cli/cmdlinelogger.h cli/cmdlineparser
cli/cppcheckexecutor.o: cli/cppcheckexecutor.cpp cli/cmdlinelogger.h cli/cmdlineparser.h cli/cppcheckexecutor.h cli/cppcheckexecutorseh.h cli/cppcheckexecutorsig.h cli/executor.h cli/filelister.h cli/processexecutor.h cli/singleexecutor.h cli/threadexecutor.h lib/addoninfo.h lib/analyzerinfo.h lib/check.h lib/checkersreport.h lib/checkunusedfunctions.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/pathmatch.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h
$(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/cppcheckexecutor.cpp
cli/cppcheckexecutorseh.o: cli/cppcheckexecutorseh.cpp cli/cppcheckexecutor.h cli/cppcheckexecutorseh.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/platform.h lib/standards.h lib/utils.h
cli/cppcheckexecutorseh.o: cli/cppcheckexecutorseh.cpp cli/cppcheckexecutor.h cli/cppcheckexecutorseh.h lib/config.h lib/filesettings.h lib/platform.h lib/standards.h lib/utils.h
$(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/cppcheckexecutorseh.cpp
cli/cppcheckexecutorsig.o: cli/cppcheckexecutorsig.cpp cli/cppcheckexecutor.h cli/cppcheckexecutorsig.h cli/stacktrace.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/platform.h lib/standards.h lib/utils.h
cli/cppcheckexecutorsig.o: cli/cppcheckexecutorsig.cpp cli/cppcheckexecutor.h cli/cppcheckexecutorsig.h cli/stacktrace.h lib/config.h lib/filesettings.h lib/platform.h lib/standards.h lib/utils.h
$(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/cppcheckexecutorsig.cpp
cli/executor.o: cli/executor.cpp cli/executor.h lib/addoninfo.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h
@ -665,7 +665,7 @@ cli/executor.o: cli/executor.cpp cli/executor.h lib/addoninfo.h lib/color.h lib/
cli/filelister.o: cli/filelister.cpp cli/filelister.h lib/config.h lib/path.h lib/pathmatch.h lib/utils.h
$(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/filelister.cpp
cli/main.o: cli/main.cpp cli/cppcheckexecutor.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/platform.h lib/standards.h lib/utils.h
cli/main.o: cli/main.cpp cli/cppcheckexecutor.h lib/config.h lib/errortypes.h lib/filesettings.h lib/platform.h lib/standards.h lib/utils.h
$(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/main.cpp
cli/processexecutor.o: cli/processexecutor.cpp cli/executor.h cli/processexecutor.h lib/addoninfo.h lib/analyzerinfo.h lib/check.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h

View File

@ -26,6 +26,7 @@
#include "color.h"
#include "config.h"
#include "cppcheck.h"
#include "errorlogger.h"
#include "errortypes.h"
#include "filelister.h"
#include "filesettings.h"
@ -49,9 +50,11 @@
#include <cassert>
#include <cstdio>
#include <cstdlib> // EXIT_SUCCESS and EXIT_FAILURE
#include <ctime>
#include <iostream>
#include <iterator>
#include <list>
#include <set>
#include <sstream> // IWYU pragma: keep
#include <unordered_set>
#include <utility>
@ -106,17 +109,90 @@ public:
}
};
class CppCheckExecutor::StdLogger : public ErrorLogger
{
public:
explicit StdLogger(const Settings& settings)
: mSettings(settings)
{
if (!mSettings.outputFile.empty()) {
mErrorOutput = new std::ofstream(settings.outputFile);
}
}
~StdLogger() override {
delete mErrorOutput;
}
StdLogger(const StdLogger&) = delete;
StdLogger& operator=(const SingleExecutor &) = delete;
void resetLatestProgressOutputTime() {
mLatestProgressOutputTime = std::time(nullptr);
}
/**
* Helper function to print out errors. Appends a line change.
* @param errmsg String printed to error stream
*/
void reportErr(const std::string &errmsg);
/**
* @brief Write the checkers report
*/
void writeCheckersReport() const;
private:
/**
* Information about progress is directed here. This should be
* called by the CppCheck class only.
*
* @param outmsg Progress message e.g. "Checking main.cpp..."
*/
void reportOut(const std::string &outmsg, Color c = Color::Reset) override;
/** xml output of errors */
void reportErr(const ErrorMessage &msg) override;
void reportProgress(const std::string &filename, const char stage[], const std::size_t value) override;
/**
* Pointer to current settings; set while check() is running for reportError().
*/
const Settings& mSettings;
/**
* Used to filter out duplicate error messages.
*/
std::set<std::string> mShownErrors;
/**
* Report progress time
*/
std::time_t mLatestProgressOutputTime{};
/**
* Error output
*/
std::ofstream* mErrorOutput{};
/**
* Checkers that has been executed
*/
std::set<std::string> mActiveCheckers;
/**
* True if there are critical errors
*/
std::string mCriticalErrors;
};
// TODO: do not directly write to stdout
#if defined(USE_WINDOWS_SEH) || defined(USE_UNIX_SIGNAL_HANDLING)
/*static*/ FILE* CppCheckExecutor::mExceptionOutput = stdout;
#endif
CppCheckExecutor::~CppCheckExecutor()
{
delete mErrorOutput;
}
bool CppCheckExecutor::parseFromArgs(Settings &settings, int argc, const char* const argv[])
{
CmdLineLoggerStd logger;
@ -168,6 +244,7 @@ bool CppCheckExecutor::parseFromArgs(Settings &settings, int argc, const char* c
if (Path::isDirectory(path))
++iter;
else {
// TODO: this bypasses the template format and other settings
// If the include path is not found, warn user and remove the non-existing path from the list.
if (settings.severity.isEnabled(Severity::information))
std::cout << "(information) Couldn't find path given by -I '" << path << '\'' << std::endl;
@ -283,13 +360,14 @@ int CppCheckExecutor::check(int argc, const char* const argv[])
return EXIT_SUCCESS;
}
CppCheck cppCheck(*this, true, executeCommand);
mStdLogger = new StdLogger(settings);
CppCheck cppCheck(*mStdLogger, true, executeCommand);
cppCheck.settings() = settings;
mSettings = &settings;
const int ret = check_wrapper(cppCheck);
mSettings = nullptr;
delete mStdLogger;
mStdLogger = nullptr;
return ret;
}
@ -331,14 +409,10 @@ int CppCheckExecutor::check_internal(CppCheck& cppcheck)
Settings& settings = cppcheck.settings();
if (settings.reportProgress >= 0)
mLatestProgressOutputTime = std::time(nullptr);
if (!settings.outputFile.empty()) {
mErrorOutput = new std::ofstream(settings.outputFile);
}
mStdLogger->resetLatestProgressOutputTime();
if (settings.xml) {
reportErr(ErrorMessage::getXMLHeader(settings.cppcheckCfgProductName));
mStdLogger->reportErr(ErrorMessage::getXMLHeader(settings.cppcheckCfgProductName));
}
if (!settings.buildDir.empty()) {
@ -353,16 +427,16 @@ int CppCheckExecutor::check_internal(CppCheck& cppcheck)
if (!settings.checkersReportFilename.empty())
std::remove(settings.checkersReportFilename.c_str());
unsigned int returnValue = 0;
unsigned int returnValue;
if (settings.useSingleJob()) {
// Single process
SingleExecutor executor(cppcheck, mFiles, mFileSettings, settings, settings.nomsg, *this);
SingleExecutor executor(cppcheck, mFiles, mFileSettings, settings, settings.nomsg, *mStdLogger);
returnValue = executor.check();
} else {
#if defined(THREADING_MODEL_THREAD)
ThreadExecutor executor(mFiles, mFileSettings, settings, settings.nomsg, *this, CppCheckExecutor::executeCommand);
ThreadExecutor executor(mFiles, mFileSettings, settings, settings.nomsg, *mStdLogger, CppCheckExecutor::executeCommand);
#elif defined(THREADING_MODEL_FORK)
ProcessExecutor executor(mFiles, mFileSettings, settings, settings.nomsg, *this, CppCheckExecutor::executeCommand);
ProcessExecutor executor(mFiles, mFileSettings, settings, settings.nomsg, *mStdLogger, CppCheckExecutor::executeCommand);
#endif
returnValue = executor.check();
}
@ -370,7 +444,7 @@ int CppCheckExecutor::check_internal(CppCheck& cppcheck)
cppcheck.analyseWholeProgram(settings.buildDir, mFiles, mFileSettings);
if (settings.severity.isEnabled(Severity::information) || settings.checkConfiguration) {
const bool err = reportSuppressions(settings, cppcheck.isUnusedFunctionCheckEnabled(), mFiles, *this);
const bool err = reportSuppressions(settings, cppcheck.isUnusedFunctionCheckEnabled(), mFiles, *mStdLogger);
if (err && returnValue == 0)
returnValue = settings.exitCode;
}
@ -380,35 +454,35 @@ int CppCheckExecutor::check_internal(CppCheck& cppcheck)
}
if (settings.xml) {
reportErr(ErrorMessage::getXMLFooter());
mStdLogger->reportErr(ErrorMessage::getXMLFooter());
}
writeCheckersReport(settings);
mStdLogger->writeCheckersReport();
if (returnValue)
return settings.exitCode;
return 0;
}
void CppCheckExecutor::writeCheckersReport(const Settings& settings) const
void CppCheckExecutor::StdLogger::writeCheckersReport() const
{
CheckersReport checkersReport(settings, mActiveCheckers);
CheckersReport checkersReport(mSettings, mActiveCheckers);
if (!settings.quiet) {
if (!mSettings.quiet) {
const int activeCheckers = checkersReport.getActiveCheckersCount();
const int totalCheckers = checkersReport.getAllCheckersCount();
const std::string extra = settings.verbose ? " (use --checkers-report=<filename> to see details)" : "";
const std::string extra = mSettings.verbose ? " (use --checkers-report=<filename> to see details)" : "";
if (mCriticalErrors.empty())
std::cout << "Active checkers: " << activeCheckers << "/" << totalCheckers << extra << std::endl;
else
std::cout << "Active checkers: There was critical errors" << extra << std::endl;
}
if (settings.checkersReportFilename.empty())
if (mSettings.checkersReportFilename.empty())
return;
std::ofstream fout(settings.checkersReportFilename);
std::ofstream fout(mSettings.checkersReportFilename);
if (fout.is_open())
fout << checkersReport.getReport(mCriticalErrors);
@ -481,16 +555,16 @@ static inline std::string ansiToOEM(const std::string &msg, bool doConvert)
#define ansiToOEM(msg, doConvert) (msg)
#endif
void CppCheckExecutor::reportErr(const std::string &errmsg)
void CppCheckExecutor::StdLogger::reportErr(const std::string &errmsg)
{
if (mErrorOutput)
*mErrorOutput << errmsg << std::endl;
else {
std::cerr << ansiToOEM(errmsg, (mSettings == nullptr) ? true : !mSettings->xml) << std::endl;
std::cerr << ansiToOEM(errmsg, !mSettings.xml) << std::endl;
}
}
void CppCheckExecutor::reportOut(const std::string &outmsg, Color c)
void CppCheckExecutor::StdLogger::reportOut(const std::string &outmsg, Color c)
{
if (c == Color::Reset)
std::cout << ansiToOEM(outmsg, true) << std::endl;
@ -499,7 +573,7 @@ void CppCheckExecutor::reportOut(const std::string &outmsg, Color c)
}
// TODO: remove filename parameter?
void CppCheckExecutor::reportProgress(const std::string &filename, const char stage[], const std::size_t value)
void CppCheckExecutor::StdLogger::reportProgress(const std::string &filename, const char stage[], const std::size_t value)
{
(void)filename;
@ -508,7 +582,7 @@ void CppCheckExecutor::reportProgress(const std::string &filename, const char st
// Report progress messages every x seconds
const std::time_t currentTime = std::time(nullptr);
if (currentTime >= (mLatestProgressOutputTime + mSettings->reportProgress))
if (currentTime >= (mLatestProgressOutputTime + mSettings.reportProgress))
{
mLatestProgressOutputTime = currentTime;
@ -523,10 +597,8 @@ void CppCheckExecutor::reportProgress(const std::string &filename, const char st
}
}
void CppCheckExecutor::reportErr(const ErrorMessage &msg)
void CppCheckExecutor::StdLogger::reportErr(const ErrorMessage &msg)
{
assert(mSettings != nullptr);
if (msg.severity == Severity::none && (msg.id == "logChecker" || endsWith(msg.id, "-logChecker"))) {
const std::string& checker = msg.shortMessage();
mActiveCheckers.emplace(checker);
@ -534,7 +606,7 @@ void CppCheckExecutor::reportErr(const ErrorMessage &msg)
}
// Alert only about unique errors
if (!mShownErrors.insert(msg.toString(mSettings->verbose)).second)
if (!mShownErrors.insert(msg.toString(mSettings.verbose)).second)
return;
if (ErrorLogger::isCriticalErrorId(msg.id) && mCriticalErrors.find(msg.id) == std::string::npos) {
@ -543,10 +615,10 @@ void CppCheckExecutor::reportErr(const ErrorMessage &msg)
mCriticalErrors += msg.id;
}
if (mSettings->xml)
if (mSettings.xml)
reportErr(msg.toXML());
else
reportErr(msg.toString(mSettings->verbose, mSettings->templateFormat, mSettings->templateLocation));
reportErr(msg.toString(mSettings.verbose, mSettings.templateFormat, mSettings.templateLocation));
}
#if defined(USE_WINDOWS_SEH) || defined(USE_UNIX_SIGNAL_HANDLING)

View File

@ -19,16 +19,11 @@
#ifndef CPPCHECKEXECUTOR_H
#define CPPCHECKEXECUTOR_H
#include "color.h"
#include "config.h"
#include "errorlogger.h"
#include "filesettings.h"
#include <cstdio>
#include <ctime>
#include <iosfwd>
#include <list>
#include <set>
#include <string>
#include <utility>
#include <vector>
@ -36,6 +31,7 @@
class CppCheck;
class Library;
class Settings;
class ErrorLogger;
/**
* This class works as an example of how CppCheck can be used in external
@ -44,7 +40,7 @@ class Settings;
* just rewrite this class for your needs and possibly use other methods
* from CppCheck class instead the ones used here.
*/
class CppCheckExecutor : public ErrorLogger {
class CppCheckExecutor {
public:
friend class TestSuppressions;
@ -55,11 +51,6 @@ public:
CppCheckExecutor(const CppCheckExecutor &) = delete;
void operator=(const CppCheckExecutor&) = delete;
/**
* Destructor
*/
~CppCheckExecutor() override;
/**
* Starts the checking.
*
@ -73,23 +64,6 @@ public:
*/
int check(int argc, const char* const argv[]);
private:
/**
* Information about progress is directed here. This should be
* called by the CppCheck class only.
*
* @param outmsg Progress message e.g. "Checking main.cpp..."
*/
void reportOut(const std::string &outmsg, Color c = Color::Reset) override;
/** xml output of errors */
void reportErr(const ErrorMessage &msg) override;
void reportProgress(const std::string &filename, const char stage[], const std::size_t value) override;
public:
/**
* @param exceptionOutput Output file
*/
@ -112,11 +86,7 @@ private:
*/
static int executeCommand(std::string exe, std::vector<std::string> args, std::string redirect, std::string &output_);
/**
* Helper function to print out errors. Appends a line change.
* @param errmsg String printed to error stream
*/
void reportErr(const std::string &errmsg);
protected:
/**
* @brief Parse command line args and get settings and file lists
@ -156,7 +126,7 @@ private:
* @param settings Settings
* @return Returns true if successful
*/
bool loadLibraries(Settings& settings);
static bool loadLibraries(Settings& settings);
/**
* @brief Load addons
@ -165,21 +135,6 @@ private:
*/
static bool loadAddons(Settings& settings);
/**
* @brief Write the checkers report
*/
void writeCheckersReport(const Settings& settings) const;
/**
* Pointer to current settings; set while check() is running for reportError().
*/
const Settings* mSettings{};
/**
* Used to filter out duplicate error messages.
*/
std::set<std::string> mShownErrors;
/**
* Filename associated with size of file
*/
@ -187,11 +142,6 @@ private:
std::list<FileSettings> mFileSettings;
/**
* Report progress time
*/
std::time_t mLatestProgressOutputTime{};
#if defined(USE_WINDOWS_SEH) || defined(USE_UNIX_SIGNAL_HANDLING)
/**
* Output file name for exception handler
@ -199,20 +149,8 @@ private:
static FILE* mExceptionOutput;
#endif
/**
* Error output
*/
std::ofstream* mErrorOutput{};
/**
* Checkers that has been executed
*/
std::set<std::string> mActiveCheckers;
/**
* True if there are critical errors
*/
std::string mCriticalErrors;
class StdLogger;
StdLogger* mStdLogger{};
};
#endif // CPPCHECKEXECUTOR_H