Rules: Make it possible run a rule on the 'normal' token list
This commit is contained in:
parent
964b6cbd82
commit
537166cf47
|
@ -598,6 +598,10 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[])
|
||||||
for (; node && strcmp(node->Value(), "rule") == 0; node = node->NextSiblingElement()) {
|
for (; node && strcmp(node->Value(), "rule") == 0; node = node->NextSiblingElement()) {
|
||||||
Settings::Rule rule;
|
Settings::Rule rule;
|
||||||
|
|
||||||
|
tinyxml2::XMLElement *tokenlist = node->FirstChildElement("tokenlist");
|
||||||
|
if (tokenlist)
|
||||||
|
rule.tokenlist = tokenlist->GetText();
|
||||||
|
|
||||||
tinyxml2::XMLElement *pattern = node->FirstChildElement("pattern");
|
tinyxml2::XMLElement *pattern = node->FirstChildElement("pattern");
|
||||||
if (pattern) {
|
if (pattern) {
|
||||||
rule.pattern = pattern->GetText();
|
rule.pattern = pattern->GetText();
|
||||||
|
|
156
lib/cppcheck.cpp
156
lib/cppcheck.cpp
|
@ -344,6 +344,8 @@ void CppCheck::checkFile(const std::string &code, const char FileName[])
|
||||||
if (_settings.isEnabled("unusedFunction") && _settings._jobs == 1)
|
if (_settings.isEnabled("unusedFunction") && _settings._jobs == 1)
|
||||||
_checkUnusedFunctions.parseTokens(_tokenizer);
|
_checkUnusedFunctions.parseTokens(_tokenizer);
|
||||||
|
|
||||||
|
executeRules("normal", _tokenizer);
|
||||||
|
|
||||||
if (!_simplify)
|
if (!_simplify)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -362,75 +364,7 @@ void CppCheck::checkFile(const std::string &code, const char FileName[])
|
||||||
(*it)->runSimplifiedChecks(&_tokenizer, &_settings, this);
|
(*it)->runSimplifiedChecks(&_tokenizer, &_settings, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_RULES
|
executeRules("simple", _tokenizer);
|
||||||
// Are there extra rules?
|
|
||||||
if (!_settings.rules.empty()) {
|
|
||||||
std::ostringstream ostr;
|
|
||||||
for (const Token *tok = _tokenizer.tokens(); tok; tok = tok->next())
|
|
||||||
ostr << " " << tok->str();
|
|
||||||
const std::string str(ostr.str());
|
|
||||||
for (std::list<Settings::Rule>::const_iterator it = _settings.rules.begin(); it != _settings.rules.end(); ++it) {
|
|
||||||
const Settings::Rule &rule = *it;
|
|
||||||
if (rule.pattern.empty() || rule.id.empty() || rule.severity.empty())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const char *error = 0;
|
|
||||||
int erroffset = 0;
|
|
||||||
pcre *re = pcre_compile(rule.pattern.c_str(),0,&error,&erroffset,NULL);
|
|
||||||
if (!re && error) {
|
|
||||||
ErrorLogger::ErrorMessage errmsg(std::list<ErrorLogger::ErrorMessage::FileLocation>(),
|
|
||||||
Severity::error,
|
|
||||||
error,
|
|
||||||
"pcre_compile",
|
|
||||||
false);
|
|
||||||
|
|
||||||
reportErr(errmsg);
|
|
||||||
}
|
|
||||||
if (!re)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
int pos = 0;
|
|
||||||
int ovector[30];
|
|
||||||
while (0 <= pcre_exec(re, NULL, str.c_str(), (int)str.size(), pos, 0, ovector, 30)) {
|
|
||||||
unsigned int pos1 = (unsigned int)ovector[0];
|
|
||||||
unsigned int pos2 = (unsigned int)ovector[1];
|
|
||||||
|
|
||||||
// jump to the end of the match for the next pcre_exec
|
|
||||||
pos = (int)pos2;
|
|
||||||
|
|
||||||
// determine location..
|
|
||||||
ErrorLogger::ErrorMessage::FileLocation loc;
|
|
||||||
loc.setfile(_tokenizer.getSourceFilePath());
|
|
||||||
loc.line = 0;
|
|
||||||
|
|
||||||
unsigned int len = 0;
|
|
||||||
for (const Token *tok = _tokenizer.tokens(); tok; tok = tok->next()) {
|
|
||||||
len = len + 1 + tok->str().size();
|
|
||||||
if (len > pos1) {
|
|
||||||
loc.setfile(_tokenizer.list.getFiles().at(tok->fileIndex()));
|
|
||||||
loc.line = tok->linenr();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::list<ErrorLogger::ErrorMessage::FileLocation> callStack(1, loc);
|
|
||||||
|
|
||||||
// Create error message
|
|
||||||
std::string summary;
|
|
||||||
if (rule.summary.empty())
|
|
||||||
summary = "found '" + str.substr(pos1, pos2 - pos1) + "'";
|
|
||||||
else
|
|
||||||
summary = rule.summary;
|
|
||||||
const ErrorLogger::ErrorMessage errmsg(callStack, Severity::fromString(rule.severity), summary, rule.id, false);
|
|
||||||
|
|
||||||
// Report error
|
|
||||||
reportErr(errmsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
pcre_free(re);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
} catch (const InternalError &e) {
|
} catch (const InternalError &e) {
|
||||||
std::list<ErrorLogger::ErrorMessage::FileLocation> locationList;
|
std::list<ErrorLogger::ErrorMessage::FileLocation> locationList;
|
||||||
ErrorLogger::ErrorMessage::FileLocation loc2;
|
ErrorLogger::ErrorMessage::FileLocation loc2;
|
||||||
|
@ -455,6 +389,90 @@ void CppCheck::checkFile(const std::string &code, const char FileName[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CppCheck::executeRules(const std::string &tokenlist, const Tokenizer &tokenizer)
|
||||||
|
{
|
||||||
|
// Are there rules to execute?
|
||||||
|
bool isrule = false;
|
||||||
|
for (std::list<Settings::Rule>::const_iterator it = _settings.rules.begin(); it != _settings.rules.end(); ++it) {
|
||||||
|
if (it->tokenlist == tokenlist)
|
||||||
|
isrule = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// There is no rule to execute
|
||||||
|
if (isrule == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Write all tokens in a string that can be parsed by pcre
|
||||||
|
std::ostringstream ostr;
|
||||||
|
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next())
|
||||||
|
ostr << " " << tok->str();
|
||||||
|
const std::string str(ostr.str());
|
||||||
|
|
||||||
|
for (std::list<Settings::Rule>::const_iterator it = _settings.rules.begin(); it != _settings.rules.end(); ++it) {
|
||||||
|
const Settings::Rule &rule = *it;
|
||||||
|
if (rule.pattern.empty() || rule.id.empty() || rule.severity.empty() || rule.tokenlist != tokenlist)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
#ifdef HAVE_RULES
|
||||||
|
const char *error = 0;
|
||||||
|
int erroffset = 0;
|
||||||
|
pcre *re = pcre_compile(rule.pattern.c_str(),0,&error,&erroffset,NULL);
|
||||||
|
if (!re) {
|
||||||
|
if (error) {
|
||||||
|
ErrorLogger::ErrorMessage errmsg(std::list<ErrorLogger::ErrorMessage::FileLocation>(),
|
||||||
|
Severity::error,
|
||||||
|
error,
|
||||||
|
"pcre_compile",
|
||||||
|
false);
|
||||||
|
|
||||||
|
reportErr(errmsg);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pos = 0;
|
||||||
|
int ovector[30];
|
||||||
|
while (pos < (int)str.size() && 0 <= pcre_exec(re, NULL, str.c_str(), (int)str.size(), pos, 0, ovector, 30)) {
|
||||||
|
unsigned int pos1 = (unsigned int)ovector[0];
|
||||||
|
unsigned int pos2 = (unsigned int)ovector[1];
|
||||||
|
|
||||||
|
// jump to the end of the match for the next pcre_exec
|
||||||
|
pos = (int)pos2;
|
||||||
|
|
||||||
|
// determine location..
|
||||||
|
ErrorLogger::ErrorMessage::FileLocation loc;
|
||||||
|
loc.setfile(tokenizer.getSourceFilePath());
|
||||||
|
loc.line = 0;
|
||||||
|
|
||||||
|
std::size_t len = 0;
|
||||||
|
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) {
|
||||||
|
len = len + 1U + tok->str().size();
|
||||||
|
if (len > pos1) {
|
||||||
|
loc.setfile(tokenizer.list.getFiles().at(tok->fileIndex()));
|
||||||
|
loc.line = tok->linenr();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::list<ErrorLogger::ErrorMessage::FileLocation> callStack(1, loc);
|
||||||
|
|
||||||
|
// Create error message
|
||||||
|
std::string summary;
|
||||||
|
if (rule.summary.empty())
|
||||||
|
summary = "found '" + str.substr(pos1, pos2 - pos1) + "'";
|
||||||
|
else
|
||||||
|
summary = rule.summary;
|
||||||
|
const ErrorLogger::ErrorMessage errmsg(callStack, Severity::fromString(rule.severity), summary, rule.id, false);
|
||||||
|
|
||||||
|
// Report error
|
||||||
|
reportErr(errmsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
pcre_free(re);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Settings &CppCheck::settings()
|
Settings &CppCheck::settings()
|
||||||
{
|
{
|
||||||
return _settings;
|
return _settings;
|
||||||
|
|
|
@ -148,6 +148,13 @@ private:
|
||||||
/** @brief Check file */
|
/** @brief Check file */
|
||||||
void checkFile(const std::string &code, const char FileName[]);
|
void checkFile(const std::string &code, const char FileName[]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Execute rules, if any
|
||||||
|
* @param tokenlist token list to use (normal / simple)
|
||||||
|
* @param tokenizer tokenizer
|
||||||
|
*/
|
||||||
|
void executeRules(const std::string &tokenlist, const Tokenizer &tokenizer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Errors and warnings are directed here.
|
* @brief Errors and warnings are directed here.
|
||||||
*
|
*
|
||||||
|
|
|
@ -178,10 +178,12 @@ public:
|
||||||
class CPPCHECKLIB Rule {
|
class CPPCHECKLIB Rule {
|
||||||
public:
|
public:
|
||||||
Rule()
|
Rule()
|
||||||
: id("rule") // default id
|
: tokenlist("simple") // use simple tokenlist
|
||||||
|
, id("rule") // default id
|
||||||
, severity("style") { // default severity
|
, severity("style") { // default severity
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string tokenlist;
|
||||||
std::string pattern;
|
std::string pattern;
|
||||||
std::string id;
|
std::string id;
|
||||||
std::string severity;
|
std::string severity;
|
||||||
|
|
Loading…
Reference in New Issue