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 "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"

View File

@ -31,19 +31,37 @@ bool PathMatch::Match(const std::string &path)
std::vector<std::string>::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;
}

View File

@ -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;

View File

@ -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<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)