From fcd5cda97f10085c7def7fda6fc6199f624010ce Mon Sep 17 00:00:00 2001 From: fuzzelhjb Date: Fri, 10 Jan 2020 08:57:37 +0100 Subject: [PATCH] Check selected files from project (#2378) --- cli/cmdlineparser.cpp | 7 +++++++ cli/cppcheckexecutor.cpp | 35 ++++++++++++++++++++++++++++++++--- lib/settings.h | 3 +++ man/manual.md | 10 ++++++++++ test/cli/test-proj2.py | 10 +++++++++- 5 files changed, 61 insertions(+), 4 deletions(-) diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index 3fbc7f6c6..292327051 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -376,6 +376,10 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) mSettings->xml = true; } + // use a file filter + else if (std::strncmp(argv[i], "--file-filter=", 14) == 0) + mSettings->fileFilter = std::string(argv[i] + 14); + // Only print something when there are errors else if (std::strcmp(argv[i], "-q") == 0 || std::strcmp(argv[i], "--quiet") == 0) mSettings->quiet = true; @@ -1035,6 +1039,9 @@ void CmdLineParser::printHelp() " --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" + " Example: --file-filter=*bar.cpp analyzes only files\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/cli/cppcheckexecutor.cpp b/cli/cppcheckexecutor.cpp index ea5d89767..7f9b2ab98 100644 --- a/cli/cppcheckexecutor.cpp +++ b/cli/cppcheckexecutor.cpp @@ -159,7 +159,23 @@ bool CppCheckExecutor::parseFromArgs(CppCheck *cppcheck, int argc, const char* c #else const bool caseSensitive = true; #endif - if (!pathnames.empty()) { + if (!mSettings->project.fileSettings.empty() && !mSettings->fileFilter.empty()) { + // filter only for the selected filenames from all project files + std::list newList; + + for (const ImportProject::FileSettings &fsetting : settings.project.fileSettings) { + if (Suppressions::matchglob(mSettings->fileFilter, fsetting.filename)) { + newList.push_back(fsetting); + } + } + if (!newList.empty()) + settings.project.fileSettings = newList; + else { + std::cout << "cppcheck: error: could not find any files matching the filter." << std::endl; + return false; + } + } + else if (!pathnames.empty()) { // Execute recursiveAddFiles() to each given file parameter const PathMatch matcher(ignored, caseSensitive); for (const std::string &pathname : pathnames) @@ -172,6 +188,20 @@ bool CppCheckExecutor::parseFromArgs(CppCheck *cppcheck, int argc, const char* c std::cout << "cppcheck: Maybe all paths were ignored?" << std::endl; return false; } + else if(!mSettings->fileFilter.empty()) { + std::map newMap; + for (std::map::const_iterator i = mFiles.begin(); i != mFiles.end(); ++i) + if (Suppressions::matchglob(mSettings->fileFilter, i->first)) { + newMap[i->first] = i->second; + } + mFiles = newMap; + if (mFiles.empty()) { + std::cout << "cppcheck: error: could not find any files matching the filter." << std::endl; + return false; + } + + } + return true; } @@ -890,9 +920,8 @@ int CppCheckExecutor::check_internal(CppCheck& cppcheck, int /*argc*/, const cha } } } else { - // filesettings - c = 0; + // check all files of the project for (const ImportProject::FileSettings &fs : settings.project.fileSettings) { returnValue += cppcheck.check(fs); ++c; diff --git a/lib/settings.h b/lib/settings.h index d72444c55..c60a2886a 100644 --- a/lib/settings.h +++ b/lib/settings.h @@ -79,6 +79,9 @@ public: /** @brief --cppcheck-build-dir */ std::string buildDir; + /** @brief --file-filter for analyzing special files */ + std::string fileFilter; + /** Is the 'configuration checking' wanted? */ bool checkConfiguration; diff --git a/man/manual.md b/man/manual.md index b6826398f..aaf8ad846 100644 --- a/man/manual.md +++ b/man/manual.md @@ -82,6 +82,16 @@ We don't know which approach (project file or manual configuration) will give yo Later chapters will describe this in more detail. +### Check files matching a given file filter + +With `--file-filter=` you can set a file filter and only those files matching the filter will be checked. + +For example: if you want to check only those files and folders starting from a subfolder src/ that start with "test" you have to type: + + cppcheck src/ --file-filter=src/test* + +Cppcheck first collects all files in src/ and will apply the filter after that. So the filter must start with the given start folder. + ### Excluding a file or folder from checking To exclude a file or folder, there are two options. The first option is to only provide the paths and files you want to check. diff --git a/test/cli/test-proj2.py b/test/cli/test-proj2.py index 953934d4f..b46f44c01 100644 --- a/test/cli/test-proj2.py +++ b/test/cli/test-proj2.py @@ -29,6 +29,15 @@ def cppcheck_local(args): os.chdir(cwd) return (ret, stdout, stderr) +def test_file_filter(): + ret, stdout, stderr = cppcheck(['proj2/','--file-filter=proj2/a/*']) + file1 = os.path.join('proj2', 'a', 'a.c') + file2 = os.path.join('proj2', 'b', 'b.c') + assert ret == 0 + assert stdout.find('Checking %s ...' % (file1)) >= 0 + ret, stdout, stderr = cppcheck(['proj2/','--file-filter=proj2/b*']) + assert ret == 0 + assert stdout.find('Checking %s ...' % (file2)) >= 0 def test_local_path(): create_compile_commands() @@ -150,4 +159,3 @@ def test_gui_project_loads_absolute_vs_solution(): import_project=os.path.join(os.getcwd(), 'proj2', 'proj2.sln').replace('\\', '/')) ret, stdout, stderr = cppcheck(['--project=test.cppcheck']) assert stderr == ERR_A + ERR_B -