Implement support for passing multiple file filters (#3479)

This commit is contained in:
Leon De Andrade 2021-11-23 22:51:45 +01:00 committed by GitHub
parent b80e24231b
commit 5b52f4946a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 26 additions and 16 deletions

View File

@ -362,7 +362,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
// use a file filter // use a file filter
else if (std::strncmp(argv[i], "--file-filter=", 14) == 0) else if (std::strncmp(argv[i], "--file-filter=", 14) == 0)
mSettings->fileFilter = argv[i] + 14; mSettings->fileFilters.push_back(argv[i] + 14);
// file list specified // file list specified
else if (std::strncmp(argv[i], "--file-list=", 12) == 0) else if (std::strncmp(argv[i], "--file-list=", 12) == 0)
@ -1055,6 +1055,7 @@ void CmdLineParser::printHelp()
" Used when certain messages should be displayed but\n" " Used when certain messages should be displayed but\n"
" should not cause a non-zero exitcode.\n" " should not cause a non-zero exitcode.\n"
" --file-filter=<str> Analyze only those files matching the given filter str\n" " --file-filter=<str> Analyze only those files matching the given filter str\n"
" Can be used multiple times\n"
" Example: --file-filter=*bar.cpp analyzes only files\n" " Example: --file-filter=*bar.cpp analyzes only files\n"
" that end with bar.cpp.\n" " that end with bar.cpp.\n"
" --file-list=<file> Specify the files to check in a text file. Add one\n" " --file-list=<file> Specify the files to check in a text file. Add one\n"

View File

@ -167,12 +167,12 @@ bool CppCheckExecutor::parseFromArgs(CppCheck *cppcheck, int argc, const char* c
#else #else
const bool caseSensitive = true; const bool caseSensitive = true;
#endif #endif
if (!mSettings->project.fileSettings.empty() && !mSettings->fileFilter.empty()) { if (!mSettings->project.fileSettings.empty() && !mSettings->fileFilters.empty()) {
// filter only for the selected filenames from all project files // filter only for the selected filenames from all project files
std::list<ImportProject::FileSettings> newList; std::list<ImportProject::FileSettings> newList;
for (const ImportProject::FileSettings &fsetting : settings.project.fileSettings) { for (const ImportProject::FileSettings &fsetting : settings.project.fileSettings) {
if (matchglob(mSettings->fileFilter, fsetting.filename)) { if (matchglobs(mSettings->fileFilters, fsetting.filename)) {
newList.emplace_back(fsetting); newList.emplace_back(fsetting);
} }
} }
@ -198,10 +198,10 @@ bool CppCheckExecutor::parseFromArgs(CppCheck *cppcheck, int argc, const char* c
if (!ignored.empty()) if (!ignored.empty())
std::cout << "cppcheck: Maybe all paths were ignored?" << std::endl; std::cout << "cppcheck: Maybe all paths were ignored?" << std::endl;
return false; return false;
} else if (!mSettings->fileFilter.empty() && settings.project.fileSettings.empty()) { } else if (!mSettings->fileFilters.empty() && settings.project.fileSettings.empty()) {
std::map<std::string, std::size_t> newMap; std::map<std::string, std::size_t> newMap;
for (std::map<std::string, std::size_t>::const_iterator i = mFiles.begin(); i != mFiles.end(); ++i) for (std::map<std::string, std::size_t>::const_iterator i = mFiles.begin(); i != mFiles.end(); ++i)
if (matchglob(mSettings->fileFilter, i->first)) { if (matchglobs(mSettings->fileFilters, i->first)) {
newMap[i->first] = i->second; newMap[i->first] = i->second;
} }
mFiles = newMap; mFiles = newMap;

View File

@ -195,19 +195,20 @@ ImportProject::Type ImportProject::import(const std::string &filename, Settings
if (!mPath.empty() && !endsWith(mPath,'/')) if (!mPath.empty() && !endsWith(mPath,'/'))
mPath += '/'; mPath += '/';
const std::string fileFilter = settings ? settings->fileFilter : std::string(); const std::vector<std::string> fileFilters =
settings ? settings->fileFilters : std::vector<std::string>();
if (endsWith(filename, ".json")) { if (endsWith(filename, ".json")) {
importCompileCommands(fin); importCompileCommands(fin);
setRelativePaths(filename); setRelativePaths(filename);
return ImportProject::Type::COMPILE_DB; return ImportProject::Type::COMPILE_DB;
} else if (endsWith(filename, ".sln")) { } else if (endsWith(filename, ".sln")) {
importSln(fin, mPath, fileFilter); importSln(fin, mPath, fileFilters);
setRelativePaths(filename); setRelativePaths(filename);
return ImportProject::Type::VS_SLN; return ImportProject::Type::VS_SLN;
} else if (endsWith(filename, ".vcxproj")) { } else if (endsWith(filename, ".vcxproj")) {
std::map<std::string, std::string, cppcheck::stricmp> variables; std::map<std::string, std::string, cppcheck::stricmp> variables;
importVcxproj(filename, variables, emptyString, fileFilter); importVcxproj(filename, variables, emptyString, fileFilters);
setRelativePaths(filename); setRelativePaths(filename);
return ImportProject::Type::VS_VCXPROJ; return ImportProject::Type::VS_VCXPROJ;
} else if (endsWith(filename, ".bpr")) { } else if (endsWith(filename, ".bpr")) {
@ -447,7 +448,7 @@ void ImportProject::importCompileCommands(std::istream &istr)
} }
} }
void ImportProject::importSln(std::istream &istr, const std::string &path, const std::string &fileFilter) void ImportProject::importSln(std::istream &istr, const std::string &path, const std::vector<std::string> &fileFilters)
{ {
std::map<std::string,std::string,cppcheck::stricmp> variables; std::map<std::string,std::string,cppcheck::stricmp> variables;
variables["SolutionDir"] = path; variables["SolutionDir"] = path;
@ -465,7 +466,7 @@ void ImportProject::importSln(std::istream &istr, const std::string &path, const
std::string vcxproj(line.substr(pos1+1, pos-pos1+7)); std::string vcxproj(line.substr(pos1+1, pos-pos1+7));
if (!Path::isAbsolute(vcxproj)) if (!Path::isAbsolute(vcxproj))
vcxproj = path + vcxproj; vcxproj = path + vcxproj;
importVcxproj(Path::fromNativeSeparators(vcxproj), variables, emptyString, fileFilter); importVcxproj(Path::fromNativeSeparators(vcxproj), variables, emptyString, fileFilters);
} }
} }
@ -658,7 +659,7 @@ static void loadVisualStudioProperties(const std::string &props, std::map<std::s
} }
} }
void ImportProject::importVcxproj(const std::string &filename, std::map<std::string, std::string, cppcheck::stricmp> &variables, const std::string &additionalIncludeDirectories, const std::string &fileFilter) void ImportProject::importVcxproj(const std::string &filename, std::map<std::string, std::string, cppcheck::stricmp> &variables, const std::string &additionalIncludeDirectories, const std::vector<std::string> &fileFilters)
{ {
variables["ProjectDir"] = Path::simplifyPath(Path::getPathFromFilename(filename)); variables["ProjectDir"] = Path::simplifyPath(Path::getPathFromFilename(filename));
@ -718,7 +719,7 @@ void ImportProject::importVcxproj(const std::string &filename, std::map<std::str
for (const std::string &c : compileList) { for (const std::string &c : compileList) {
const std::string cfilename = Path::simplifyPath(Path::isAbsolute(c) ? c : Path::getPathFromFilename(filename) + c); const std::string cfilename = Path::simplifyPath(Path::isAbsolute(c) ? c : Path::getPathFromFilename(filename) + c);
if (!fileFilter.empty() && !matchglob(fileFilter, cfilename)) if (!fileFilters.empty() && !matchglobs(fileFilters, cfilename))
continue; continue;
for (const ProjectConfiguration &p : projectConfigurationList) { for (const ProjectConfiguration &p : projectConfigurationList) {

View File

@ -109,8 +109,8 @@ protected:
void importCompileCommands(std::istream &istr); void importCompileCommands(std::istream &istr);
bool importCppcheckGuiProject(std::istream &istr, Settings *settings); bool importCppcheckGuiProject(std::istream &istr, Settings *settings);
private: private:
void importSln(std::istream &istr, const std::string &path, const std::string &fileFilter); void importSln(std::istream &istr, const std::string &path, const std::vector<std::string> &fileFilters);
void importVcxproj(const std::string &filename, std::map<std::string, std::string, cppcheck::stricmp> &variables, const std::string &additionalIncludeDirectories, const std::string &fileFilter); void importVcxproj(const std::string &filename, std::map<std::string, std::string, cppcheck::stricmp> &variables, const std::string &additionalIncludeDirectories, const std::vector<std::string> &fileFilters);
void importBcb6Prj(const std::string &projectFilename); void importBcb6Prj(const std::string &projectFilename);
void setRelativePaths(const std::string &filename); void setRelativePaths(const std::string &filename);

View File

@ -193,8 +193,8 @@ public:
Default value is 0. */ Default value is 0. */
int exitCode; int exitCode;
/** @brief --file-filter for analyzing special files */ /** @brief List of --file-filter for analyzing special files */
std::string fileFilter; std::vector<std::string> fileFilters;
/** @brief Force checking the files with "too many" configurations (--force). */ /** @brief Force checking the files with "too many" configurations (--force). */
bool force; bool force;

View File

@ -112,3 +112,9 @@ bool matchglob(const std::string& pattern, const std::string& name)
n++; n++;
} }
} }
bool matchglobs(const std::vector<std::string> &patterns, const std::string &name) {
return std::any_of(begin(patterns), end(patterns), [&name](const std::string &pattern) {
return matchglob(pattern, name);
});
}

View File

@ -152,6 +152,8 @@ CPPCHECKLIB bool isValidGlobPattern(const std::string& pattern);
CPPCHECKLIB bool matchglob(const std::string& pattern, const std::string& name); CPPCHECKLIB bool matchglob(const std::string& pattern, const std::string& name);
CPPCHECKLIB bool matchglobs(const std::vector<std::string> &patterns, const std::string &name);
#define UNUSED(x) (void)(x) #define UNUSED(x) (void)(x)
// Use the nonneg macro when you want to assert that a variable/argument is not negative // Use the nonneg macro when you want to assert that a variable/argument is not negative