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)
This commit is contained in:
Kimmo Varis 2011-02-03 14:43:42 +02:00
parent 96d62553bc
commit 2d6d8580d7
4 changed files with 130 additions and 20 deletions

View File

@ -26,6 +26,7 @@
#include "settings.h" #include "settings.h"
#include "cmdlineparser.h" #include "cmdlineparser.h"
#include "path.h" #include "path.h"
#include "filelister.h"
// xml is used in rules // xml is used in rules
#include "tinyxml/tinyxml.h" #include "tinyxml/tinyxml.h"
@ -361,7 +362,7 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[])
path = argv[i]; path = argv[i];
} }
// "-Ipath/" // "-ipath/"
else else
{ {
path = 2 + argv[i]; path = 2 + argv[i];
@ -371,10 +372,13 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[])
{ {
path = Path::fromNativeSeparators(path); path = Path::fromNativeSeparators(path);
// If path doesn't end with / or \, add it // If not "known" filename extension then assume it is path
if (path[path.length()-1] != '/') if (!FileLister::acceptFile(path))
path += '/'; {
// If path doesn't end with / or \, add it
if (path[path.length()-1] != '/')
path += '/';
}
_ignoredPaths.push_back(path); _ignoredPaths.push_back(path);
} }
} }
@ -514,7 +518,8 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[])
if (doc.LoadFile(12+argv[i])) if (doc.LoadFile(12+argv[i]))
{ {
TiXmlElement *node = doc.FirstChildElement(); TiXmlElement *node = doc.FirstChildElement();
for (; node && node->ValueStr() == "rule"; node = node->NextSiblingElement()) { for (; node && node->ValueStr() == "rule"; node = node->NextSiblingElement())
{
Settings::Rule rule; Settings::Rule rule;
TiXmlElement *pattern = node->FirstChildElement("pattern"); TiXmlElement *pattern = node->FirstChildElement("pattern");
@ -641,8 +646,9 @@ void CmdLineParser::PrintHelp()
" several paths. First given path is checked first. If\n" " several paths. First given path is checked first. If\n"
" paths are relative to source files, this is not needed\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" " -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" " several paths. Give directory name or filename with path\n"
" given dir the path is ignored and not checked.\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" " --inline-suppr Enable inline suppressions. Use them by placing one or\n"
" more comments, like: // cppcheck-suppress warningId\n" " more comments, like: // cppcheck-suppress warningId\n"
" on the lines before the warning to suppress.\n" " on the lines before the warning to suppress.\n"

View File

@ -31,19 +31,37 @@ bool PathMatch::Match(const std::string &path)
std::vector<std::string>::const_iterator iterMask; std::vector<std::string>::const_iterator iterMask;
for (iterMask = _masks.begin(); iterMask != _masks.end(); ++iterMask) for (iterMask = _masks.begin(); iterMask != _masks.end(); ++iterMask)
{ {
std::string findpath(path); // Filtering directory name
if (findpath[findpath.length() - 1] != '/') if ((*iterMask)[(*iterMask).length() - 1] == '/')
findpath = RemoveFilename(findpath); {
std::string findpath(path);
if (findpath[findpath.length() - 1] != '/')
findpath = RemoveFilename(findpath);
// Match relative paths starting with mask if ((*iterMask).length() > findpath.length())
// -isrc matches src/foo.cpp continue;
if (findpath.compare(0, (*iterMask).size(), *iterMask) == 0) // Match relative paths starting with mask
return true; // -isrc matches src/foo.cpp
// Match only full directory name in middle or end of the path if (findpath.compare(0, (*iterMask).size(), *iterMask) == 0)
// -isrc matches myproject/src/ but does not match return true;
// myproject/srcfiles/ or myproject/mysrc/ // Match only full directory name in middle or end of the path
if (findpath.find("/" + *iterMask) != std::string::npos) // -isrc matches myproject/src/ but does not match
return true; // 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; return false;
} }

View File

@ -95,6 +95,8 @@ private:
TEST_CASE(ignorepaths2) TEST_CASE(ignorepaths2)
TEST_CASE(ignorepaths3) TEST_CASE(ignorepaths3)
TEST_CASE(ignorepaths4) TEST_CASE(ignorepaths4)
TEST_CASE(ignorefilepaths1)
TEST_CASE(ignorefilepaths2)
TEST_CASE(unknownParam); TEST_CASE(unknownParam);
} }
@ -740,6 +742,28 @@ private:
ASSERT_EQUALS("module/", parser.GetIgnoredPaths()[1]); 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() void unknownParam()
{ {
REDIRECT; REDIRECT;

View File

@ -45,6 +45,13 @@ private:
TEST_CASE(onemasklongerpath1); TEST_CASE(onemasklongerpath1);
TEST_CASE(onemasklongerpath2); TEST_CASE(onemasklongerpath2);
TEST_CASE(onemasklongerpath3); 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() void emptymaskemptyfile()
@ -191,6 +198,61 @@ private:
ASSERT(match.Match("project/src/module/")); ASSERT(match.Match("project/src/module/"));
} }
void filemask1()
{
std::vector<std::string> masks;
masks.push_back("foo.cpp");
PathMatch match(masks);
ASSERT(match.Match("foo.cpp"));
}
void filemask2()
{
std::vector<std::string> masks;
masks.push_back("foo.cpp");
PathMatch match(masks);
ASSERT(match.Match("../foo.cpp"));
}
void filemask3()
{
std::vector<std::string> masks;
masks.push_back("foo.cpp");
PathMatch match(masks);
ASSERT(match.Match("src/foo.cpp"));
}
void filemaskpath1()
{
std::vector<std::string> masks;
masks.push_back("src/foo.cpp");
PathMatch match(masks);
ASSERT(match.Match("src/foo.cpp"));
}
void filemaskpath2()
{
std::vector<std::string> masks;
masks.push_back("src/foo.cpp");
PathMatch match(masks);
ASSERT(match.Match("proj/src/foo.cpp"));
}
void filemaskpath3()
{
std::vector<std::string> masks;
masks.push_back("src/foo.cpp");
PathMatch match(masks);
ASSERT(!match.Match("foo.cpp"));
}
void filemaskpath4()
{
std::vector<std::string> masks;
masks.push_back("src/foo.cpp");
PathMatch match(masks);
ASSERT(!match.Match("bar/foo.cpp"));
}
}; };
REGISTER_TEST(TestPathMatch) REGISTER_TEST(TestPathMatch)