diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index 48592a3e5c0..2343652fa61 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -382,6 +382,7 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a bool def = false; bool maxconfigs = false; bool debug = false; + bool inputAsFilter = false; // set by: --file-filter=+ ImportProject::Type projectType = ImportProject::Type::NONE; ImportProject project; @@ -768,6 +769,8 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a mLogger.printError("Failed: --file-filter=-"); return Result::Fail; } + } else if (std::strcmp(filter, "+") == 0) { + inputAsFilter = true; } else { mSettings.fileFilters.emplace_back(filter); } @@ -1582,6 +1585,11 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a //mLogger.printMessage("whole program analysis requires --cppcheck-build-dir to be active with -j."); } + if (inputAsFilter) { + mSettings.fileFilters.insert(mSettings.fileFilters.end(), mPathNames.cbegin(), mPathNames.cend()); + mPathNames.clear(); + } + if (!mPathNames.empty() && projectType != ImportProject::Type::NONE) { mLogger.printError("--project cannot be used in conjunction with source files."); return Result::Fail; @@ -1777,10 +1785,12 @@ void CmdLineParser::printHelp() const " --exitcode-suppressions=\n" " Used when certain messages should be displayed but\n" " should not cause a non-zero exitcode.\n" - " --file-filter= Analyze only those files matching the given filter str\n" - " Can be used multiple times\n" + " --file-filter= Analyze only those files matching the given filter str.\n" + " Can be used multiple times. When str is '-', the file\n" + " filter will be read from standard input. When str is '+',\n" + " given files on CLI will be treated as file filters.\n" " Example: --file-filter=*bar.cpp analyzes only files\n" - " that end with bar.cpp.\n" + " that end with bar.cpp.\n" " --file-list= Specify the files to check in a text file. Add one\n" " filename per line. When file is '-,' the file list will\n" " be read from standard input.\n" diff --git a/test/cli/more-projects_test.py b/test/cli/more-projects_test.py index 71959e7f4c8..f3ed273c4b9 100644 --- a/test/cli/more-projects_test.py +++ b/test/cli/more-projects_test.py @@ -295,7 +295,13 @@ def test_clang_tidy(tmpdir): assert stderr == '' -def test_project_file_filter(tmpdir): +@pytest.mark.parametrize("file_filter", [ + ['--file-filter=test.cpp'], + ['--file-filter=*.cpp'], + ['--file-filter=+', 'test.cpp'], + ['--file-filter=+', '*.cpp'], +]) +def test_project_file_filter(tmpdir, file_filter): test_file = os.path.join(tmpdir, 'test.cpp') with open(test_file, 'wt') as f: pass @@ -310,7 +316,7 @@ def test_project_file_filter(tmpdir): """.format(test_file)) - args = ['--file-filter=*.cpp', '--project={}'.format(project_file)] + args = file_filter + ['--project={}'.format(project_file)] out_lines = [ 'Checking {} ...'.format(test_file) ] @@ -318,7 +324,11 @@ def test_project_file_filter(tmpdir): assert_cppcheck(args, ec_exp=0, err_exp=[], out_exp=out_lines) -def test_project_file_filter_2(tmpdir): +@pytest.mark.parametrize("file_filter", [ + ['--file-filter=*.cpp'], + ['--file-filter=+', '*.cpp'], +]) +def test_project_file_filter_cpp(tmpdir, file_filter): test_file_1 = os.path.join(tmpdir, 'test.cpp') with open(test_file_1, 'wt') as f: pass @@ -337,7 +347,7 @@ def test_project_file_filter_2(tmpdir): """.format(test_file_1, test_file_2)) - args = ['--file-filter=*.cpp', '--project={}'.format(project_file)] + args = file_filter + ['--project={}'.format(project_file)] out_lines = [ 'Checking {} ...'.format(test_file_1) ] @@ -345,7 +355,11 @@ def test_project_file_filter_2(tmpdir): assert_cppcheck(args, ec_exp=0, err_exp=[], out_exp=out_lines) -def test_project_file_filter_3(tmpdir): +@pytest.mark.parametrize("file_filter", [ + ['--file-filter=*.c'], + ['--file-filter=+', '*.c'], +]) +def test_project_file_filter_c(tmpdir, file_filter): test_file_1 = os.path.join(tmpdir, 'test.cpp') with open(test_file_1, 'wt') as f: pass @@ -364,7 +378,7 @@ def test_project_file_filter_3(tmpdir): """.format(test_file_1, test_file_2)) - args = ['--file-filter=*.c', '--project={}'.format(project_file)] + args = file_filter + ['--project={}'.format(project_file)] out_lines = [ 'Checking {} ...'.format(test_file_2) ] diff --git a/test/testcmdlineparser.cpp b/test/testcmdlineparser.cpp index 65bf6906841..3527ff6cc76 100644 --- a/test/testcmdlineparser.cpp +++ b/test/testcmdlineparser.cpp @@ -208,6 +208,7 @@ class TestCmdlineParser : public TestFixture { TEST_CASE(fileFilterFileWithDetailsSimplifiedPath); TEST_CASE(fileFilterFileWithDetailsCase); TEST_CASE(fileFilterStdin); + TEST_CASE(fileFilterPlus); TEST_CASE(fileFilterNoMatch); TEST_CASE(fileList); TEST_CASE(fileListNoFile); @@ -1233,6 +1234,19 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS("file2.cpp", settings->fileFilters[1]); } + void fileFilterPlus() { + REDIRECT; + ScopedFile file("project.cppcheck", + "\n" + "\n" + "\n" + "\n" + ""); + const char * const argv[] = {"cppcheck", "--project=project.cppcheck", "--file-filter=+", "src/file.cpp"}; + ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); + ASSERT_EQUALS("src/file.cpp", settings->fileFilters.front()); + } + void fileFilterNoMatch() { REDIRECT; RedirectInput input("notexist1.c\nnotexist2.cpp\n");