Fix #674 (Feature request: error filtering)

--suppressions argument added to CLI
http://sourceforge.net/apps/trac/cppcheck/ticket/674
This commit is contained in:
Reijo Tomperi 2009-10-08 17:56:30 +03:00
parent a078c9353d
commit 38c2a360ee
4 changed files with 120 additions and 2 deletions

View File

@ -112,6 +112,7 @@ man(1), man(7), http://www.tldp.org/HOWTO/Man-Page/
<arg choice="opt"><option>-j[jobs]</option></arg> <arg choice="opt"><option>-j[jobs]</option></arg>
<arg choice="opt"><option>--quiet</option></arg> <arg choice="opt"><option>--quiet</option></arg>
<arg choice="opt"><option>--style</option></arg> <arg choice="opt"><option>--style</option></arg>
<arg choice="opt"><option>--suppressions [file]</option></arg>
<arg choice="opt"><option>--template ['text']</option></arg> <arg choice="opt"><option>--template ['text']</option></arg>
<arg choice="opt"><option>--unused-functions</option></arg> <arg choice="opt"><option>--unused-functions</option></arg>
<arg choice="opt"><option>--verbose</option></arg> <arg choice="opt"><option>--verbose</option></arg>
@ -208,6 +209,12 @@ files, this is not needed.</para>
<para>Check coding style.</para> <para>Check coding style.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>--suppressions [file]</option></term>
<listitem>
<para>Suppress warnings listed in the file. Filename and line as optional. The format of the single line in file is: [error id]:[filename]:[line]</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><option>--template ['text']</option></term> <term><option>--template ['text']</option></term>
<listitem> <listitem>

View File

@ -98,6 +98,20 @@ std::string CppCheck::parseFromArgs(int argc, const char* const argv[])
else if (strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--style") == 0) else if (strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--style") == 0)
_settings._checkCodingStyle = true; _settings._checkCodingStyle = true;
// Filter errors
else if (strcmp(argv[i], "--suppressions") == 0)
{
++i;
if (i >= argc)
return "No file specified for the --suppressions option\n";
std::ifstream f(argv[i]);
if (!f.is_open())
return "couldn't open the file \"" + std::string(argv[i]) + "\"\n";
_settings.suppressions(f);
}
// Verbose error messages (configuration info) // Verbose error messages (configuration info)
else if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0) else if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0)
_settings._verbose = true; _settings._verbose = true;
@ -301,8 +315,8 @@ std::string CppCheck::parseFromArgs(int argc, const char* const argv[])
"Syntax:\n" "Syntax:\n"
" cppcheck [--all] [--append=file] [--auto-dealloc file.lst]\n" " cppcheck [--all] [--append=file] [--auto-dealloc file.lst]\n"
" [--error-exitcode=[n]] [--force] [--help] [-Idir] [-j [jobs]]\n" " [--error-exitcode=[n]] [--force] [--help] [-Idir] [-j [jobs]]\n"
" [--quiet] [--style] [--unused-functions] [--verbose] [--version]\n" " [--quiet] [--style] [--suppressions file.txt] [--unused-functions]\n"
" [--xml] [file or path1] [file or path] ...\n" " [--verbose] [--version] [--xml] [file or path1] [file or path] ...\n"
"\n" "\n"
"If path is given instead of filename, *.cpp, *.cxx, *.cc, *.c++ and *.c files\n" "If path is given instead of filename, *.cpp, *.cxx, *.cc, *.c++ and *.c files\n"
"are checked recursively from given directory.\n\n" "are checked recursively from given directory.\n\n"
@ -331,6 +345,9 @@ std::string CppCheck::parseFromArgs(int argc, const char* const argv[])
" -j [jobs] Start [jobs] threads to do the checking simultaneously.\n" " -j [jobs] Start [jobs] threads to do the checking simultaneously.\n"
" -q, --quiet Only print error messages\n" " -q, --quiet Only print error messages\n"
" -s, --style Check coding style\n" " -s, --style Check coding style\n"
" --suppressions file Suppress warnings listed in the file. Filename and line\n"
" are optional. The format of the single line in file is:\n"
" [error id]:[filename]:[line]\n"
" --template '[text]' Format the error messages. E.g.\n" " --template '[text]' Format the error messages. E.g.\n"
" '{file}:{line},{severity},{id},{message}' or\n" " '{file}:{line},{severity},{id},{message}' or\n"
" '{file}({line}):({severity}) {message}'\n" " '{file}({line}):({severity}) {message}'\n"
@ -528,6 +545,17 @@ void CppCheck::reportErr(const ErrorLogger::ErrorMessage &msg)
if (std::find(_errorList.begin(), _errorList.end(), errmsg) != _errorList.end()) if (std::find(_errorList.begin(), _errorList.end(), errmsg) != _errorList.end())
return; return;
std::string file;
unsigned int line(0);
if (!msg._callStack.empty())
{
file = msg._callStack.back().getfile();
line = msg._callStack.back().line;
}
if (_settings.isSuppressed(msg._id, file, line))
return;
_errorList.push_back(errmsg); _errorList.push_back(errmsg);
std::string errmsg2(errmsg); std::string errmsg2(errmsg);
if (_settings._verbose) if (_settings._verbose)

View File

@ -20,6 +20,7 @@
#include <algorithm> #include <algorithm>
#include <fstream> #include <fstream>
#include <sstream>
Settings::Settings() Settings::Settings()
{ {
@ -59,6 +60,62 @@ void Settings::autoDealloc(std::istream &istr)
} }
} }
bool Settings::suppressions(std::istream &istr)
{
std::string line;
while (getline(istr, line))
{
// Skip empty lines
if (line.empty())
continue;
std::istringstream lineStream(line);
std::string id;
std::string file;
unsigned int lineNumber = 0;
if (std::getline(lineStream, id, ':'))
{
if (std::getline(lineStream, file, ':'))
{
lineStream >> lineNumber;
}
}
// We could perhaps check if the id is valid and return error if it is not
addSuppression(id, file, lineNumber);
}
return true;
}
void Settings::addSuppression(const std::string &errorId, const std::string &file, unsigned int line)
{
_suppressions[errorId][file].push_back(line);
_suppressions[errorId][file].sort();
}
bool Settings::isSuppressed(const std::string &errorId, const std::string &file, unsigned int line)
{
if (_suppressions.find(errorId) == _suppressions.end())
return false;
// Check are all errors of this type filtered out
if (_suppressions[errorId].find("") != _suppressions[errorId].end())
return true;
if (_suppressions[errorId].find(file) == _suppressions[errorId].end())
return false;
// Check should all errors in this file be filtered out
if (std::find(_suppressions[errorId][file].begin(), _suppressions[errorId][file].end(), 0) != _suppressions[errorId][file].end())
return true;
if (std::find(_suppressions[errorId][file].begin(), _suppressions[errorId][file].end(), line) == _suppressions[errorId][file].end())
return false;
return true;
}
void Settings::addAutoAllocClass(const std::string &name) void Settings::addAutoAllocClass(const std::string &name)
{ {
_autoDealloc.push_back(name); _autoDealloc.push_back(name);

View File

@ -22,6 +22,7 @@
#include <list> #include <list>
#include <string> #include <string>
#include <istream> #include <istream>
#include <map>
/// @addtogroup Core /// @addtogroup Core
/// @{ /// @{
@ -41,6 +42,9 @@ private:
/** Code to append in the checks */ /** Code to append in the checks */
std::string _append; std::string _append;
/** List of error which the user doesn't want to see. */
std::map<std::string, std::map<std::string, std::list<int> > > _suppressions;
public: public:
Settings(); Settings();
virtual ~Settings(); virtual ~Settings();
@ -87,6 +91,28 @@ public:
/** Add class to list of automatically deallocated classes */ /** Add class to list of automatically deallocated classes */
void addAutoAllocClass(const std::string &name); void addAutoAllocClass(const std::string &name);
/**
* Don't show errors listed in the file.
* @param istr Open file stream where errors can be read.
* @return true on success, false in syntax error is noticed.
*/
bool suppressions(std::istream &istr);
/**
* Don't show this error. If file and/or line are optional. In which case
* the errorId alone is used for filtering.
* @param errorId, the id for the error, e.g. "arrayIndexOutOfBounds"
* @param file File name with the path, e.g. "src/main.cpp"
* @param line number, e.g. "123"
*/
void addSuppression(const std::string &errorId, const std::string &file = "", unsigned int line = 0);
/**
* Returns true if this message should not be shown to the user.
* @return true if this error is suppressed.
*/
bool isSuppressed(const std::string &errorId, const std::string &file, unsigned int line);
/** is a class automaticly deallocated? */ /** is a class automaticly deallocated? */
bool isAutoDealloc(const char classname[]) const; bool isAutoDealloc(const char classname[]) const;