CLI: Added more fields for --template and added a new --template-location. The gcc predefined template now matches latest gcc better.
This commit is contained in:
parent
b44a40801b
commit
f058d9ad08
|
@ -538,23 +538,42 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[])
|
|||
// Output formatter
|
||||
else if (std::strcmp(argv[i], "--template") == 0 ||
|
||||
std::strncmp(argv[i], "--template=", 11) == 0) {
|
||||
// "--template path/"
|
||||
// "--template format"
|
||||
if (argv[i][10] == '=')
|
||||
_settings->outputFormat = argv[i] + 11;
|
||||
_settings->templateFormat = argv[i] + 11;
|
||||
else if ((i+1) < argc && argv[i+1][0] != '-') {
|
||||
++i;
|
||||
_settings->outputFormat = argv[i];
|
||||
_settings->templateFormat = argv[i];
|
||||
} else {
|
||||
PrintMessage("cppcheck: argument to '--template' is missing.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_settings->outputFormat == "gcc")
|
||||
_settings->outputFormat = "{file}:{line}: {severity}: {message}";
|
||||
else if (_settings->outputFormat == "vs")
|
||||
_settings->outputFormat = "{file}({line}): {severity}: {message}";
|
||||
else if (_settings->outputFormat == "edit")
|
||||
_settings->outputFormat = "{file} +{line}: {severity}: {message}";
|
||||
if (_settings->templateFormat == "gcc") {
|
||||
//_settings->templateFormat = "{file}:{line}: {severity}: {message}";
|
||||
_settings->templateFormat = "{file}:{line}:{column}: warning: {message} [{id}]\\n{code}";
|
||||
_settings->templateLocation = "{file}:{line}:{column}: note: {info}\\n{code}";
|
||||
} else if (_settings->templateFormat == "daca2") {
|
||||
_settings->templateFormat = "{file}:{line}:{column}: {inconclusive:inconclusive }{severity}: {message} [{id}]\\n{code}";
|
||||
_settings->templateLocation = "{file}:{line}:{column}: note: {info}\\n{code}";
|
||||
} else if (_settings->templateFormat == "vs")
|
||||
_settings->templateFormat = "{file}({line}): {severity}: {message}";
|
||||
else if (_settings->templateFormat == "edit")
|
||||
_settings->templateFormat = "{file} +{line}: {severity}: {message}";
|
||||
}
|
||||
|
||||
else if (std::strcmp(argv[i], "--template-location") == 0 ||
|
||||
std::strncmp(argv[i], "--template-location=", 20) == 0) {
|
||||
// "--template-location format"
|
||||
if (argv[i][19] == '=')
|
||||
_settings->templateLocation = argv[i] + 20;
|
||||
else if ((i+1) < argc && argv[i+1][0] != '-') {
|
||||
++i;
|
||||
_settings->templateLocation = argv[i];
|
||||
} else {
|
||||
PrintMessage("cppcheck: argument to '--template' is missing.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Checking threads
|
||||
|
@ -1008,11 +1027,40 @@ void CmdLineParser::PrintHelp()
|
|||
" --suppressions-list=<file>\n"
|
||||
" Suppress warnings listed in the file. Each suppression\n"
|
||||
" is in the same format as <spec> above.\n"
|
||||
" --template='<text>' Format the error messages. E.g.\n"
|
||||
" --template='<text>' Format the error messages. Available fields:\n"
|
||||
" {file} file name\n"
|
||||
" {line} line number\n"
|
||||
" {column} column number\n"
|
||||
" {callstack} show a callstack. Example:\n"
|
||||
" [file.c:1] -> [file.c:100]\n"
|
||||
" {inconlusive:text} if warning is inconclusive, text\n"
|
||||
" is written\n"
|
||||
" {severity} severity\n"
|
||||
" {message} warning message\n"
|
||||
" {id} warning id\n"
|
||||
" {code} show the real code\n"
|
||||
" \\t insert tab\n"
|
||||
" \\n insert newline\n"
|
||||
" \\r insert carriage return\n"
|
||||
" Example formats:\n"
|
||||
" '{file}:{line},{severity},{id},{message}' or\n"
|
||||
" '{file}({line}):({severity}) {message}' or\n"
|
||||
" '{callstack} {message}'\n"
|
||||
" Pre-defined templates: gcc, vs, edit.\n"
|
||||
" --template-location='<text>'\n"
|
||||
" Format error message location. If this is not provided\n"
|
||||
" then no extra location info is shown.\n"
|
||||
" Available fields:\n"
|
||||
" {file} file name\n"
|
||||
" {line} line number\n"
|
||||
" {column} column number\n"
|
||||
" {info} location info\n"
|
||||
" {code} show the real code\n"
|
||||
" \\t insert tab\n"
|
||||
" \\n insert newline\n"
|
||||
" \\r insert carriage return\n"
|
||||
" Example format (gcc-like):\n"
|
||||
" '{file}:{line}:{column}: note: {info}\\n{code}'\n"
|
||||
" -v, --verbose Output more detailed error information.\n"
|
||||
" --version Print out version number.\n"
|
||||
" --xml Write results in xml format to error stream (stderr).\n"
|
||||
|
|
|
@ -1040,7 +1040,7 @@ void CppCheckExecutor::reportErr(const ErrorLogger::ErrorMessage &msg)
|
|||
} else if (_settings->xml) {
|
||||
reportErr(msg.toXML());
|
||||
} else {
|
||||
reportErr(msg.toString(_settings->verbose, _settings->outputFormat));
|
||||
reportErr(msg.toString(_settings->verbose, _settings->templateFormat, _settings->templateLocation));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -163,7 +163,7 @@ protected:
|
|||
ErrorPath errorPath;
|
||||
if (!value) {
|
||||
errorPath.emplace_back(errtok,bug);
|
||||
} else if (_settings->verbose || _settings->xml || _settings->outputFormat == "daca2") {
|
||||
} else if (_settings->verbose || _settings->xml || !_settings->templateLocation.empty()) {
|
||||
errorPath = value->errorPath;
|
||||
errorPath.emplace_back(errtok,bug);
|
||||
} else {
|
||||
|
|
|
@ -93,7 +93,7 @@ void CheckBufferOverrun::arrayIndexOutOfBoundsError(const Token *tok, const Arra
|
|||
}
|
||||
|
||||
std::list<ErrorPathItem> errorPath;
|
||||
if (_settings->xml || _settings->outputFormat == "daca2") {
|
||||
if (_settings->xml || !_settings->templateLocation.empty()) {
|
||||
for (std::size_t i = 0; i < index.size(); ++i) {
|
||||
const ErrorPath &e = getErrorPath(tok, &index[i], "");
|
||||
for (ErrorPath::const_iterator it = e.begin(); it != e.end(); ++it) {
|
||||
|
|
|
@ -444,15 +444,15 @@ static std::string readCode(const std::string &file, unsigned int linenr, unsign
|
|||
const std::string::size_type endPos = line.find_last_not_of("\r\n\t ");
|
||||
if (endPos + 1 < line.size())
|
||||
line.erase(endPos + 1);
|
||||
return line + endl + std::string(column,' ') + '^';
|
||||
return line + endl + std::string((column>0 ? column-1 : column), ' ') + '^';
|
||||
}
|
||||
|
||||
std::string ErrorLogger::ErrorMessage::toString(bool verbose, const std::string &outputFormat) const
|
||||
std::string ErrorLogger::ErrorMessage::toString(bool verbose, const std::string &templateFormat, const std::string &templateLocation) const
|
||||
{
|
||||
// Save this ErrorMessage in plain text.
|
||||
|
||||
// No template is given
|
||||
if (outputFormat.empty()) {
|
||||
if (templateFormat.empty()) {
|
||||
std::ostringstream text;
|
||||
if (!_callStack.empty())
|
||||
text << callStackToString(_callStack) << ": ";
|
||||
|
@ -466,76 +466,77 @@ std::string ErrorLogger::ErrorMessage::toString(bool verbose, const std::string
|
|||
return text.str();
|
||||
}
|
||||
|
||||
else if (outputFormat == "daca2") {
|
||||
// This is a clang-like output format for daca2
|
||||
std::ostringstream text;
|
||||
if (_callStack.empty()) {
|
||||
text << "nofile:0:0: ";
|
||||
} else {
|
||||
const ErrorLogger::ErrorMessage::FileLocation &loc = _callStack.back();
|
||||
text << loc.getfile() << ':' << loc.line << ':' << loc.col << ": ";
|
||||
// template is given. Reformat the output according to it
|
||||
std::string result = templateFormat;
|
||||
// Support a few special characters to allow to specific formatting, see http://sourceforge.net/apps/phpbb/cppcheck/viewtopic.php?f=4&t=494&sid=21715d362c0dbafd3791da4d9522f814
|
||||
// Substitution should be done first so messages from cppcheck never get translated.
|
||||
findAndReplace(result, "\\b", "\b");
|
||||
findAndReplace(result, "\\n", "\n");
|
||||
findAndReplace(result, "\\r", "\r");
|
||||
findAndReplace(result, "\\t", "\t");
|
||||
|
||||
findAndReplace(result, "{id}", _id);
|
||||
if (result.find("{inconclusive:") != std::string::npos) {
|
||||
const std::string::size_type pos1 = result.find("{inconclusive:");
|
||||
const std::string::size_type pos2 = result.find("}", pos1+1);
|
||||
const std::string replaceFrom = result.substr(pos1,pos2-pos1+1);
|
||||
const std::string replaceWith = result.substr(pos1+14, pos2-pos1-14);
|
||||
findAndReplace(result, replaceFrom, replaceWith);
|
||||
}
|
||||
findAndReplace(result, "{severity}", Severity::toString(_severity));
|
||||
findAndReplace(result, "{message}", verbose ? _verboseMessage : _shortMessage);
|
||||
findAndReplace(result, "{callstack}", _callStack.empty() ? emptyString : callStackToString(_callStack));
|
||||
if (!_callStack.empty()) {
|
||||
findAndReplace(result, "{file}", _callStack.back().getfile());
|
||||
findAndReplace(result, "{line}", MathLib::toString(_callStack.back().line));
|
||||
findAndReplace(result, "{column}", MathLib::toString(_callStack.back().col));
|
||||
if (result.find("{code}") != std::string::npos) {
|
||||
const std::string::size_type pos = result.find("\r");
|
||||
const char *endl;
|
||||
if (pos == std::string::npos)
|
||||
endl = "\n";
|
||||
else if (pos+1 < result.size() && result[pos+1] == '\n')
|
||||
endl = "\r\n";
|
||||
else
|
||||
endl = "\r";
|
||||
findAndReplace(result, "{code}", readCode(_callStack.back().getfile(), _callStack.back().line, _callStack.back().col, endl));
|
||||
}
|
||||
|
||||
if (_inconclusive)
|
||||
text << "inconclusive ";
|
||||
text << Severity::toString(_severity) << ": ";
|
||||
|
||||
text << (verbose ? _verboseMessage : _shortMessage)
|
||||
<< " [" << _id << ']';
|
||||
|
||||
if (_callStack.size() <= 1U)
|
||||
return text.str();
|
||||
|
||||
for (std::list<FileLocation>::const_iterator loc = _callStack.begin(); loc != _callStack.end(); ++loc)
|
||||
text << std::endl
|
||||
<< loc->getfile()
|
||||
<< ':'
|
||||
<< loc->line
|
||||
<< ':'
|
||||
<< loc->col
|
||||
<< ": note: "
|
||||
<< (loc->getinfo().empty() ? _shortMessage : loc->getinfo());
|
||||
return text.str();
|
||||
} else {
|
||||
findAndReplace(result, "{file}", "nofile");
|
||||
findAndReplace(result, "{line}", "0");
|
||||
findAndReplace(result, "{column}", "0");
|
||||
findAndReplace(result, "{code}", emptyString);
|
||||
}
|
||||
|
||||
// template is given. Reformat the output according to it
|
||||
else {
|
||||
std::string result = outputFormat;
|
||||
// Support a few special characters to allow to specific formatting, see http://sourceforge.net/apps/phpbb/cppcheck/viewtopic.php?f=4&t=494&sid=21715d362c0dbafd3791da4d9522f814
|
||||
// Substitution should be done first so messages from cppcheck never get translated.
|
||||
findAndReplace(result, "\\b", "\b");
|
||||
findAndReplace(result, "\\n", "\n");
|
||||
findAndReplace(result, "\\r", "\r");
|
||||
findAndReplace(result, "\\t", "\t");
|
||||
if (!templateLocation.empty() && _callStack.size() >= 2U) {
|
||||
for (const FileLocation &fileLocation : _callStack) {
|
||||
std::string text = templateLocation;
|
||||
|
||||
findAndReplace(result, "{id}", _id);
|
||||
findAndReplace(result, "{severity}", Severity::toString(_severity));
|
||||
findAndReplace(result, "{message}", verbose ? _verboseMessage : _shortMessage);
|
||||
findAndReplace(result, "{callstack}", _callStack.empty() ? emptyString : callStackToString(_callStack));
|
||||
if (!_callStack.empty()) {
|
||||
findAndReplace(result, "{file}", _callStack.back().getfile());
|
||||
findAndReplace(result, "{line}", MathLib::toString(_callStack.back().line));
|
||||
findAndReplace(result, "{column}", MathLib::toString(_callStack.back().col));
|
||||
if (result.find("{code}") != std::string::npos) {
|
||||
const std::string::size_type pos = result.find("\r");
|
||||
findAndReplace(text, "\\b", "\b");
|
||||
findAndReplace(text, "\\n", "\n");
|
||||
findAndReplace(text, "\\r", "\r");
|
||||
findAndReplace(text, "\\t", "\t");
|
||||
|
||||
findAndReplace(text, "{file}", fileLocation.getfile());
|
||||
findAndReplace(text, "{line}", MathLib::toString(fileLocation.line));
|
||||
findAndReplace(text, "{column}", MathLib::toString(fileLocation.col));
|
||||
findAndReplace(text, "{info}", fileLocation.getinfo().empty() ? _shortMessage : fileLocation.getinfo());
|
||||
if (text.find("{code}") != std::string::npos) {
|
||||
const std::string::size_type pos = text.find("\r");
|
||||
const char *endl;
|
||||
if (pos == std::string::npos)
|
||||
endl = "\n";
|
||||
else if (pos+1 < result.size() && result[pos+1] == '\n')
|
||||
else if (pos+1 < text.size() && text[pos+1] == '\n')
|
||||
endl = "\r\n";
|
||||
else
|
||||
endl = "\r";
|
||||
findAndReplace(result, "{code}", readCode(_callStack.back().getfile(), _callStack.back().line, _callStack.back().col, endl));
|
||||
findAndReplace(text, "{code}", readCode(fileLocation.getfile(), fileLocation.line, fileLocation.col, endl));
|
||||
}
|
||||
} else {
|
||||
findAndReplace(result, "{file}", emptyString);
|
||||
findAndReplace(result, "{line}", emptyString);
|
||||
findAndReplace(result, "{column}", emptyString);
|
||||
findAndReplace(result, "{code}", emptyString);
|
||||
result += '\n' + text;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void ErrorLogger::reportUnmatchedSuppressions(const std::list<Suppressions::Suppression> &unmatched)
|
||||
|
|
|
@ -256,11 +256,13 @@ public:
|
|||
/**
|
||||
* Format the error message into a string.
|
||||
* @param verbose use verbose message
|
||||
* @param outputFormat Empty string to use default output format
|
||||
* @param templateFormat Empty string to use default output format
|
||||
* or template to be used. E.g. "{file}:{line},{severity},{id},{message}"
|
||||
* @param templateLocation Format Empty string to use default output format
|
||||
* or template to be used. E.g. "{file}:{line},{info}"
|
||||
* @return formatted string
|
||||
*/
|
||||
std::string toString(bool verbose, const std::string &outputFormat = emptyString) const;
|
||||
std::string toString(bool verbose, const std::string &templateFormat = emptyString, const std::string &templateLocation = emptyString) const;
|
||||
|
||||
std::string serialize() const;
|
||||
bool deserialize(const std::string &data);
|
||||
|
|
|
@ -158,7 +158,11 @@ public:
|
|||
|
||||
/** @brief The output format in which the errors are printed in text mode,
|
||||
e.g. "{severity} {file}:{line} {message} {id}" */
|
||||
std::string outputFormat;
|
||||
std::string templateFormat;
|
||||
|
||||
/** @brief The output format in which the error locations are printed in
|
||||
* text mode, e.g. "{file}:{line} {info}" */
|
||||
std::string templateLocation;
|
||||
|
||||
/** @brief show timing information (--showtime=file|summary|top5) */
|
||||
SHOWTIME_MODES showtime;
|
||||
|
|
|
@ -802,33 +802,33 @@ private:
|
|||
void templates() {
|
||||
REDIRECT;
|
||||
const char *argv[] = {"cppcheck", "--template", "{file}:{line},{severity},{id},{message}", "file.cpp"};
|
||||
settings.outputFormat.clear();
|
||||
settings.templateFormat.clear();
|
||||
ASSERT(defParser.ParseFromArgs(4, argv));
|
||||
ASSERT_EQUALS("{file}:{line},{severity},{id},{message}", settings.outputFormat);
|
||||
ASSERT_EQUALS("{file}:{line},{severity},{id},{message}", settings.templateFormat);
|
||||
}
|
||||
|
||||
void templatesGcc() {
|
||||
REDIRECT;
|
||||
const char *argv[] = {"cppcheck", "--template", "gcc", "file.cpp"};
|
||||
settings.outputFormat.clear();
|
||||
settings.templateFormat.clear();
|
||||
ASSERT(defParser.ParseFromArgs(4, argv));
|
||||
ASSERT_EQUALS("{file}:{line}: {severity}: {message}", settings.outputFormat);
|
||||
ASSERT_EQUALS("{file}:{line}:{column}: warning: {message} [{id}]\\n{code}", settings.templateFormat);
|
||||
}
|
||||
|
||||
void templatesVs() {
|
||||
REDIRECT;
|
||||
const char *argv[] = {"cppcheck", "--template", "vs", "file.cpp"};
|
||||
settings.outputFormat.clear();
|
||||
settings.templateFormat.clear();
|
||||
ASSERT(defParser.ParseFromArgs(4, argv));
|
||||
ASSERT_EQUALS("{file}({line}): {severity}: {message}", settings.outputFormat);
|
||||
ASSERT_EQUALS("{file}({line}): {severity}: {message}", settings.templateFormat);
|
||||
}
|
||||
|
||||
void templatesEdit() {
|
||||
REDIRECT;
|
||||
const char *argv[] = {"cppcheck", "--template", "edit", "file.cpp"};
|
||||
settings.outputFormat.clear();
|
||||
settings.templateFormat.clear();
|
||||
ASSERT(defParser.ParseFromArgs(4, argv));
|
||||
ASSERT_EQUALS("{file} +{line}: {severity}: {message}", settings.outputFormat);
|
||||
ASSERT_EQUALS("{file} +{line}: {severity}: {message}", settings.templateFormat);
|
||||
}
|
||||
|
||||
void xml() {
|
||||
|
|
Loading…
Reference in New Issue