perform logging in `CmdLineParser` through an interface (#5478)

This is in preparation of avoiding accessing `std::cout` directly as
well as streamlining and improving the logging during the settings
parsing. There are no functional changes yet.
This commit is contained in:
Oliver Stöneberg 2023-09-25 13:43:18 +02:00 committed by GitHub
parent 1959c85e34
commit 3fd00c19df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 127 additions and 74 deletions

View File

@ -639,10 +639,10 @@ $(libcppdir)/utils.o: lib/utils.cpp lib/config.h lib/utils.h
$(libcppdir)/vfvalue.o: lib/vfvalue.cpp lib/config.h lib/errortypes.h lib/mathlib.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/vfvalue.h
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vfvalue.cpp
cli/cmdlineparser.o: cli/cmdlineparser.cpp cli/cmdlineparser.h cli/cppcheckexecutor.h cli/filelister.h externals/tinyxml2/tinyxml2.h lib/check.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h
cli/cmdlineparser.o: cli/cmdlineparser.cpp cli/cmdlinelogger.h cli/cmdlineparser.h cli/cppcheckexecutor.h cli/filelister.h externals/tinyxml2/tinyxml2.h lib/check.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h
$(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/cmdlineparser.cpp
cli/cppcheckexecutor.o: cli/cppcheckexecutor.cpp 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/analyzerinfo.h lib/check.h lib/checkers.h lib/checkersreport.h lib/checkunusedfunctions.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/importproject.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
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/analyzerinfo.h lib/check.h lib/checkers.h lib/checkersreport.h lib/checkunusedfunctions.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/importproject.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/utils.h
@ -720,7 +720,7 @@ test/testclangimport.o: test/testclangimport.cpp lib/check.h lib/clangimport.h l
test/testclass.o: test/testclass.cpp externals/simplecpp/simplecpp.h lib/check.h lib/checkclass.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/preprocessor.h lib/settings.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testclass.cpp
test/testcmdlineparser.o: test/testcmdlineparser.cpp cli/cmdlineparser.h cli/cppcheckexecutor.h lib/check.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h test/redirect.h
test/testcmdlineparser.o: test/testcmdlineparser.cpp cli/cmdlinelogger.h cli/cmdlineparser.h cli/cppcheckexecutor.h lib/check.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h test/redirect.h
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testcmdlineparser.cpp
test/testcolor.o: test/testcolor.cpp lib/check.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h test/fixture.h

33
cli/cmdlinelogger.h Normal file
View File

@ -0,0 +1,33 @@
/*
* Cppcheck - A tool for static C/C++ code analysis
* Copyright (C) 2007-2023 Cppcheck team.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CMD_LINE_LOGGER_H
#define CMD_LINE_LOGGER_H
#include <string>
class CmdLineLogger
{
public:
virtual ~CmdLineLogger() = default;
virtual void printMessage(const std::string &message) = 0;
virtual void printError(const std::string &message) = 0;
};
#endif // CMD_LINE_LOGGER_H

View File

@ -109,22 +109,13 @@ static bool addPathsToSet(const std::string& fileName, std::set<std::string>& se
return true;
}
CmdLineParser::CmdLineParser(Settings &settings, Suppressions &suppressions, Suppressions &suppressionsNoFail)
: mSettings(settings)
CmdLineParser::CmdLineParser(CmdLineLogger &logger, Settings &settings, Suppressions &suppressions, Suppressions &suppressionsNoFail)
: mLogger(logger)
, mSettings(settings)
, mSuppressions(suppressions)
, mSuppressionsNoFail(suppressionsNoFail)
{}
void CmdLineParser::printMessage(const std::string &message)
{
std::cout << "cppcheck: " << message << std::endl;
}
void CmdLineParser::printError(const std::string &message)
{
printMessage("error: " + message);
}
// TODO: normalize/simplify/native all path parameters
// TODO: error out on all missing given files/paths
bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
@ -144,7 +135,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
if (std::strcmp(argv[i], "-D") == 0) {
++i;
if (i >= argc || argv[i][0] == '-') {
printError("argument to '-D' is missing.");
mLogger.printError("argument to '-D' is missing.");
return false;
}
@ -180,7 +171,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
if (std::strcmp(argv[i], "-I") == 0) {
++i;
if (i >= argc || argv[i][0] == '-') {
printError("argument to '-I' is missing.");
mLogger.printError("argument to '-I' is missing.");
return false;
}
path = argv[i];
@ -208,7 +199,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
if (std::strcmp(argv[i], "-U") == 0) {
++i;
if (i >= argc || argv[i][0] == '-') {
printError("argument to '-U' is missing.");
mLogger.printError("argument to '-U' is missing.");
return false;
}
@ -270,7 +261,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
// open this file and read every input file (1 file name per line)
const std::string cfgExcludesFile(23 + argv[i]);
if (!addPathsToSet(cfgExcludesFile, mSettings.configExcludePaths)) {
printError("unable to open config excludes file at '" + cfgExcludesFile + "'");
mLogger.printError("unable to open config excludes file at '" + cfgExcludesFile + "'");
return false;
}
}
@ -281,7 +272,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
mSettings.buildDir.pop_back();
if (!Path::isDirectory(mSettings.buildDir)) {
printError("Directory '" + mSettings.buildDir + "' specified by --cppcheck-build-dir argument has to be existent.");
mLogger.printError("Directory '" + mSettings.buildDir + "' specified by --cppcheck-build-dir argument has to be existent.");
return false;
}
}
@ -306,7 +297,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
else if (std::strncmp(argv[i], "--disable=", 10) == 0) {
const std::string errmsg = mSettings.removeEnabled(argv[i] + 10);
if (!errmsg.empty()) {
printError(errmsg);
mLogger.printError(errmsg);
return false;
}
}
@ -336,7 +327,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
const std::string enable_arg = argv[i] + 9;
const std::string errmsg = mSettings.addEnabled(enable_arg);
if (!errmsg.empty()) {
printError(errmsg);
mLogger.printError(errmsg);
return false;
}
// when "style" is enabled, also enable "warning", "performance" and "portability"
@ -347,7 +338,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
}
if (enable_arg.find("information") != std::string::npos) {
mSettings.addEnabled("missingInclude");
printMessage("'--enable=information' will no longer implicitly enable 'missingInclude' starting with 2.16. Please enable it explicitly if you require it.");
mLogger.printMessage("'--enable=information' will no longer implicitly enable 'missingInclude' starting with 2.16. Please enable it explicitly if you require it.");
}
}
@ -373,7 +364,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
else if (std::strncmp(argv[i], "--exception-handling=", 21) == 0) {
const std::string exceptionOutfilename = argv[i] + 21;
if (exceptionOutfilename != "stderr" && exceptionOutfilename != "stdout") {
printError("invalid '--exception-handling' argument");
mLogger.printError("invalid '--exception-handling' argument");
return false;
}
mSettings.exceptionHandling = true;
@ -387,12 +378,12 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
std::ifstream f(filename);
if (!f.is_open()) {
printError("couldn't open the file: \"" + filename + "\".");
mLogger.printError("couldn't open the file: \"" + filename + "\".");
return false;
}
const std::string errmsg(mSuppressionsNoFail.parseFile(f));
if (!errmsg.empty()) {
printError(errmsg);
mLogger.printError(errmsg);
return false;
}
}
@ -406,7 +397,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
// open this file and read every input file (1 file name per line)
const std::string fileList = argv[i] + 12;
if (!addFilesToList(fileList, mPathNames)) {
printError("couldn't open the file: \"" + fileList + "\".");
mLogger.printError("couldn't open the file: \"" + fileList + "\".");
return false;
}
}
@ -431,7 +422,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
if (std::strcmp(argv[i], "-i") == 0) {
++i;
if (i >= argc || argv[i][0] == '-') {
printError("argument to '-i' is missing.");
mLogger.printError("argument to '-i' is missing.");
return false;
}
path = argv[i];
@ -464,7 +455,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
// open this file and read every input file (1 file name per line)
const std::string includesFile(16 + argv[i]);
if (!addIncludePathsToList(includesFile, mSettings.includePaths)) {
printError("unable to open includes file at '" + includesFile + "'");
mLogger.printError("unable to open includes file at '" + includesFile + "'");
return false;
}
}
@ -485,7 +476,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
if (std::strcmp(argv[i], "-j") == 0) {
++i;
if (i >= argc || argv[i][0] == '-') {
printError("argument to '-j' is missing.");
mLogger.printError("argument to '-j' is missing.");
return false;
}
@ -499,20 +490,20 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
unsigned int tmp;
std::string err;
if (!strToInt(numberString, tmp, &err)) {
printError("argument to '-j' is not valid - " + err + ".");
mLogger.printError("argument to '-j' is not valid - " + err + ".");
return false;
}
if (tmp == 0) {
// TODO: implement get CPU logical core count and use that.
// Usually, -j 0 would mean "use all available cores," but
// if we get a 0, we just stall and don't do any work.
printError("argument for '-j' must be greater than 0.");
mLogger.printError("argument for '-j' must be greater than 0.");
return false;
}
if (tmp > 1024) {
// Almost nobody has 1024 logical cores, but somebody out
// there does.
printError("argument for '-j' is allowed to be 1024 at max.");
mLogger.printError("argument for '-j' is allowed to be 1024 at max.");
return false;
}
mSettings.jobs = tmp;
@ -526,7 +517,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
if (std::strcmp(argv[i], "-l") == 0) {
++i;
if (i >= argc || argv[i][0] == '-') {
printError("argument to '-l' is missing.");
mLogger.printError("argument to '-l' is missing.");
return false;
}
@ -540,7 +531,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
int tmp;
std::string err;
if (!strToInt(numberString, tmp, &err)) {
printError("argument to '-l' is not valid - " + err + ".");
mLogger.printError("argument to '-l' is not valid - " + err + ".");
return false;
}
mSettings.loadAverage = tmp;
@ -555,7 +546,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
} else {
i++;
if (i >= argc || argv[i][0] == '-') {
printError("no language given to '-x' option.");
mLogger.printError("no language given to '-x' option.");
return false;
}
str = argv[i];
@ -566,7 +557,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
else if (str == "c++")
mSettings.enforcedLang = Settings::Language::CPP;
else {
printError("unknown language '" + str + "' enforced.");
mLogger.printError("unknown language '" + str + "' enforced.");
return false;
}
}
@ -582,7 +573,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
if (!parseNumberArg(argv[i], 14, tmp))
return false;
if (tmp < 1) {
printError("argument to '--max-configs=' must be greater than 0.");
mLogger.printError("argument to '--max-configs=' must be greater than 0.");
return false;
}
@ -620,7 +611,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
std::string errstr;
const std::vector<std::string> paths = {argv[0]};
if (!mSettings.platform.set(platform, errstr, paths)) {
printError(errstr);
mLogger.printError(errstr);
return false;
}
@ -646,7 +637,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
std::string message("plist folder does not exist: \"");
message += plistOutput;
message += "\".";
printError(message);
mLogger.printError(message);
return false;
}
}
@ -680,14 +671,14 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
// keep existing platform from command-line intact
if (!platform.empty()) {
if (platform == "Unspecified") {
printMessage("'Unspecified' is a deprecated platform type and will be removed in Cppcheck 2.14. Please use 'unspecified' instead.");
mLogger.printMessage("'Unspecified' is a deprecated platform type and will be removed in Cppcheck 2.14. Please use 'unspecified' instead.");
platform = "unspecified";
}
std::string errstr;
const std::vector<std::string> paths = {projectFile, argv[0]};
if (!mSettings.platform.set(platform, errstr, paths)) {
printError(errstr);
mLogger.printError(errstr);
return false;
}
}
@ -702,20 +693,20 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
mSettings.project.selectOneVsConfig(mSettings.platform.type);
if (!CppCheckExecutor::tryLoadLibrary(mSettings.library, argv[0], "windows.cfg")) {
// This shouldn't happen normally.
printError("failed to load 'windows.cfg'. Your Cppcheck installation is broken. Please re-install.");
mLogger.printError("failed to load 'windows.cfg'. Your Cppcheck installation is broken. Please re-install.");
return false;
}
}
if (projType == ImportProject::Type::MISSING) {
printError("failed to open project '" + projectFile + "'. The file does not exist.");
mLogger.printError("failed to open project '" + projectFile + "'. The file does not exist.");
return false;
}
if (projType == ImportProject::Type::UNKNOWN) {
printError("failed to load project '" + projectFile + "'. The format is unknown.");
mLogger.printError("failed to load project '" + projectFile + "'. The format is unknown.");
return false;
}
if (projType == ImportProject::Type::FAILURE) {
printError("failed to load project '" + projectFile + "'. An error occurred.");
mLogger.printError("failed to load project '" + projectFile + "'. An error occurred.");
return false;
}
}
@ -748,7 +739,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
paths.erase(0, pos + 1);
}
} else {
printError("no paths specified for the '" + std::string(argv[i]) + "' option.");
mLogger.printError("no paths specified for the '" + std::string(argv[i]) + "' option.");
return false;
}
}
@ -811,7 +802,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
mSettings.rules.emplace_back(std::move(rule));
}
} else {
printError("unable to load rule-file: " + std::string(12+argv[i]));
mLogger.printError("unable to load rule-file: " + std::string(12+argv[i]));
return false;
}
}
@ -831,7 +822,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
else if (showtimeMode.empty())
mSettings.showtime = SHOWTIME_MODES::SHOWTIME_NONE;
else {
printError("unrecognized showtime mode: \"" + showtimeMode + "\". Supported modes: file, file-total, summary, top5.");
mLogger.printError("unrecognized showtime mode: \"" + showtimeMode + "\". Supported modes: file, file-total, summary, top5.");
return false;
}
}
@ -847,7 +838,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
mSettings.standards.c = Standards::getC(std);
}
else {
printError("unknown --std value '" + std + "'");
mLogger.printError("unknown --std value '" + std + "'");
return false;
}
}
@ -856,7 +847,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
const std::string suppression = argv[i]+11;
const std::string errmsg(mSuppressions.addSuppressionLine(suppression));
if (!errmsg.empty()) {
printError(errmsg);
mLogger.printError(errmsg);
return false;
}
}
@ -878,12 +869,12 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
message += "\n cppcheck --suppressions-list=a.txt --suppressions-list=b.txt file.cpp";
}
printError(message);
mLogger.printError(message);
return false;
}
const std::string errmsg(mSuppressions.parseFile(f));
if (!errmsg.empty()) {
printError(errmsg);
mLogger.printError(errmsg);
return false;
}
}
@ -892,7 +883,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
const char * filename = argv[i] + 15;
const std::string errmsg(mSuppressions.parseXmlFile(filename));
if (!errmsg.empty()) {
printError(errmsg);
mLogger.printError(errmsg);
return false;
}
}
@ -965,7 +956,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
return false;
if (tmp != 2) {
// We only have xml version 2
printError("'--xml-version' can only be 2.");
mLogger.printError("'--xml-version' can only be 2.");
return false;
}
@ -978,7 +969,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
std::string message("unrecognized command line option: \"");
message += argv[i];
message += "\".";
printError(message);
mLogger.printError(message);
return false;
}
}
@ -1012,7 +1003,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
mSettings.maxConfigs = 1U;
if (mSettings.checks.isEnabled(Checks::unusedFunction) && mSettings.jobs > 1 && mSettings.buildDir.empty()) {
printMessage("unusedFunction check can't be used with '-j' option. Disabling unusedFunction check.");
mLogger.printMessage("unusedFunction check can't be used with '-j' option. Disabling unusedFunction check.");
}
if (argc <= 1) {
@ -1027,7 +1018,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
// Print error only if we have "real" command and expect files
if (!mExitAfterPrint && mPathNames.empty() && mSettings.project.fileSettings.empty()) {
printError("no C or C++ source files found.");
mLogger.printError("no C or C++ source files found.");
return false;
}

View File

@ -23,6 +23,7 @@
#include <string>
#include <vector>
#include "cmdlinelogger.h"
#include "utils.h"
class Settings;
@ -44,12 +45,13 @@ class CmdLineParser {
public:
/**
* The constructor.
* @param logger The logger instance to log messages through
* @param settings Settings instance that will be modified according to
* options user has given.
* @param suppressions Suppressions instance that keeps the suppressions
* @param suppressionsNoFail Suppressions instance that keeps the "do not fail" suppressions
*/
CmdLineParser(Settings &settings, Suppressions &suppressions, Suppressions &suppressionsNoFail);
CmdLineParser(CmdLineLogger &logger, Settings &settings, Suppressions &suppressions, Suppressions &suppressionsNoFail);
/**
* Parse given command line.
@ -99,36 +101,28 @@ protected:
*/
void printHelp();
/**
* Print message (to stdout).
*/
static void printMessage(const std::string &message);
/**
* Print error message (to stdout).
*/
static void printError(const std::string &message);
private:
bool isCppcheckPremium() const;
template<typename T>
static bool parseNumberArg(const char* const arg, std::size_t offset, T& num, bool mustBePositive = false)
bool parseNumberArg(const char* const arg, std::size_t offset, T& num, bool mustBePositive = false)
{
T tmp;
std::string err;
if (!strToInt(arg + offset, tmp, &err)) {
printError("argument to '" + std::string(arg, offset) + "' is not valid - " + err + ".");
mLogger.printError("argument to '" + std::string(arg, offset) + "' is not valid - " + err + ".");
return false;
}
if (mustBePositive && tmp < 0) {
printError("argument to '" + std::string(arg, offset) + "' needs to be a positive integer.");
mLogger.printError("argument to '" + std::string(arg, offset) + "' needs to be a positive integer.");
return false;
}
num = tmp;
return true;
}
CmdLineLogger &mLogger;
std::vector<std::string> mPathNames;
std::vector<std::string> mIgnoredPaths;
Settings &mSettings;

View File

@ -85,6 +85,22 @@ class XMLErrorMessagesLogger : public ErrorLogger
{}
};
class CmdLineLoggerStd : public CmdLineLogger
{
public:
CmdLineLoggerStd() = default;
void printMessage(const std::string &message) override
{
std::cout << "cppcheck: " << message << std::endl;
}
void printError(const std::string &message) override
{
printMessage("error: " + message);
}
};
// TODO: do not directly write to stdout
/*static*/ FILE* CppCheckExecutor::mExceptionOutput = stdout;
@ -96,7 +112,8 @@ CppCheckExecutor::~CppCheckExecutor()
bool CppCheckExecutor::parseFromArgs(Settings &settings, int argc, const char* const argv[])
{
CmdLineParser parser(settings, settings.nomsg, settings.nofail);
CmdLineLoggerStd logger;
CmdLineParser parser(logger, settings, settings.nomsg, settings.nofail);
const bool success = parser.parseFromArgs(argc, argv);
if (success) {

View File

@ -32,6 +32,7 @@
#include <cstdint>
#include <cstdio>
#include <iostream>
#include <list>
#include <set>
#include <string>
@ -43,12 +44,29 @@ public:
{}
private:
class CmdLineLoggerTest : public CmdLineLogger
{
public:
CmdLineLoggerTest() = default;
void printMessage(const std::string &message) override
{
std::cout << "cppcheck: " << message << std::endl;
}
void printError(const std::string &message) override
{
printMessage("error: " + message);
}
};
CmdLineLoggerTest logger;
std::unique_ptr<Settings> settings;
std::unique_ptr<CmdLineParser> parser;
void prepareTestInternal() override {
settings.reset(new Settings());
parser.reset(new CmdLineParser(*settings, settings->nomsg, settings->nofail));
parser.reset(new CmdLineParser(logger, *settings, settings->nomsg, settings->nofail));
}
void run() override {