diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index 4e567e47d9f..47759b75196 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -1702,11 +1702,6 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a void CmdLineParser::printHelp(bool premium) const { - // TODO: fetch URL from config like product name? - const std::string manualUrl(premium ? - "https://files.cppchecksolutions.com/manual.pdf" : - "https://cppcheck.sourceforge.io/manual.pdf"); - std::ostringstream oss; // TODO: display product name oss << "Cppcheck - A tool for static C/C++ code analysis\n" @@ -2077,7 +2072,7 @@ void CmdLineParser::printHelp(bool premium) const " cppcheck -I inc1/ -I inc2/ f.cpp\n" "\n" "For more information:\n" - " " << manualUrl << "\n" + " " << mSettings.manualUrl << "\n" "\n" "Many thanks to the 3rd party libraries we use:\n" " * tinyxml2 -- loading project/library/ctu files.\n" diff --git a/lib/settings.cpp b/lib/settings.cpp index 19b8ce5142f..8e4b8d2a6d4 100644 --- a/lib/settings.cpp +++ b/lib/settings.cpp @@ -117,6 +117,15 @@ std::string Settings::loadCppcheckCfg(Settings& settings, Suppressions& suppress settings.cppcheckCfgProductName = v.get(); } } + { + const auto it = utils::as_const(obj).find("manualUrl"); + if (it != obj.cend()) { + const auto& v = it->second; + if (!v.is()) + return "'manualUrl' is not a string"; + settings.manualUrl = v.get(); + } + } { const auto it = utils::as_const(obj).find("about"); if (it != obj.cend()) { diff --git a/lib/settings.h b/lib/settings.h index cae78e850eb..04541cda08c 100644 --- a/lib/settings.h +++ b/lib/settings.h @@ -291,6 +291,8 @@ class CPPCHECKLIB WARN_UNUSED Settings { int loadAverage{}; #endif + std::string manualUrl{"https://cppcheck.sourceforge.io/manual.pdf"}; + /** --max-configs value */ int maxConfigsOption = 0; // "Not Assigned" value diff --git a/test/cli/premium_test.py b/test/cli/premium_test.py index 1bb01260b42..ddf7b1e2fbe 100644 --- a/test/cli/premium_test.py +++ b/test/cli/premium_test.py @@ -29,6 +29,7 @@ def __copy_cppcheck_premium(tmpdir): "addons": [], "productName": "NAME", "about": "NAME", + "manualUrl" : "https://files.cppchecksolutions.com/manual.pdf", "safety": true } """.replace('NAME', __PRODUCT_NAME)) diff --git a/test/testcmdlineparser.cpp b/test/testcmdlineparser.cpp index 038d1ea0b01..7b5c646e4bf 100644 --- a/test/testcmdlineparser.cpp +++ b/test/testcmdlineparser.cpp @@ -551,7 +551,8 @@ class TestCmdlineParser : public TestFixture { REDIRECT; ScopedFile file(Path::join(Path::getPathFromFilename(Path::getCurrentExecutablePath("")), "cppcheck.cfg"), "{\n" - "\"productName\": \"Cppcheck Premium\"" + "\"productName\": \"Cppcheck Premium\"," + "\"manualUrl\": \"https://docs.notcppcheck.com/manual.pdf\"" "}\n"); const char * const argv[] = {"cppcheck"}; ASSERT_EQUALS_ENUM(CmdLineParser::Result::Exit, parseFromArgs(argv)); @@ -559,7 +560,7 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS(file.path(), *settings->settingsFiles.cbegin()); const std::string log_str = logger->str(); ASSERT_MSG(startsWith(log_str, "Cppcheck - A tool for static C/C++ code analysis"), "header"); - ASSERT_MSG(log_str.find("https://files.cppchecksolutions.com/manual.pdf") != std::string::npos, "help url"); + ASSERT_MSG(log_str.find("https://docs.notcppcheck.com/manual.pdf") != std::string::npos, "help url"); } void nooptionsWithInvalidCfg() { @@ -589,7 +590,8 @@ class TestCmdlineParser : public TestFixture { REDIRECT; ScopedFile file(Path::join(Path::getPathFromFilename(Path::getCurrentExecutablePath("")), "cppcheck.cfg"), "{\n" - "\"productName\": \"Cppcheck Premium\"" + "\"productName\": \"Cppcheck Premium\"," + "\"manualUrl\": \"https://docs.notcppcheck.com/manual.pdf\"" "}\n"); const char * const argv[] = {"cppcheck", "-h"}; ASSERT_EQUALS_ENUM(CmdLineParser::Result::Exit, parseFromArgs(argv)); @@ -597,7 +599,7 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS(file.path(), *settings->settingsFiles.cbegin()); const std::string log_str = logger->str(); ASSERT_MSG(startsWith(log_str, "Cppcheck - A tool for static C/C++ code analysis"), "header"); - ASSERT_MSG(log_str.find("https://files.cppchecksolutions.com/manual.pdf") != std::string::npos, "help url"); + ASSERT_MSG(log_str.find("https://docs.notcppcheck.com/manual.pdf") != std::string::npos, "help url"); } void helplong() { @@ -618,7 +620,8 @@ class TestCmdlineParser : public TestFixture { REDIRECT; ScopedFile file(Path::join(Path::getPathFromFilename(Path::getCurrentExecutablePath("")), "cppcheck.cfg"), "{\n" - "\"productName\": \"Cppcheck Premium\"" + "\"productName\": \"Cppcheck Premium\"," + "\"manualUrl\": \"https://docs.notcppcheck.com/manual.pdf\"" "}\n"); const char * const argv[] = {"cppcheck", "--help"}; ASSERT_EQUALS_ENUM(CmdLineParser::Result::Exit, parseFromArgs(argv)); @@ -626,7 +629,7 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS(file.path(), *settings->settingsFiles.cbegin()); const std::string log_str = logger->str(); ASSERT_MSG(startsWith(log_str, "Cppcheck - A tool for static C/C++ code analysis"), "header"); - ASSERT_MSG(log_str.find("https://files.cppchecksolutions.com/manual.pdf") != std::string::npos, "help url"); + ASSERT_MSG(log_str.find("https://docs.notcppcheck.com/manual.pdf") != std::string::npos, "help url"); } void version() { diff --git a/test/testsettings.cpp b/test/testsettings.cpp index fd8f62c1a82..7bc6aeb0352 100644 --- a/test/testsettings.cpp +++ b/test/testsettings.cpp @@ -236,6 +236,21 @@ class TestSettings : public TestFixture { R"({"suppressions": [1]}\n)"); ASSERT_EQUALS("'suppressions' array entry is not a string", Settings::loadCppcheckCfg(s, supprs)); } + { + Settings s; + Suppressions supprs; + ScopedFile file("cppcheck.cfg", + R"({"manualUrl": "https://docs.notcppcheck.com/manual.pdf"})"); + ASSERT_EQUALS("", Settings::loadCppcheckCfg(s, supprs)); + ASSERT_EQUALS("https://docs.notcppcheck.com/manual.pdf", s.manualUrl); + } + { + Settings s; + Suppressions supprs; + ScopedFile file("cppcheck.cfg", + R"({"manualUrl": 0}\n)"); + ASSERT_EQUALS("'manualUrl' is not a string", Settings::loadCppcheckCfg(s, supprs)); + } // TODO: test with FILESDIR }