New command line argument added --template

Fix ticket #462 (Allow using template to customize output format)
http://sourceforge.net/apps/trac/cppcheck/ticket/462
This commit is contained in:
Reijo Tomperi 2009-09-05 22:01:49 +03:00
parent 195cc9aae9
commit 7af4ac4282
7 changed files with 104 additions and 11 deletions

View File

@ -111,6 +111,7 @@ man(1), man(7), http://www.tldp.org/HOWTO/Man-Page/
<arg choice="opt"><option>-j[jobs]</option></arg>
<arg choice="opt"><option>--quiet</option></arg>
<arg choice="opt"><option>--style</option></arg>
<arg choice="opt"><option>--template ['text']</option></arg>
<arg choice="opt"><option>--unused-functions</option></arg>
<arg choice="opt"><option>--verbose</option></arg>
<arg choice="opt"><option>--version</option></arg>
@ -200,6 +201,12 @@ files, this is not needed.</para>
<para>Check coding style.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--template ['text']</option></term>
<listitem>
<para>Format the error messages. E.g. '{file}:{line},{severity},{id},{message}' or '{file}({line}):({severity}) {message}'</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--unused-functions</option></term>
<listitem>

View File

@ -172,7 +172,22 @@ std::string CppCheck::parseFromArgs(int argc, const char* const argv[])
_settings._includePaths.push_back(path);
}
// Include paths
// Output formatter
else if (strcmp(argv[i], "--template") == 0)
{
// "--template path/"
if (strcmp(argv[i], "--template") == 0)
{
++i;
if (i >= argc)
return "cppcheck: argument to '--template' is missing\n";
_settings._outputFormat = argv[i];
}
}
// Include paths
else if (strcmp(argv[i], "-j") == 0 ||
strncmp(argv[i], "-j", 2) == 0)
{
@ -308,6 +323,9 @@ std::string CppCheck::parseFromArgs(int argc, const char* const argv[])
" -j [jobs] Start [jobs] threads to do the checking simultaneously.\n"
" -q, --quiet Only print error messages\n"
" -s, --style Check coding style\n"
" --template '[text]' Format the error messages. E.g.\n"
" '{file}:{line},{severity},{id},{message}' or\n"
" '{file}({line}):({severity}) {message}'\n"
" --unused-functions Check if there are unused functions\n"
" -v, --verbose More detailed error reports\n"
" --version Print out version number\n"

View File

@ -112,6 +112,6 @@ void CppCheckExecutor::reportErr(const ErrorLogger::ErrorMessage &msg)
}
else
{
reportErr(msg.toText());
reportErr(msg.toText(_settings._outputFormat));
}
}

View File

@ -158,15 +158,50 @@ std::string ErrorLogger::ErrorMessage::toXML() const
return xml.str();
}
std::string ErrorLogger::ErrorMessage::toText() const
void ErrorLogger::ErrorMessage::findAndReplace(std::string &source, const std::string &searchFor, const std::string &replaceWith)
{
std::ostringstream text;
if (!_callStack.empty())
text << callStackToString(_callStack) << ": ";
if (!_severity.empty())
text << "(" << _severity << ") ";
text << _msg;
return text.str();
std::string::size_type index = 0;
while ((index = source.find(searchFor, index)) != std::string::npos)
{
source.replace(index, searchFor.length(), replaceWith);
index += replaceWith.length() - searchFor.length() + 1;
}
}
std::string ErrorLogger::ErrorMessage::toText(const std::string &outputFormat) const
{
if (outputFormat.length() == 0)
{
std::ostringstream text;
if (!_callStack.empty())
text << callStackToString(_callStack) << ": ";
if (!_severity.empty())
text << "(" << _severity << ") ";
text << _msg;
return text.str();
}
else
{
std::string result = outputFormat;
findAndReplace(result, "{id}", _id);
findAndReplace(result, "{severity}", _severity);
findAndReplace(result, "{message}", _msg);
if (!_callStack.empty())
{
std::ostringstream oss;
oss << _callStack.back().line;
findAndReplace(result, "{line}", oss.str());
findAndReplace(result, "{file}", _callStack.back().getfile());
}
else
{
findAndReplace(result, "{file}", "");
findAndReplace(result, "{line}", "");
}
return result;
}
}
void ErrorLogger::_writemsg(const Tokenizer *tokenizer, const Token *tok, const char severity[], const std::string &msg, const std::string &id)

View File

@ -66,7 +66,21 @@ public:
static std::string getXMLHeader();
static std::string getXMLFooter();
std::string toText() const;
/**
* Format the error message into a string.
* @param outputFormat Empty string to use default output format
* or template to be used. E.g. "{file}:{line},{severity},{id},{message}"
*/
std::string toText(const std::string &outputFormat = "") const;
/**
* Replace all occurances of searchFor with replaceWith in the
* given source.
* @param source The string to modify
* @param searchFor What should be searched for
* @param replaceWith What will replace the found item
*/
static void findAndReplace(std::string &source, const std::string &searchFor, const std::string &replaceWith);
std::string serialize() const;
bool deserialize(const std::string &data);
std::list<FileLocation> _callStack;

View File

@ -65,6 +65,10 @@ public:
Default value is 0. */
int _exitCode;
/** The output format in which the errors are printed in text mode,
e.g. "{severity} {file}:{line} {message} {id}" */
std::string _outputFormat;
#ifdef __GNUC__
/** show timing information */
bool _showtime;

View File

@ -53,6 +53,7 @@ private:
TEST_CASE(xml);
TEST_CASE(include);
TEST_CASE(templateFormat);
}
void linenumbers()
@ -104,6 +105,20 @@ private:
ASSERT_EQUALS("[ab/ef.h:0]: ", errmsg.toText());
}
void templateFormat()
{
ErrorLogger::ErrorMessage errmsg;
ErrorLogger::ErrorMessage::FileLocation loc;
loc.file = "some/{file}file.cpp";
loc.line = 10;
errmsg._callStack.push_back(loc);
errmsg._id = "testId";
errmsg._severity = "testSeverity";
errmsg._msg = "long testMessage";
ASSERT_EQUALS("<error file=\"some/{file}file.cpp\" line=\"10\" id=\"testId\" severity=\"testSeverity\" msg=\"long testMessage\"/>", errmsg.toXML());
ASSERT_EQUALS("[some/{file}file.cpp:10]: (testSeverity) long testMessage", errmsg.toText());
ASSERT_EQUALS("testId-some/{file}file.cpp,testSeverity.10?{long testMessage}", errmsg.toText("{id}-{file},{severity}.{line}?{{message}}"));
}
};
REGISTER_TEST(TestCppcheck)