From 2d6d8580d73cbd86f95b21f6a8776e646f8087e5 Mon Sep 17 00:00:00 2001 From: Kimmo Varis Date: Thu, 3 Feb 2011 14:43:42 +0200 Subject: [PATCH] Allow to exclude filenames (with paths). This expands the CLI exclude feature to also allow excluding filenames (with paths). When filename with recognized extension is given to -i option then matching filenames (with paths) are ignored when checking. Ticket #2538 (Allow excluding files from the checking) --- cli/cmdlineparser.cpp | 22 +++++++++----- cli/pathmatch.cpp | 42 ++++++++++++++++++-------- test/testcmdlineparser.cpp | 24 +++++++++++++++ test/testpathmatch.cpp | 62 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 130 insertions(+), 20 deletions(-) diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index 10482e6fc..b64229edf 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -26,6 +26,7 @@ #include "settings.h" #include "cmdlineparser.h" #include "path.h" +#include "filelister.h" // xml is used in rules #include "tinyxml/tinyxml.h" @@ -361,7 +362,7 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[]) path = argv[i]; } - // "-Ipath/" + // "-ipath/" else { path = 2 + argv[i]; @@ -371,10 +372,13 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[]) { path = Path::fromNativeSeparators(path); - // If path doesn't end with / or \, add it - if (path[path.length()-1] != '/') - path += '/'; - + // If not "known" filename extension then assume it is path + if (!FileLister::acceptFile(path)) + { + // If path doesn't end with / or \, add it + if (path[path.length()-1] != '/') + path += '/'; + } _ignoredPaths.push_back(path); } } @@ -514,7 +518,8 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[]) if (doc.LoadFile(12+argv[i])) { TiXmlElement *node = doc.FirstChildElement(); - for (; node && node->ValueStr() == "rule"; node = node->NextSiblingElement()) { + for (; node && node->ValueStr() == "rule"; node = node->NextSiblingElement()) + { Settings::Rule rule; TiXmlElement *pattern = node->FirstChildElement("pattern"); @@ -641,8 +646,9 @@ void CmdLineParser::PrintHelp() " several paths. First given path is checked first. If\n" " paths are relative to source files, this is not needed\n" " -i [dir] Give path to ignore. Give several -i parameters to ignore\n" - " several paths. If any part of the checked path matches the\n" - " given dir the path is ignored and not checked.\n" + " several paths. Give directory name or filename with path\n" + " as parameter. Directory name is matched to all parts of the\n" + " path." " --inline-suppr Enable inline suppressions. Use them by placing one or\n" " more comments, like: // cppcheck-suppress warningId\n" " on the lines before the warning to suppress.\n" diff --git a/cli/pathmatch.cpp b/cli/pathmatch.cpp index 270f5c1da..db36d99c9 100644 --- a/cli/pathmatch.cpp +++ b/cli/pathmatch.cpp @@ -31,19 +31,37 @@ bool PathMatch::Match(const std::string &path) std::vector::const_iterator iterMask; for (iterMask = _masks.begin(); iterMask != _masks.end(); ++iterMask) { - std::string findpath(path); - if (findpath[findpath.length() - 1] != '/') - findpath = RemoveFilename(findpath); + // Filtering directory name + if ((*iterMask)[(*iterMask).length() - 1] == '/') + { + std::string findpath(path); + if (findpath[findpath.length() - 1] != '/') + findpath = RemoveFilename(findpath); - // Match relative paths starting with mask - // -isrc matches src/foo.cpp - if (findpath.compare(0, (*iterMask).size(), *iterMask) == 0) - return true; - // Match only full directory name in middle or end of the path - // -isrc matches myproject/src/ but does not match - // myproject/srcfiles/ or myproject/mysrc/ - if (findpath.find("/" + *iterMask) != std::string::npos) - return true; + if ((*iterMask).length() > findpath.length()) + continue; + // Match relative paths starting with mask + // -isrc matches src/foo.cpp + if (findpath.compare(0, (*iterMask).size(), *iterMask) == 0) + return true; + // Match only full directory name in middle or end of the path + // -isrc matches myproject/src/ but does not match + // myproject/srcfiles/ or myproject/mysrc/ + if (findpath.find("/" + *iterMask) != std::string::npos) + return true; + } + // Filtering filename + else + { + if ((*iterMask).length() > path.length()) + continue; + // Check if path ends with mask + // -ifoo.cpp matches (./)foo.c, src/foo.cpp and proj/src/foo.cpp + // -isrc/file.cpp matches src/foo.cpp and proj/src/foo.cpp + if (path.compare(path.size() - (*iterMask).size(), path.size(), *iterMask) == 0) + return true; + + } } return false; } diff --git a/test/testcmdlineparser.cpp b/test/testcmdlineparser.cpp index 91cd92e01..bdbd1e4d7 100644 --- a/test/testcmdlineparser.cpp +++ b/test/testcmdlineparser.cpp @@ -95,6 +95,8 @@ private: TEST_CASE(ignorepaths2) TEST_CASE(ignorepaths3) TEST_CASE(ignorepaths4) + TEST_CASE(ignorefilepaths1) + TEST_CASE(ignorefilepaths2) TEST_CASE(unknownParam); } @@ -740,6 +742,28 @@ private: ASSERT_EQUALS("module/", parser.GetIgnoredPaths()[1]); } + void ignorefilepaths1() + { + REDIRECT; + const char *argv[] = {"cppcheck", "-ifoo.cpp", "file.cpp"}; + Settings settings; + CmdLineParser parser(&settings); + ASSERT(parser.ParseFromArgs(3, argv)); + ASSERT_EQUALS(1, parser.GetIgnoredPaths().size()); + ASSERT_EQUALS("foo.cpp", parser.GetIgnoredPaths()[0]); + } + + void ignorefilepaths2() + { + REDIRECT; + const char *argv[] = {"cppcheck", "-isrc/foo.cpp", "file.cpp"}; + Settings settings; + CmdLineParser parser(&settings); + ASSERT(parser.ParseFromArgs(3, argv)); + ASSERT_EQUALS(1, parser.GetIgnoredPaths().size()); + ASSERT_EQUALS("src/foo.cpp", parser.GetIgnoredPaths()[0]); + } + void unknownParam() { REDIRECT; diff --git a/test/testpathmatch.cpp b/test/testpathmatch.cpp index f929308e7..1f552e0f8 100644 --- a/test/testpathmatch.cpp +++ b/test/testpathmatch.cpp @@ -45,6 +45,13 @@ private: TEST_CASE(onemasklongerpath1); TEST_CASE(onemasklongerpath2); TEST_CASE(onemasklongerpath3); + TEST_CASE(filemask1); + TEST_CASE(filemask2); + TEST_CASE(filemask3); + TEST_CASE(filemaskpath1); + TEST_CASE(filemaskpath2); + TEST_CASE(filemaskpath3); + TEST_CASE(filemaskpath4); } void emptymaskemptyfile() @@ -191,6 +198,61 @@ private: ASSERT(match.Match("project/src/module/")); } + void filemask1() + { + std::vector masks; + masks.push_back("foo.cpp"); + PathMatch match(masks); + ASSERT(match.Match("foo.cpp")); + } + + void filemask2() + { + std::vector masks; + masks.push_back("foo.cpp"); + PathMatch match(masks); + ASSERT(match.Match("../foo.cpp")); + } + + void filemask3() + { + std::vector masks; + masks.push_back("foo.cpp"); + PathMatch match(masks); + ASSERT(match.Match("src/foo.cpp")); + } + + void filemaskpath1() + { + std::vector masks; + masks.push_back("src/foo.cpp"); + PathMatch match(masks); + ASSERT(match.Match("src/foo.cpp")); + } + + void filemaskpath2() + { + std::vector masks; + masks.push_back("src/foo.cpp"); + PathMatch match(masks); + ASSERT(match.Match("proj/src/foo.cpp")); + } + + void filemaskpath3() + { + std::vector masks; + masks.push_back("src/foo.cpp"); + PathMatch match(masks); + ASSERT(!match.Match("foo.cpp")); + } + + void filemaskpath4() + { + std::vector masks; + masks.push_back("src/foo.cpp"); + PathMatch match(masks); + ASSERT(!match.Match("bar/foo.cpp")); + } }; REGISTER_TEST(TestPathMatch)