Skip to content

Commit 4692a9c

Browse files
committed
improved determination if application is Premium / added TODOs
1 parent 1852b10 commit 4692a9c

File tree

10 files changed

+89
-30
lines changed

10 files changed

+89
-30
lines changed

cli/cmdlineparser.cpp

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -380,8 +380,20 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
380380
// default to --check-level=normal from CLI for now
381381
mSettings.setCheckLevel(Settings::CheckLevel::normal);
382382

383+
// TODO: this is duplicated in gui/mainwindows.cpp
384+
{
385+
// load config to determine if we are premium - do not apply any other settings
386+
Settings s;
387+
s.exename = mSettings.exename;
388+
Suppressions supprs;
389+
// TODO: errorhandling
390+
Settings::loadCppcheckCfg(s, supprs, mSettings.debuglookup || mSettings.debuglookupConfig);
391+
mSettings.cppcheckCfgProductName = s.cppcheckCfgProductName;
392+
mSettings.premium = startsWith(mSettings.cppcheckCfgProductName, "Cppcheck Premium");
393+
}
394+
383395
if (argc <= 1) {
384-
printHelp();
396+
printHelp(mSettings.premium);
385397
return Result::Exit;
386398
}
387399

@@ -418,7 +430,7 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
418430

419431
// Print help
420432
if (std::strcmp(argv[i], "-h") == 0 || std::strcmp(argv[i], "--help") == 0) {
421-
printHelp();
433+
printHelp(mSettings.premium);
422434
return Result::Exit;
423435
}
424436

@@ -1086,7 +1098,7 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
10861098
}
10871099

10881100
// Special Cppcheck Premium options
1089-
else if ((std::strncmp(argv[i], "--premium=", 10) == 0 || std::strncmp(argv[i], "--premium-", 10) == 0) && isCppcheckPremium()) {
1101+
else if ((std::strncmp(argv[i], "--premium=", 10) == 0 || std::strncmp(argv[i], "--premium-", 10) == 0) && mSettings.premium) {
10901102
// valid options --premium=..
10911103
const std::set<std::string> valid{
10921104
"autosar",
@@ -1616,13 +1628,15 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
16161628
return Result::Success;
16171629
}
16181630

1619-
void CmdLineParser::printHelp() const
1631+
void CmdLineParser::printHelp(bool premium) const
16201632
{
1621-
const std::string manualUrl(isCppcheckPremium() ?
1622-
"https://cppcheck.sourceforge.io/manual.pdf" :
1623-
"https://files.cppchecksolutions.com/manual.pdf");
1633+
// TODO: fetch URL from config like product name?
1634+
const std::string manualUrl(premium ?
1635+
"https://files.cppchecksolutions.com/manual.pdf" :
1636+
"https://cppcheck.sourceforge.io/manual.pdf");
16241637

16251638
std::ostringstream oss;
1639+
// TODO: display product name
16261640
oss << "Cppcheck - A tool for static C/C++ code analysis\n"
16271641
"\n"
16281642
"Syntax:\n"
@@ -1820,7 +1834,7 @@ void CmdLineParser::printHelp() const
18201834
" --plist-output=<path>\n"
18211835
" Generate Clang-plist output files in folder.\n";
18221836

1823-
if (isCppcheckPremium()) {
1837+
if (premium) {
18241838
oss <<
18251839
" --premium=<option>\n"
18261840
" Coding standards:\n"
@@ -1994,6 +2008,7 @@ void CmdLineParser::printHelp() const
19942008
}
19952009

19962010
std::string CmdLineParser::getVersion() const {
2011+
// TODO: this should not contain the version - it should set the extraVersion
19972012
if (!mSettings.cppcheckCfgProductName.empty())
19982013
return mSettings.cppcheckCfgProductName;
19992014
const char * const extraVersion = CppCheck::extraVersion();
@@ -2002,12 +2017,6 @@ std::string CmdLineParser::getVersion() const {
20022017
return std::string("Cppcheck ") + CppCheck::version();
20032018
}
20042019

2005-
bool CmdLineParser::isCppcheckPremium() const {
2006-
if (mSettings.cppcheckCfgProductName.empty())
2007-
Settings::loadCppcheckCfg(mSettings, mSuppressions, mSettings.debuglookup || mSettings.debuglookupConfig);
2008-
return startsWith(mSettings.cppcheckCfgProductName, "Cppcheck Premium");
2009-
}
2010-
20112020
bool CmdLineParser::tryLoadLibrary(Library& destination, const std::string& basepath, const char* filename, bool debug)
20122021
{
20132022
const Library::Error err = destination.load(basepath.c_str(), filename, debug);
@@ -2100,8 +2109,12 @@ bool CmdLineParser::loadAddons(Settings& settings)
21002109

21012110
bool CmdLineParser::loadCppcheckCfg()
21022111
{
2103-
if (!mSettings.cppcheckCfgProductName.empty())
2104-
return true;
2112+
if (!mSettings.settingsFiles.empty())
2113+
{
2114+
// should never happen - programming error
2115+
mLogger.printError("cppcheck.cfg has already been loaded from " + mSettings.settingsFiles[0]);
2116+
return false;
2117+
}
21052118
const std::string cfgErr = Settings::loadCppcheckCfg(mSettings, mSuppressions, mSettings.debuglookup || mSettings.debuglookupConfig);
21062119
if (!cfgErr.empty()) {
21072120
mLogger.printError("could not load cppcheck.cfg - " + cfgErr);

cli/cmdlineparser.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,11 +112,9 @@ class CmdLineParser {
112112
/**
113113
* Print help text to the console.
114114
*/
115-
void printHelp() const;
115+
void printHelp(bool premium) const;
116116

117117
private:
118-
bool isCppcheckPremium() const;
119-
120118
template<typename T>
121119
bool parseNumberArg(const char* const arg, std::size_t offset, T& num, bool mustBePositive = false)
122120
{

gui/main.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ static void ShowUsage()
130130

131131
static void ShowVersion()
132132
{
133+
// TODO: should only *not* show a dialog when we are on a commnd-line
133134
#if defined(_WIN32)
134135
AboutDialog *dlg = new AboutDialog(CppCheck::version(), CppCheck::extraVersion(), 0);
135136
dlg->exec();

gui/mainwindow.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ MainWindow::MainWindow(TranslationHandler* th, QSettings* settings) :
124124
mSelectLanguageActions(new QActionGroup(this)),
125125
mSelectReportActions(new QActionGroup(this))
126126
{
127+
// TODO: this is duplicated in cli/cmdlineparser.cpp
127128
{
128129
Settings tempSettings;
129130
tempSettings.exename = QCoreApplication::applicationFilePath().toStdString();
@@ -1058,6 +1059,8 @@ bool MainWindow::getCppcheckSettings(Settings& settings, Suppressions& supprs)
10581059
return false;
10591060
}
10601061

1062+
settings.premium = startsWith(settings.cppcheckCfgProductName, "Cppcheck Premium");
1063+
10611064
const auto cfgAddons = settings.addons;
10621065
settings.addons.clear();
10631066
for (const std::string& addon : cfgAddons) {
@@ -1713,6 +1716,7 @@ void MainWindow::formatAndSetTitle(const QString &text)
17131716
nameWithVersion += " (" + extraVersion + ")";
17141717
}
17151718

1719+
// TODO: should not contain the version
17161720
if (!mCppcheckCfgProductName.isEmpty())
17171721
nameWithVersion = mCppcheckCfgProductName;
17181722

@@ -2240,7 +2244,9 @@ void MainWindow::replyFinished(QNetworkReply *reply) {
22402244
const QString str = reply->readAll();
22412245
qDebug() << "Response: " << str;
22422246
if (reply->url().fileName() == "version.txt") {
2247+
// TODO: lacks extra version
22432248
QString nameWithVersion = QString("Cppcheck %1").arg(CppCheck::version());
2249+
// TODO: this should not contain the version
22442250
if (!mCppcheckCfgProductName.isEmpty())
22452251
nameWithVersion = mCppcheckCfgProductName;
22462252
const int appVersion = getVersion(nameWithVersion);

gui/xmlreportv2.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ void XmlReportV2::writeHeader()
9595
{
9696
const auto nameAndVersion = Settings::getNameAndVersion(mProductName.toStdString());
9797
const QString name = QString::fromStdString(nameAndVersion.first);
98+
// TODO: lacks extraVersion
9899
const QString version = nameAndVersion.first.empty() ? CppCheck::version() : QString::fromStdString(nameAndVersion.second);
99100

100101
mXmlWriter->setAutoFormatting(true);

lib/errorlogger.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,7 @@ std::string ErrorMessage::getXMLHeader(std::string productName, int xmlVersion)
433433
{
434434
const auto nameAndVersion = Settings::getNameAndVersion(productName);
435435
productName = nameAndVersion.first;
436+
// TODO: lacks extra version
436437
const std::string version = nameAndVersion.first.empty() ? CppCheck::version() : nameAndVersion.second;
437438

438439
tinyxml2::XMLPrinter printer;

lib/settings.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ Settings::Settings()
6767

6868
std::string Settings::loadCppcheckCfg(Settings& settings, Suppressions& suppressions, bool debug)
6969
{
70-
// TODO: this always needs to be run *after* the Settings has been filled
7170
static const std::string cfgFilename = "cppcheck.cfg";
7271
std::string fileName;
7372
#ifdef FILESDIR
@@ -167,6 +166,8 @@ std::string Settings::loadCppcheckCfg(Settings& settings, Suppressions& suppress
167166
}
168167
}
169168

169+
settings.settingsFiles.emplace_back(std::move(fileName));
170+
170171
return "";
171172
}
172173

lib/settings.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,9 @@ class CPPCHECKLIB WARN_UNUSED Settings {
298298
/** @brief plist output (--plist-output=&lt;dir&gt;) */
299299
std::string plistOutput;
300300

301+
/** @brief Are we Cppcheck Premium */
302+
bool premium{};
303+
301304
/** @brief Extra arguments for Cppcheck Premium addon */
302305
std::string premiumArgs;
303306

@@ -384,6 +387,9 @@ class CPPCHECKLIB WARN_UNUSED Settings {
384387

385388
SafeChecks safeChecks;
386389

390+
/** @brief the files we successfully loaded settings from */
391+
std::vector<std::string> settingsFiles;
392+
387393
SimpleEnableGroup<Severity> severity;
388394
SimpleEnableGroup<Certainty> certainty;
389395
SimpleEnableGroup<Checks> checks;

test/cli/other_test.py

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
import sys
66
import pytest
77
import json
8+
import shutil
89

9-
from testutils import cppcheck, assert_cppcheck, cppcheck_ex
10+
from testutils import cppcheck, assert_cppcheck, cppcheck_ex, __lookup_cppcheck_exe
1011
from xml.etree import ElementTree
1112

1213

@@ -1962,25 +1963,25 @@ def test_addon_lookup_ext_notfound(tmpdir):
19621963

19631964

19641965
# TODO: test with FILESDIR
1965-
@pytest.mark.skip
19661966
def test_config_lookup(tmpdir):
1967+
# cppcheck.cfg needs to be next to executable
1968+
exe = shutil.copy2(__lookup_cppcheck_exe(), tmpdir)
1969+
shutil.copytree(os.path.join(os.path.dirname(__lookup_cppcheck_exe()), 'cfg'), os.path.join(tmpdir, 'cfg'))
1970+
19671971
test_file = os.path.join(tmpdir, 'test.c')
19681972
with open(test_file, 'wt'):
19691973
pass
19701974

1971-
# TODO: needs to be in exepath so this is found
19721975
config_file = os.path.join(tmpdir, 'cppcheck.cfg')
1973-
with open(config_file, 'wt'):
1974-
pass
1976+
with open(config_file, 'wt') as f:
1977+
f.write(json.dumps({}))
19751978

1976-
exitcode, stdout, stderr, exe = cppcheck_ex(['--debug-lookup=config', '--addon=misra', test_file], cwd=tmpdir)
1979+
exitcode, stdout, stderr, exe = cppcheck_ex(['--debug-lookup=config', test_file], cwd=tmpdir, cppcheck_exe=exe)
19771980
exepath = os.path.dirname(exe)
19781981
exepath_sep = exepath + os.path.sep
19791982
assert exitcode == 0, stdout if stdout else stderr
1980-
lines = stdout.splitlines()
1981-
assert lines == [
1983+
assert stdout.splitlines() == [
19821984
"looking for '{}cppcheck.cfg'".format(exepath_sep),
1983-
'no configuration found',
19841985
'Checking {} ...'.format(test_file)
19851986
]
19861987

@@ -2003,6 +2004,29 @@ def test_config_lookup_notfound(tmpdir):
20032004
]
20042005

20052006

2007+
def test_config_invalid(tmpdir):
2008+
# cppcheck.cfg needs to be next to executable
2009+
exe = shutil.copy2(__lookup_cppcheck_exe(), tmpdir)
2010+
shutil.copytree(os.path.join(os.path.dirname(__lookup_cppcheck_exe()), 'cfg'), os.path.join(tmpdir, 'cfg'))
2011+
2012+
test_file = os.path.join(tmpdir, 'test.c')
2013+
with open(test_file, 'wt'):
2014+
pass
2015+
2016+
config_file = os.path.join(tmpdir, 'cppcheck.cfg')
2017+
with open(config_file, 'wt'):
2018+
pass
2019+
2020+
exitcode, stdout, stderr, exe = cppcheck_ex(['--debug-lookup=config', test_file], cwd=tmpdir, cppcheck_exe=exe)
2021+
exepath = os.path.dirname(exe)
2022+
exepath_sep = exepath + os.path.sep
2023+
assert exitcode == 1, stdout if stdout else stderr
2024+
assert stdout.splitlines() == [
2025+
"looking for '{}cppcheck.cfg'".format(exepath_sep),
2026+
'cppcheck: error: could not load cppcheck.cfg - not a valid JSON - syntax error at line 1 near: '
2027+
]
2028+
2029+
20062030
def test_checkers_report(tmpdir):
20072031
test_file = os.path.join(tmpdir, 'test.c')
20082032
with open(test_file, 'wt') as f:
@@ -3160,4 +3184,4 @@ def test_debug_valueflow_xml(tmp_path): # #13606
31603184
assert 'floatvalue' in value_elem[1].attrib
31613185
assert value_elem[1].attrib['floatvalue'] == '1e-07'
31623186
assert 'floatvalue' in value_elem[2].attrib
3163-
assert value_elem[2].attrib['floatvalue'] == '1e-07'
3187+
assert value_elem[2].attrib['floatvalue'] == '1e-07'

test/cli/premium_test.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,3 +114,11 @@ def _get_hash(s:str):
114114
assert hash1 != hash2
115115

116116

117+
def test_help(tmpdir):
118+
exe = __copy_cppcheck_premium(tmpdir)
119+
120+
exitcode, stdout, _ = cppcheck(['--help'], cppcheck_exe=exe)
121+
assert exitcode == 0
122+
assert stdout.startswith('Cppcheck ') # check for product name - TODO: should be "Cppcheck Premium"
123+
assert '--premium=' in stdout, stdout # check for premium option
124+
assert 'cppchecksolutions.com' in stdout, stdout # check for premium help link

0 commit comments

Comments
 (0)