optimized template string substitutions a bit (#4840)
This commit is contained in:
parent
1f2b49142e
commit
cfca3a69a2
4
Makefile
4
Makefile
|
@ -281,6 +281,7 @@ TESTOBJ = test/fixture.o \
|
||||||
test/testclangimport.o \
|
test/testclangimport.o \
|
||||||
test/testclass.o \
|
test/testclass.o \
|
||||||
test/testcmdlineparser.o \
|
test/testcmdlineparser.o \
|
||||||
|
test/testcolor.o \
|
||||||
test/testcondition.o \
|
test/testcondition.o \
|
||||||
test/testconstructors.o \
|
test/testconstructors.o \
|
||||||
test/testcppcheck.o \
|
test/testcppcheck.o \
|
||||||
|
@ -714,6 +715,9 @@ test/testclass.o: test/testclass.cpp externals/simplecpp/simplecpp.h lib/check.h
|
||||||
test/testcmdlineparser.o: test/testcmdlineparser.cpp cli/cmdlineparser.h cli/cppcheckexecutor.h lib/check.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h test/fixture.h test/redirect.h
|
test/testcmdlineparser.o: test/testcmdlineparser.cpp cli/cmdlineparser.h cli/cppcheckexecutor.h lib/check.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h test/fixture.h test/redirect.h
|
||||||
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testcmdlineparser.cpp
|
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testcmdlineparser.cpp
|
||||||
|
|
||||||
|
test/testcolor.o: test/testcolor.cpp lib/check.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/suppressions.h test/fixture.h
|
||||||
|
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testcolor.cpp
|
||||||
|
|
||||||
test/testcondition.o: test/testcondition.cpp externals/simplecpp/simplecpp.h lib/check.h lib/checkcondition.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/preprocessor.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h
|
test/testcondition.o: test/testcondition.cpp externals/simplecpp/simplecpp.h lib/check.h lib/checkcondition.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/preprocessor.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h
|
||||||
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testcondition.cpp
|
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testcondition.cpp
|
||||||
|
|
||||||
|
|
|
@ -888,6 +888,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: deprecate "--template <template>"
|
||||||
// Output formatter
|
// Output formatter
|
||||||
else if (std::strcmp(argv[i], "--template") == 0 ||
|
else if (std::strcmp(argv[i], "--template") == 0 ||
|
||||||
std::strncmp(argv[i], "--template=", 11) == 0) {
|
std::strncmp(argv[i], "--template=", 11) == 0) {
|
||||||
|
@ -901,6 +902,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
|
||||||
printError("argument to '--template' is missing.");
|
printError("argument to '--template' is missing.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// TODO: bail out when no placeholders are found?
|
||||||
|
|
||||||
if (mSettings.templateFormat == "gcc") {
|
if (mSettings.templateFormat == "gcc") {
|
||||||
mSettings.templateFormat = "{bold}{file}:{line}:{column}: {magenta}warning:{default} {message} [{id}]{reset}\\n{code}";
|
mSettings.templateFormat = "{bold}{file}:{line}:{column}: {magenta}warning:{default} {message} [{id}]{reset}\\n{code}";
|
||||||
|
@ -922,6 +924,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: deprecate "--template-location <template>"
|
||||||
else if (std::strcmp(argv[i], "--template-location") == 0 ||
|
else if (std::strcmp(argv[i], "--template-location") == 0 ||
|
||||||
std::strncmp(argv[i], "--template-location=", 20) == 0) {
|
std::strncmp(argv[i], "--template-location=", 20) == 0) {
|
||||||
// "--template-location format"
|
// "--template-location format"
|
||||||
|
@ -931,9 +934,10 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
|
||||||
++i;
|
++i;
|
||||||
mSettings.templateLocation = argv[i];
|
mSettings.templateLocation = argv[i];
|
||||||
} else {
|
} else {
|
||||||
printError("argument to '--template' is missing.");
|
printError("argument to '--template-location' is missing.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// TODO: bail out when no placeholders are found?
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (std::strncmp(argv[i], "--template-max-time=", 20) == 0) {
|
else if (std::strncmp(argv[i], "--template-max-time=", 20) == 0) {
|
||||||
|
@ -1015,6 +1019,9 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
|
||||||
if (mSettings.templateLocation.empty())
|
if (mSettings.templateLocation.empty())
|
||||||
mSettings.templateLocation = "{bold}{file}:{line}:{column}: {dim}note:{reset} {info}\\n{code}";
|
mSettings.templateLocation = "{bold}{file}:{line}:{column}: {dim}note:{reset} {info}\\n{code}";
|
||||||
}
|
}
|
||||||
|
// replace static parts of the templates
|
||||||
|
substituteTemplateFormatStatic(mSettings.templateFormat);
|
||||||
|
substituteTemplateLocationStatic(mSettings.templateLocation);
|
||||||
|
|
||||||
mSettings.project.ignorePaths(mIgnoredPaths);
|
mSettings.project.ignorePaths(mIgnoredPaths);
|
||||||
|
|
||||||
|
|
|
@ -383,7 +383,7 @@ void CppCheckExecutor::reportOut(const std::string &outmsg, Color c)
|
||||||
if (c == Color::Reset)
|
if (c == Color::Reset)
|
||||||
std::cout << ansiToOEM(outmsg, true) << std::endl;
|
std::cout << ansiToOEM(outmsg, true) << std::endl;
|
||||||
else
|
else
|
||||||
std::cout << toString(c) << ansiToOEM(outmsg, true) << toString(Color::Reset) << std::endl;
|
std::cout << c << ansiToOEM(outmsg, true) << Color::Reset << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CppCheckExecutor::reportProgress(const std::string &filename, const char stage[], const std::size_t value)
|
void CppCheckExecutor::reportProgress(const std::string &filename, const char stage[], const std::size_t value)
|
||||||
|
|
|
@ -20,30 +20,46 @@
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <sstream> // IWYU pragma: keep
|
#include <sstream> // IWYU pragma: keep
|
||||||
|
#include <iostream>
|
||||||
|
#endif
|
||||||
|
|
||||||
bool gDisableColors = false;
|
bool gDisableColors = false;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifndef _WIN32
|
||||||
std::ostream& operator<<(std::ostream& os, const Color& /*c*/)
|
static bool isStreamATty(const std::ostream & os)
|
||||||
{
|
{
|
||||||
#else
|
static const bool stdout_tty = isatty(STDOUT_FILENO);
|
||||||
|
static const bool stderr_tty = isatty(STDERR_FILENO);
|
||||||
|
if (&os == &std::cout)
|
||||||
|
return stdout_tty;
|
||||||
|
if (&os == &std::cerr)
|
||||||
|
return stderr_tty;
|
||||||
|
return (stdout_tty && stderr_tty);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream & os, const Color& c)
|
std::ostream& operator<<(std::ostream & os, const Color& c)
|
||||||
{
|
{
|
||||||
// TODO: handle piping into file as well as other pipes like stderr
|
#ifndef _WIN32
|
||||||
static const bool s_is_tty = isatty(STDOUT_FILENO);
|
if (!gDisableColors && isStreamATty(os))
|
||||||
if (!gDisableColors && s_is_tty)
|
|
||||||
return os << "\033[" << static_cast<std::size_t>(c) << "m";
|
return os << "\033[" << static_cast<std::size_t>(c) << "m";
|
||||||
|
#else
|
||||||
|
(void)c;
|
||||||
#endif
|
#endif
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string toString(const Color& c)
|
std::string toString(const Color& c)
|
||||||
{
|
{
|
||||||
|
#ifndef _WIN32
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << c;
|
ss << c;
|
||||||
return ss.str();
|
return ss.str();
|
||||||
|
#else
|
||||||
|
(void)c;
|
||||||
|
return "";
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -511,24 +511,64 @@ static std::string readCode(const std::string &file, int linenr, int column, con
|
||||||
return line + endl + std::string((column>0 ? column-1 : 0), ' ') + '^';
|
return line + endl + std::string((column>0 ? column-1 : 0), ' ') + '^';
|
||||||
}
|
}
|
||||||
|
|
||||||
static void replaceColors(std::string& source)
|
static void replaceSpecialChars(std::string& source)
|
||||||
{
|
{
|
||||||
static const std::string reset_str = ::toString(Color::Reset);
|
// 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
|
||||||
findAndReplace(source, "{reset}", reset_str);
|
// Substitution should be done first so messages from cppcheck never get translated.
|
||||||
static const std::string bold_str = ::toString(Color::Bold);
|
static const std::unordered_map<char, std::string> substitutionMap = {
|
||||||
findAndReplace(source, "{bold}", bold_str);
|
{'b', "\b"},
|
||||||
static const std::string dim_str = ::toString(Color::Dim);
|
{'n', "\n"},
|
||||||
findAndReplace(source, "{dim}", dim_str);
|
{'r', "\r"},
|
||||||
static const std::string red_str = ::toString(Color::FgRed);
|
{'t', "\t"}
|
||||||
findAndReplace(source, "{red}", red_str);
|
};
|
||||||
static const std::string green_str = ::toString(Color::FgGreen);
|
|
||||||
findAndReplace(source, "{green}", green_str);
|
std::string::size_type index = 0;
|
||||||
static const std::string blue_str = ::toString(Color::FgBlue);
|
while ((index = source.find('\\', index)) != std::string::npos) {
|
||||||
findAndReplace(source, "{blue}", blue_str);
|
const char searchFor = source[index+1];
|
||||||
static const std::string magenta_str = ::toString(Color::FgMagenta);
|
const auto it = substitutionMap.find(searchFor);
|
||||||
findAndReplace(source, "{magenta}", magenta_str);
|
if (it == substitutionMap.end()) {
|
||||||
static const std::string default_str = ::toString(Color::FgDefault);
|
index += 1;
|
||||||
findAndReplace(source, "{default}", default_str);
|
continue;
|
||||||
|
}
|
||||||
|
const std::string& replaceWith = it->second;
|
||||||
|
source.replace(index, 2, replaceWith);
|
||||||
|
index += replaceWith.length();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void replace(std::string& source, const std::unordered_map<std::string, std::string> &substitutionMap)
|
||||||
|
{
|
||||||
|
std::string::size_type index = 0;
|
||||||
|
while ((index = source.find('{', index)) != std::string::npos) {
|
||||||
|
const std::string::size_type end = source.find('}', index);
|
||||||
|
if (end == std::string::npos)
|
||||||
|
break;
|
||||||
|
const std::string searchFor = source.substr(index, end-index+1);
|
||||||
|
const auto it = substitutionMap.find(searchFor);
|
||||||
|
if (it == substitutionMap.end()) {
|
||||||
|
index += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const std::string& replaceWith = it->second;
|
||||||
|
source.replace(index, searchFor.length(), replaceWith);
|
||||||
|
index += replaceWith.length();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void replaceColors(std::string& source) {
|
||||||
|
// TODO: colors are not applied when either stdout or stderr is not a TTY because we resolve them before the stream usage
|
||||||
|
static const std::unordered_map<std::string, std::string> substitutionMap =
|
||||||
|
{
|
||||||
|
{"{reset}", ::toString(Color::Reset)},
|
||||||
|
{"{bold}", ::toString(Color::Bold)},
|
||||||
|
{"{dim}", ::toString(Color::Dim)},
|
||||||
|
{"{red}", ::toString(Color::FgRed)},
|
||||||
|
{"{green}", ::toString(Color::FgGreen)},
|
||||||
|
{"{blue}", ::toString(Color::FgBlue)},
|
||||||
|
{"{magenta}", ::toString(Color::FgMagenta)},
|
||||||
|
{"{default}", ::toString(Color::FgDefault)},
|
||||||
|
};
|
||||||
|
replace(source, substitutionMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ErrorMessage::toString(bool verbose, const std::string &templateFormat, const std::string &templateLocation) const
|
std::string ErrorMessage::toString(bool verbose, const std::string &templateFormat, const std::string &templateLocation) const
|
||||||
|
@ -555,14 +595,7 @@ std::string ErrorMessage::toString(bool verbose, const std::string &templateForm
|
||||||
|
|
||||||
// template is given. Reformat the output according to it
|
// template is given. Reformat the output according to it
|
||||||
std::string result = templateFormat;
|
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");
|
|
||||||
|
|
||||||
replaceColors(result);
|
|
||||||
findAndReplace(result, "{id}", id);
|
findAndReplace(result, "{id}", id);
|
||||||
|
|
||||||
std::string::size_type pos1 = result.find("{inconclusive:");
|
std::string::size_type pos1 = result.find("{inconclusive:");
|
||||||
|
@ -594,23 +627,21 @@ std::string ErrorMessage::toString(bool verbose, const std::string &templateForm
|
||||||
findAndReplace(result, "{code}", readCode(callStack.back().getOrigFile(), callStack.back().line, callStack.back().column, endl));
|
findAndReplace(result, "{code}", readCode(callStack.back().getOrigFile(), callStack.back().line, callStack.back().column, endl));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
findAndReplace(result, "{callstack}", emptyString);
|
static const std::unordered_map<std::string, std::string> callStackSubstitutionMap =
|
||||||
findAndReplace(result, "{file}", "nofile");
|
{
|
||||||
findAndReplace(result, "{line}", "0");
|
{"{callstack}", ""},
|
||||||
findAndReplace(result, "{column}", "0");
|
{"{file}", "nofile"},
|
||||||
findAndReplace(result, "{code}", emptyString);
|
{"{line}", "0"},
|
||||||
|
{"{column}", "0"},
|
||||||
|
{"{code}", ""}
|
||||||
|
};
|
||||||
|
replace(result, callStackSubstitutionMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!templateLocation.empty() && callStack.size() >= 2U) {
|
if (!templateLocation.empty() && callStack.size() >= 2U) {
|
||||||
for (const FileLocation &fileLocation : callStack) {
|
for (const FileLocation &fileLocation : callStack) {
|
||||||
std::string text = templateLocation;
|
std::string text = templateLocation;
|
||||||
|
|
||||||
findAndReplace(text, "\\b", "\b");
|
|
||||||
findAndReplace(text, "\\n", "\n");
|
|
||||||
findAndReplace(text, "\\r", "\r");
|
|
||||||
findAndReplace(text, "\\t", "\t");
|
|
||||||
|
|
||||||
replaceColors(text);
|
|
||||||
findAndReplace(text, "{file}", fileLocation.getfile());
|
findAndReplace(text, "{file}", fileLocation.getfile());
|
||||||
findAndReplace(text, "{line}", MathLib::toString(fileLocation.line));
|
findAndReplace(text, "{line}", MathLib::toString(fileLocation.line));
|
||||||
findAndReplace(text, "{column}", MathLib::toString(fileLocation.column));
|
findAndReplace(text, "{column}", MathLib::toString(fileLocation.column));
|
||||||
|
@ -877,3 +908,15 @@ std::string replaceStr(std::string s, const std::string &from, const std::string
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void substituteTemplateFormatStatic(std::string& templateFormat)
|
||||||
|
{
|
||||||
|
replaceSpecialChars(templateFormat);
|
||||||
|
replaceColors(templateFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
void substituteTemplateLocationStatic(std::string& templateLocation)
|
||||||
|
{
|
||||||
|
replaceSpecialChars(templateLocation);
|
||||||
|
replaceColors(templateLocation);
|
||||||
|
}
|
||||||
|
|
|
@ -278,6 +278,12 @@ public:
|
||||||
/** Replace substring. Example replaceStr("1,NR,3", "NR", "2") => "1,2,3" */
|
/** Replace substring. Example replaceStr("1,NR,3", "NR", "2") => "1,2,3" */
|
||||||
std::string replaceStr(std::string s, const std::string &from, const std::string &to);
|
std::string replaceStr(std::string s, const std::string &from, const std::string &to);
|
||||||
|
|
||||||
|
/** replaces the static parts of the location template **/
|
||||||
|
CPPCHECKLIB void substituteTemplateFormatStatic(std::string& templateFormat);
|
||||||
|
|
||||||
|
/** replaces the static parts of the location template **/
|
||||||
|
CPPCHECKLIB void substituteTemplateLocationStatic(std::string& templateLocation);
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
#endif // errorloggerH
|
#endif // errorloggerH
|
||||||
|
|
|
@ -678,9 +678,10 @@ Library::Error Library::loadFunction(const tinyxml2::XMLElement * const node, co
|
||||||
for (const tinyxml2::XMLElement *functionnode = node->FirstChildElement(); functionnode; functionnode = functionnode->NextSiblingElement()) {
|
for (const tinyxml2::XMLElement *functionnode = node->FirstChildElement(); functionnode; functionnode = functionnode->NextSiblingElement()) {
|
||||||
const std::string functionnodename = functionnode->Name();
|
const std::string functionnodename = functionnode->Name();
|
||||||
if (functionnodename == "noreturn") {
|
if (functionnodename == "noreturn") {
|
||||||
if (strcmp(functionnode->GetText(), "false") == 0)
|
const char * const text = functionnode->GetText();
|
||||||
|
if (strcmp(text, "false") == 0)
|
||||||
mNoReturn[name] = FalseTrueMaybe::False;
|
mNoReturn[name] = FalseTrueMaybe::False;
|
||||||
else if (strcmp(functionnode->GetText(), "maybe") == 0)
|
else if (strcmp(text, "maybe") == 0)
|
||||||
mNoReturn[name] = FalseTrueMaybe::Maybe;
|
mNoReturn[name] = FalseTrueMaybe::Maybe;
|
||||||
else
|
else
|
||||||
mNoReturn[name] = FalseTrueMaybe::True; // Safe
|
mNoReturn[name] = FalseTrueMaybe::True; // Safe
|
||||||
|
@ -757,9 +758,9 @@ Library::Error Library::loadFunction(const tinyxml2::XMLElement * const node, co
|
||||||
// Validate the validation expression
|
// Validate the validation expression
|
||||||
const char *p = argnode->GetText();
|
const char *p = argnode->GetText();
|
||||||
if (!isCompliantValidationExpression(p))
|
if (!isCompliantValidationExpression(p))
|
||||||
return Error(ErrorCode::BAD_ATTRIBUTE_VALUE, (!p ? "\"\"" : argnode->GetText()));
|
return Error(ErrorCode::BAD_ATTRIBUTE_VALUE, (!p ? "\"\"" : p));
|
||||||
// Set validation expression
|
// Set validation expression
|
||||||
ac.valid = argnode->GetText();
|
ac.valid = p;
|
||||||
}
|
}
|
||||||
else if (argnodename == "minsize") {
|
else if (argnodename == "minsize") {
|
||||||
const char *typeattr = argnode->Attribute("type");
|
const char *typeattr = argnode->Attribute("type");
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "cmdlineparser.h"
|
#include "cmdlineparser.h"
|
||||||
|
#include "color.h"
|
||||||
#include "cppcheckexecutor.h"
|
#include "cppcheckexecutor.h"
|
||||||
#include "errortypes.h"
|
#include "errortypes.h"
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
|
@ -162,6 +163,16 @@ private:
|
||||||
TEST_CASE(templatesGcc);
|
TEST_CASE(templatesGcc);
|
||||||
TEST_CASE(templatesVs);
|
TEST_CASE(templatesVs);
|
||||||
TEST_CASE(templatesEdit);
|
TEST_CASE(templatesEdit);
|
||||||
|
TEST_CASE(templatesCppcheck1);
|
||||||
|
TEST_CASE(templatesDaca2);
|
||||||
|
TEST_CASE(templatesSelfcheck);
|
||||||
|
TEST_CASE(templatesNoPlaceholder);
|
||||||
|
TEST_CASE(templateFormatInvalid);
|
||||||
|
TEST_CASE(templateFormatInvalid2);
|
||||||
|
TEST_CASE(templateFormatEmpty);
|
||||||
|
TEST_CASE(templateLocationInvalid);
|
||||||
|
TEST_CASE(templateLocationInvalid2);
|
||||||
|
TEST_CASE(templateLocationEmpty);
|
||||||
TEST_CASE(xml);
|
TEST_CASE(xml);
|
||||||
TEST_CASE(xmlver2);
|
TEST_CASE(xmlver2);
|
||||||
TEST_CASE(xmlver2both);
|
TEST_CASE(xmlver2both);
|
||||||
|
@ -1252,10 +1263,12 @@ private:
|
||||||
|
|
||||||
void templates() {
|
void templates() {
|
||||||
REDIRECT;
|
REDIRECT;
|
||||||
const char * const argv[] = {"cppcheck", "--template", "{file}:{line},{severity},{id},{message}", "file.cpp"};
|
const char * const argv[] = {"cppcheck", "--template", "{file}:{line},{severity},{id},{message}", "--template-location={file}:{line}:{column} {info}", "file.cpp"};
|
||||||
settings.templateFormat.clear();
|
settings.templateFormat.clear();
|
||||||
|
settings.templateLocation.clear();
|
||||||
ASSERT(defParser.parseFromArgs(4, argv));
|
ASSERT(defParser.parseFromArgs(4, argv));
|
||||||
ASSERT_EQUALS("{file}:{line},{severity},{id},{message}", settings.templateFormat);
|
ASSERT_EQUALS("{file}:{line},{severity},{id},{message}", settings.templateFormat);
|
||||||
|
ASSERT_EQUALS("{file}:{line}:{column} {info}", settings.templateLocation);
|
||||||
ASSERT_EQUALS("", GET_REDIRECT_OUTPUT);
|
ASSERT_EQUALS("", GET_REDIRECT_OUTPUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1263,8 +1276,10 @@ private:
|
||||||
REDIRECT;
|
REDIRECT;
|
||||||
const char * const argv[] = {"cppcheck", "--template", "gcc", "file.cpp"};
|
const char * const argv[] = {"cppcheck", "--template", "gcc", "file.cpp"};
|
||||||
settings.templateFormat.clear();
|
settings.templateFormat.clear();
|
||||||
|
settings.templateLocation.clear();
|
||||||
ASSERT(defParser.parseFromArgs(4, argv));
|
ASSERT(defParser.parseFromArgs(4, argv));
|
||||||
ASSERT_EQUALS("{bold}{file}:{line}:{column}: {magenta}warning:{default} {message} [{id}]{reset}\\n{code}", settings.templateFormat);
|
ASSERT_EQUALS("{file}:{line}:{column}: warning: {message} [{id}]\n{code}", settings.templateFormat);
|
||||||
|
ASSERT_EQUALS("{file}:{line}:{column}: note: {info}\n{code}", settings.templateLocation);
|
||||||
ASSERT_EQUALS("", GET_REDIRECT_OUTPUT);
|
ASSERT_EQUALS("", GET_REDIRECT_OUTPUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1272,8 +1287,10 @@ private:
|
||||||
REDIRECT;
|
REDIRECT;
|
||||||
const char * const argv[] = {"cppcheck", "--template", "vs", "file.cpp"};
|
const char * const argv[] = {"cppcheck", "--template", "vs", "file.cpp"};
|
||||||
settings.templateFormat.clear();
|
settings.templateFormat.clear();
|
||||||
|
settings.templateLocation.clear();
|
||||||
ASSERT(defParser.parseFromArgs(4, argv));
|
ASSERT(defParser.parseFromArgs(4, argv));
|
||||||
ASSERT_EQUALS("{file}({line}): {severity}: {message}", settings.templateFormat);
|
ASSERT_EQUALS("{file}({line}): {severity}: {message}", settings.templateFormat);
|
||||||
|
ASSERT_EQUALS("", settings.templateLocation);
|
||||||
ASSERT_EQUALS("", GET_REDIRECT_OUTPUT);
|
ASSERT_EQUALS("", GET_REDIRECT_OUTPUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1281,8 +1298,120 @@ private:
|
||||||
REDIRECT;
|
REDIRECT;
|
||||||
const char * const argv[] = {"cppcheck", "--template", "edit", "file.cpp"};
|
const char * const argv[] = {"cppcheck", "--template", "edit", "file.cpp"};
|
||||||
settings.templateFormat.clear();
|
settings.templateFormat.clear();
|
||||||
|
settings.templateLocation.clear();
|
||||||
ASSERT(defParser.parseFromArgs(4, argv));
|
ASSERT(defParser.parseFromArgs(4, argv));
|
||||||
ASSERT_EQUALS("{file} +{line}: {severity}: {message}", settings.templateFormat);
|
ASSERT_EQUALS("{file} +{line}: {severity}: {message}", settings.templateFormat);
|
||||||
|
ASSERT_EQUALS("", settings.templateLocation);
|
||||||
|
ASSERT_EQUALS("", GET_REDIRECT_OUTPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void templatesCppcheck1() {
|
||||||
|
REDIRECT;
|
||||||
|
const char * const argv[] = {"cppcheck", "--template=cppcheck1", "file.cpp"};
|
||||||
|
settings.templateFormat.clear();
|
||||||
|
settings.templateLocation.clear();
|
||||||
|
ASSERT(defParser.parseFromArgs(3, argv));
|
||||||
|
ASSERT_EQUALS("{callstack}: ({severity}{inconclusive:, inconclusive}) {message}", settings.templateFormat);
|
||||||
|
ASSERT_EQUALS("", settings.templateLocation);
|
||||||
|
ASSERT_EQUALS("", GET_REDIRECT_OUTPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void templatesDaca2() {
|
||||||
|
REDIRECT;
|
||||||
|
const char * const argv[] = {"cppcheck", "--template=daca2", "file.cpp"};
|
||||||
|
settings.templateFormat.clear();
|
||||||
|
settings.templateLocation.clear();
|
||||||
|
ASSERT(defParser.parseFromArgs(3, argv));
|
||||||
|
ASSERT_EQUALS("{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]", settings.templateFormat);
|
||||||
|
ASSERT_EQUALS("{file}:{line}:{column}: note: {info}", settings.templateLocation);
|
||||||
|
ASSERT_EQUALS(true, settings.daca);
|
||||||
|
ASSERT_EQUALS("", GET_REDIRECT_OUTPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void templatesSelfcheck() {
|
||||||
|
REDIRECT;
|
||||||
|
const char * const argv[] = {"cppcheck", "--template=selfcheck", "file.cpp"};
|
||||||
|
settings.templateFormat.clear();
|
||||||
|
settings.templateLocation.clear();
|
||||||
|
ASSERT(defParser.parseFromArgs(3, argv));
|
||||||
|
ASSERT_EQUALS("{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\n{code}", settings.templateFormat);
|
||||||
|
ASSERT_EQUALS("{file}:{line}:{column}: note: {info}\n{code}", settings.templateLocation);
|
||||||
|
ASSERT_EQUALS("", GET_REDIRECT_OUTPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: we should bail out on this
|
||||||
|
void templatesNoPlaceholder() {
|
||||||
|
REDIRECT;
|
||||||
|
const char * const argv[] = {"cppcheck", "--template=selfchek", "file.cpp"};
|
||||||
|
settings.templateFormat.clear();
|
||||||
|
settings.templateLocation.clear();
|
||||||
|
TODO_ASSERT(!defParser.parseFromArgs(3, argv));
|
||||||
|
ASSERT_EQUALS("selfchek", settings.templateFormat);
|
||||||
|
ASSERT_EQUALS("", settings.templateLocation);
|
||||||
|
ASSERT_EQUALS("", GET_REDIRECT_OUTPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void templateFormatInvalid() {
|
||||||
|
REDIRECT;
|
||||||
|
const char* const argv[] = { "cppcheck", "--template", "--template-location={file}", "file.cpp" };
|
||||||
|
ASSERT(!defParser.parseFromArgs(4, argv));
|
||||||
|
ASSERT_EQUALS("cppcheck: error: argument to '--template' is missing.\n", GET_REDIRECT_OUTPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: will not error out as he next option does not start with a "-"
|
||||||
|
void templateFormatInvalid2() {
|
||||||
|
REDIRECT;
|
||||||
|
settings.templateFormat.clear();
|
||||||
|
settings.templateLocation.clear();
|
||||||
|
const char* const argv[] = { "cppcheck", "--template", "file.cpp" };
|
||||||
|
TODO_ASSERT(!defParser.parseFromArgs(3, argv));
|
||||||
|
ASSERT_EQUALS("file.cpp", settings.templateFormat);
|
||||||
|
ASSERT_EQUALS("", settings.templateLocation);
|
||||||
|
ASSERT_EQUALS("", GET_REDIRECT_OUTPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// will use the default
|
||||||
|
// TODO: bail out on empty?
|
||||||
|
void templateFormatEmpty() {
|
||||||
|
REDIRECT;
|
||||||
|
settings.templateFormat.clear();
|
||||||
|
settings.templateLocation.clear();
|
||||||
|
const char* const argv[] = { "cppcheck", "--template=", "file.cpp" };
|
||||||
|
ASSERT(defParser.parseFromArgs(3, argv));
|
||||||
|
ASSERT_EQUALS("{file}:{line}:{column}: {inconclusive:}{severity}:{inconclusive: inconclusive:} {message} [{id}]\n{code}", settings.templateFormat);
|
||||||
|
ASSERT_EQUALS("{file}:{line}:{column}: note: {info}\n{code}", settings.templateLocation);
|
||||||
|
ASSERT_EQUALS("", GET_REDIRECT_OUTPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void templateLocationInvalid() {
|
||||||
|
REDIRECT;
|
||||||
|
const char* const argv[] = { "cppcheck", "--template-location", "--template={file}", "file.cpp" };
|
||||||
|
ASSERT(!defParser.parseFromArgs(4, argv));
|
||||||
|
ASSERT_EQUALS("cppcheck: error: argument to '--template-location' is missing.\n", GET_REDIRECT_OUTPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: will not error out as he next option does not start with a "-"
|
||||||
|
void templateLocationInvalid2() {
|
||||||
|
REDIRECT;
|
||||||
|
settings.templateFormat.clear();
|
||||||
|
settings.templateLocation.clear();
|
||||||
|
const char* const argv[] = { "cppcheck", "--template-location", "file.cpp" };
|
||||||
|
TODO_ASSERT(!defParser.parseFromArgs(3, argv));
|
||||||
|
ASSERT_EQUALS("{file}:{line}:{column}: {inconclusive:}{severity}:{inconclusive: inconclusive:} {message} [{id}]\n{code}", settings.templateFormat);
|
||||||
|
ASSERT_EQUALS("file.cpp", settings.templateLocation);
|
||||||
|
ASSERT_EQUALS("", GET_REDIRECT_OUTPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// will use the default
|
||||||
|
// TODO: bail out on empty?
|
||||||
|
void templateLocationEmpty() {
|
||||||
|
REDIRECT;
|
||||||
|
settings.templateFormat.clear();
|
||||||
|
settings.templateLocation.clear();
|
||||||
|
const char* const argv[] = { "cppcheck", "--template-location=", "file.cpp" };
|
||||||
|
ASSERT(defParser.parseFromArgs(3, argv));
|
||||||
|
ASSERT_EQUALS("{file}:{line}:{column}: {inconclusive:}{severity}:{inconclusive: inconclusive:} {message} [{id}]\n{code}", settings.templateFormat);
|
||||||
|
ASSERT_EQUALS("{file}:{line}:{column}: note: {info}\n{code}", settings.templateLocation);
|
||||||
ASSERT_EQUALS("", GET_REDIRECT_OUTPUT);
|
ASSERT_EQUALS("", GET_REDIRECT_OUTPUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* Cppcheck - A tool for static C/C++ code analysis
|
||||||
|
* Copyright (C) 2007-2023 Cppcheck team.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "color.h"
|
||||||
|
#include "fixture.h"
|
||||||
|
|
||||||
|
class TestColor : public TestFixture {
|
||||||
|
public:
|
||||||
|
TestColor() : TestFixture("TestColor") {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void run() override {
|
||||||
|
TEST_CASE(toString);
|
||||||
|
}
|
||||||
|
|
||||||
|
void toString() const {
|
||||||
|
// TODO: color conversion is dependent on stdout/stderr being a TTY
|
||||||
|
ASSERT_EQUALS("", ::toString(Color::FgRed));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
REGISTER_TEST(TestColor)
|
|
@ -16,6 +16,7 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "color.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "cppcheck.h"
|
#include "cppcheck.h"
|
||||||
#include "errorlogger.h"
|
#include "errorlogger.h"
|
||||||
|
@ -63,6 +64,8 @@ private:
|
||||||
TEST_CASE(SerializeFileLocation);
|
TEST_CASE(SerializeFileLocation);
|
||||||
|
|
||||||
TEST_CASE(suppressUnmatchedSuppressions);
|
TEST_CASE(suppressUnmatchedSuppressions);
|
||||||
|
TEST_CASE(substituteTemplateFormatStatic);
|
||||||
|
TEST_CASE(substituteTemplateLocationStatic);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestPatternSearchReplace(const std::string& idPlaceholder, const std::string& id) const {
|
void TestPatternSearchReplace(const std::string& idPlaceholder, const std::string& id) const {
|
||||||
|
@ -481,6 +484,69 @@ private:
|
||||||
reportUnmatchedSuppressions(suppressions);
|
reportUnmatchedSuppressions(suppressions);
|
||||||
ASSERT_EQUALS("[a.c:10]: (information) Unmatched suppression: abc\n", errout.str());
|
ASSERT_EQUALS("[a.c:10]: (information) Unmatched suppression: abc\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void substituteTemplateFormatStatic() const
|
||||||
|
{
|
||||||
|
{
|
||||||
|
std::string s;
|
||||||
|
::substituteTemplateFormatStatic(s);
|
||||||
|
ASSERT_EQUALS("", s);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::string s = "template{black}\\z";
|
||||||
|
::substituteTemplateFormatStatic(s);
|
||||||
|
ASSERT_EQUALS("template{black}\\z", s);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::string s = "{reset}{bold}{dim}{red}{blue}{magenta}{default}\\b\\n\\r\\t";
|
||||||
|
::substituteTemplateFormatStatic(s);
|
||||||
|
ASSERT_EQUALS("\b\n\r\t", s);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::string s = "\\\\n";
|
||||||
|
::substituteTemplateFormatStatic(s);
|
||||||
|
ASSERT_EQUALS("\\\n", s);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::string s = "{{red}";
|
||||||
|
::substituteTemplateFormatStatic(s);
|
||||||
|
ASSERT_EQUALS("{", s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void substituteTemplateLocationStatic() const
|
||||||
|
{
|
||||||
|
{
|
||||||
|
std::string s;
|
||||||
|
::substituteTemplateLocationStatic(s);
|
||||||
|
ASSERT_EQUALS("", s);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::string s = "template";
|
||||||
|
::substituteTemplateLocationStatic(s);
|
||||||
|
ASSERT_EQUALS("template", s);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::string s = "template{black}\\z";
|
||||||
|
::substituteTemplateFormatStatic(s);
|
||||||
|
ASSERT_EQUALS("template{black}\\z", s);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::string s = "{reset}{bold}{dim}{red}{blue}{magenta}{default}\\b\\n\\r\\t";
|
||||||
|
::substituteTemplateFormatStatic(s);
|
||||||
|
ASSERT_EQUALS("\b\n\r\t", s);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::string s = "\\\\n";
|
||||||
|
::substituteTemplateFormatStatic(s);
|
||||||
|
ASSERT_EQUALS("\\\n", s);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::string s = "{{red}";
|
||||||
|
::substituteTemplateFormatStatic(s);
|
||||||
|
ASSERT_EQUALS("{", s);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
REGISTER_TEST(TestErrorLogger)
|
REGISTER_TEST(TestErrorLogger)
|
||||||
|
|
|
@ -55,6 +55,7 @@
|
||||||
<ClCompile Include="testclangimport.cpp" />
|
<ClCompile Include="testclangimport.cpp" />
|
||||||
<ClCompile Include="testclass.cpp" />
|
<ClCompile Include="testclass.cpp" />
|
||||||
<ClCompile Include="testcmdlineparser.cpp" />
|
<ClCompile Include="testcmdlineparser.cpp" />
|
||||||
|
<ClCompile Include="testcolor.cpp" />
|
||||||
<ClCompile Include="testcondition.cpp" />
|
<ClCompile Include="testcondition.cpp" />
|
||||||
<ClCompile Include="testconstructors.cpp" />
|
<ClCompile Include="testconstructors.cpp" />
|
||||||
<ClCompile Include="testcppcheck.cpp" />
|
<ClCompile Include="testcppcheck.cpp" />
|
||||||
|
|
Loading…
Reference in New Issue