diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index be5b3468f..1eb8d2fb3 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -282,6 +282,62 @@ bool CmdLineParser::fillSettingsFromArgs(int argc, const char* const argv[]) // TODO: error out on all missing given files/paths CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const argv[]) { + if (argc <= 1) { + printHelp(); + return Result::Exit; + } + + // check for exclusive options + for (int i = 1; i < argc; i++) { + // documentation.. + if (std::strcmp(argv[i], "--doc") == 0) { + std::ostringstream doc; + // Get documentation.. + for (const Check * it : Check::instances()) { + const std::string& name(it->name()); + const std::string info(it->classInfo()); + if (!name.empty() && !info.empty()) + doc << "## " << name << " ##\n" + << info << "\n"; + } + + mLogger.printRaw(doc.str()); + return Result::Exit; + } + + // print all possible error messages.. + if (std::strcmp(argv[i], "--errorlist") == 0) { + mSettings.loadCppcheckCfg(); + { + XMLErrorMessagesLogger xmlLogger; + std::cout << ErrorMessage::getXMLHeader(mSettings.cppcheckCfgProductName); + CppCheck::getErrorMessages(xmlLogger); + std::cout << ErrorMessage::getXMLFooter() << std::endl; + } + return Result::Exit; + } + + // Print help + if (std::strcmp(argv[i], "-h") == 0 || std::strcmp(argv[i], "--help") == 0) { + printHelp(); + return Result::Exit; + } + + if (std::strcmp(argv[i], "--version") == 0) { + mSettings.loadCppcheckCfg(); + if (!mSettings.cppcheckCfgProductName.empty()) { + mLogger.printRaw(mSettings.cppcheckCfgProductName); + } else { + const char * const extraVersion = CppCheck::extraVersion(); + if (*extraVersion != '\0') + mLogger.printRaw(std::string("Cppcheck ") + CppCheck::version() + " ("+ extraVersion + ')'); + else + mLogger.printRaw(std::string("Cppcheck ") + CppCheck::version()); + } + return Result::Exit; + } + } + bool def = false; bool maxconfigs = false; @@ -466,23 +522,6 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a } } - // documentation.. - else if (std::strcmp(argv[i], "--doc") == 0) { - // TODO: make an exclusive option - std::ostringstream doc; - // Get documentation.. - for (const Check * it : Check::instances()) { - const std::string& name(it->name()); - const std::string info(it->classInfo()); - if (!name.empty() && !info.empty()) - doc << "## " << name << " ##\n" - << info << "\n"; - } - - mLogger.printRaw(doc.str()); - return Result::Exit; - } - // dump cppcheck data else if (std::strcmp(argv[i], "--dump") == 0) mSettings.dump = true; @@ -506,19 +545,6 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a } } - // print all possible error messages.. - else if (std::strcmp(argv[i], "--errorlist") == 0) { - // TODO: make this an exclusive option - mSettings.loadCppcheckCfg(); - { - XMLErrorMessagesLogger xmlLogger; - std::cout << ErrorMessage::getXMLHeader(mSettings.cppcheckCfgProductName); - CppCheck::getErrorMessages(xmlLogger); - std::cout << ErrorMessage::getXMLFooter() << std::endl; - } - return Result::Exit; - } - // --error-exitcode=1 else if (std::strncmp(argv[i], "--error-exitcode=", 17) == 0) { if (!parseNumberArg(argv[i], 17, mSettings.exitCode)) @@ -592,13 +618,6 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a else if (std::strcmp(argv[i], "--funsigned-char") == 0) mSettings.platform.defaultSign = 'u'; - // Print help - else if (std::strcmp(argv[i], "-h") == 0 || std::strcmp(argv[i], "--help") == 0) { - // TODO: make this an exclusive option - printHelp(); - return Result::Exit; - } - // Ignored paths else if (std::strncmp(argv[i], "-i", 2) == 0) { std::string path; @@ -1150,21 +1169,6 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a else if (std::strcmp(argv[i], "-v") == 0 || std::strcmp(argv[i], "--verbose") == 0) mSettings.verbose = true; - else if (std::strcmp(argv[i], "--version") == 0) { - // TODO: make this an exclusive parameter - mSettings.loadCppcheckCfg(); - if (!mSettings.cppcheckCfgProductName.empty()) { - mLogger.printRaw(mSettings.cppcheckCfgProductName); - } else { - const char * const extraVersion = CppCheck::extraVersion(); - if (*extraVersion != '\0') - mLogger.printRaw(std::string("Cppcheck ") + CppCheck::version() + " ("+ extraVersion + ')'); - else - mLogger.printRaw(std::string("Cppcheck ") + CppCheck::version()); - } - return Result::Exit; - } - // Write results in results.xml else if (std::strcmp(argv[i], "--xml") == 0) mSettings.xml = true; @@ -1226,11 +1230,6 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a mLogger.printMessage("unusedFunction check can't be used with '-j' option. Disabling unusedFunction check."); } - if (argc <= 1) { - printHelp(); - return Result::Exit; - } - if (!mPathNames.empty() && project.projectType != ImportProject::Type::NONE) { mLogger.printError("--project cannot be used in conjunction with source files."); return Result::Fail; diff --git a/test/testcmdlineparser.cpp b/test/testcmdlineparser.cpp index dc54eba80..955a55751 100644 --- a/test/testcmdlineparser.cpp +++ b/test/testcmdlineparser.cpp @@ -119,9 +119,12 @@ private: void run() override { TEST_CASE(nooptions); TEST_CASE(helpshort); + TEST_CASE(helpshortExclusive); TEST_CASE(helplong); + TEST_CASE(helplongExclusive); TEST_CASE(version); TEST_CASE(versionWithCfg); + TEST_CASE(versionExclusive); TEST_CASE(onefile); TEST_CASE(onepath); TEST_CASE(optionwithoutfile); @@ -255,6 +258,7 @@ private: TEST_CASE(xmlverunknown); TEST_CASE(xmlverinvalid); TEST_CASE(doc); + TEST_CASE(docExclusive); TEST_CASE(showtimeFile); TEST_CASE(showtimeFileTotal); TEST_CASE(showtimeTop5); @@ -264,6 +268,7 @@ private: TEST_CASE(showtimeEmpty); TEST_CASE(showtimeInvalid); TEST_CASE(errorlist); + TEST_CASE(errorlistExclusive); TEST_CASE(ignorepathsnopath); #if defined(USE_WINDOWS_SEH) || defined(USE_UNIX_SIGNAL_HANDLING) TEST_CASE(exceptionhandling); @@ -373,6 +378,14 @@ private: ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } + void helpshortExclusive() { + REDIRECT; + const char * const argv[] = {"cppcheck", "--library=missing", "-h"}; + ASSERT_EQUALS(CmdLineParser::Result::Exit, parser->parseFromArgs(3, argv)); + ASSERT(startsWith(logger->str(), "Cppcheck - A tool for static C/C++ code analysis")); + ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); + } + void helplong() { REDIRECT; const char * const argv[] = {"cppcheck", "--help"}; @@ -381,6 +394,14 @@ private: ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } + void helplongExclusive() { + REDIRECT; + const char * const argv[] = {"cppcheck", "--library=missing", "--help"}; + ASSERT_EQUALS(CmdLineParser::Result::Exit, parser->parseFromArgs(3, argv)); + ASSERT(startsWith(logger->str(), "Cppcheck - A tool for static C/C++ code analysis")); + ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); + } + void version() { REDIRECT; const char * const argv[] = {"cppcheck", "--version"}; @@ -402,7 +423,15 @@ private: ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } - // TODO: test extraVersion + // TODO: test --version with extraVersion + + void versionExclusive() { + REDIRECT; + const char * const argv[] = {"cppcheck", "--library=missing", "--version"}; + ASSERT_EQUALS(CmdLineParser::Result::Exit, parser->parseFromArgs(3, argv)); + ASSERT_EQUALS("Cppcheck 2.13 dev\n", logger->str()); + ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); + } void onefile() { REDIRECT; @@ -1577,6 +1606,14 @@ private: ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } + void docExclusive() { + REDIRECT; + const char * const argv[] = {"cppcheck", "--library=missing", "--doc"}; + ASSERT_EQUALS(CmdLineParser::Result::Exit, parser->parseFromArgs(3, argv)); + ASSERT(startsWith(logger->str(), "## ")); + ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); + } + void showtimeSummary() { REDIRECT; const char * const argv[] = {"cppcheck", "--showtime=summary", "file.cpp"}; @@ -1659,6 +1696,15 @@ private: // TODO: test --errorlist with product name + void errorlistExclusive() { + REDIRECT; + const char * const argv[] = {"cppcheck", "--library=missing", "--errorlist"}; + ASSERT_EQUALS(CmdLineParser::Result::Exit, parser->parseFromArgs(3, argv)); + ASSERT_EQUALS("", logger->str()); // empty since it is logged via ErrorLogger + ASSERT(startsWith(GET_REDIRECT_OUTPUT, "\n")); + } + void ignorepathsnopath() { REDIRECT; const char * const argv[] = {"cppcheck", "-i"};