Add a dynamic rule enable/disable system
This commit is contained in:
parent
2eb8492993
commit
231b486e49
|
@ -641,43 +641,68 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[])
|
|||
else if (std::strncmp(argv[i], "--rule=", 7) == 0) {
|
||||
Settings::Rule rule;
|
||||
rule.pattern = 7 + argv[i];
|
||||
_settings->rules.push_back(rule);
|
||||
_settings->rules[rule.id] = rule;
|
||||
}
|
||||
|
||||
// Rule file
|
||||
else if (std::strncmp(argv[i], "--rule-file=", 12) == 0) {
|
||||
tinyxml2::XMLDocument doc;
|
||||
if (doc.LoadFile(12+argv[i]) == tinyxml2::XML_NO_ERROR) {
|
||||
tinyxml2::XMLElement *node = doc.FirstChildElement();
|
||||
const tinyxml2::XMLElement *node = doc.FirstChildElement();
|
||||
for (; node && strcmp(node->Value(), "rule") == 0; node = node->NextSiblingElement()) {
|
||||
Settings::Rule rule;
|
||||
|
||||
tinyxml2::XMLElement *tokenlist = node->FirstChildElement("tokenlist");
|
||||
const tinyxml2::XMLElement *tokenlist = node->FirstChildElement("tokenlist");
|
||||
if (tokenlist)
|
||||
rule.tokenlist = tokenlist->GetText();
|
||||
|
||||
tinyxml2::XMLElement *pattern = node->FirstChildElement("pattern");
|
||||
const tinyxml2::XMLElement *pattern = node->FirstChildElement("pattern");
|
||||
if (pattern) {
|
||||
rule.pattern = pattern->GetText();
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *message = node->FirstChildElement("message");
|
||||
const tinyxml2::XMLElement *message = node->FirstChildElement("message");
|
||||
if (message) {
|
||||
tinyxml2::XMLElement *severity = message->FirstChildElement("severity");
|
||||
const tinyxml2::XMLElement *severity = message->FirstChildElement("severity");
|
||||
if (severity)
|
||||
rule.severity = severity->GetText();
|
||||
|
||||
tinyxml2::XMLElement *id = message->FirstChildElement("id");
|
||||
const tinyxml2::XMLElement *id = message->FirstChildElement("id");
|
||||
if (id)
|
||||
rule.id = id->GetText();
|
||||
|
||||
tinyxml2::XMLElement *summary = message->FirstChildElement("summary");
|
||||
const tinyxml2::XMLElement *summary = message->FirstChildElement("summary");
|
||||
if (summary)
|
||||
rule.summary = summary->GetText() ? summary->GetText() : "";
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *state = node->FirstChildElement("state");
|
||||
if (state) {
|
||||
std::string rule_state = state->GetText();
|
||||
if (rule_state == "enabled")
|
||||
rule.enabled = true;
|
||||
else if (rule_state == "disabled")
|
||||
rule.enabled = false;
|
||||
else {
|
||||
std::string msg("cppcheck: error: unrecognized rule state: \"");
|
||||
msg += rule_state;
|
||||
msg += "\". Supported states: disable, enable.";
|
||||
PrintMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *disabled = node->FirstChildElement("disable");
|
||||
if (disabled) {
|
||||
rule.disable_rules = disabled->GetText();
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *enabled = node->FirstChildElement("enable");
|
||||
if (enabled) {
|
||||
rule.enable_rules = enabled->GetText();
|
||||
}
|
||||
|
||||
if (!rule.pattern.empty())
|
||||
_settings->rules.push_back(rule);
|
||||
_settings->rules[rule.id] = rule;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -168,8 +168,8 @@ unsigned int CppCheck::processFile(const std::string& filename, std::istream& fi
|
|||
}
|
||||
|
||||
// Run rules on this code
|
||||
for (std::list<Settings::Rule>::const_iterator it = _settings.rules.begin(); it != _settings.rules.end(); ++it) {
|
||||
if (it->tokenlist == "define") {
|
||||
for (std::map<std::string, Settings::Rule>::const_iterator it = _settings.rules.begin(); it != _settings.rules.end(); ++it) {
|
||||
if (it->second.enabled && it->second.tokenlist == "define") {
|
||||
Tokenizer tokenizer2(&_settings, this);
|
||||
std::istringstream istr2(filedata);
|
||||
tokenizer2.list.createTokens(istr2, filename);
|
||||
|
@ -320,8 +320,8 @@ bool CppCheck::checkFile(const std::string &code, const char FileName[], std::se
|
|||
_tokenizer.setTimerResults(&S_timerResults);
|
||||
try {
|
||||
// Execute rules for "raw" code
|
||||
for (std::list<Settings::Rule>::const_iterator it = _settings.rules.begin(); it != _settings.rules.end(); ++it) {
|
||||
if (it->tokenlist == "raw") {
|
||||
for (std::map<std::string, Settings::Rule>::const_iterator it = _settings.rules.begin(); it != _settings.rules.end(); ++it) {
|
||||
if (it->second.enabled && it->second.tokenlist == "raw") {
|
||||
Tokenizer tokenizer2(&_settings, this);
|
||||
std::istringstream istr(code);
|
||||
tokenizer2.list.createTokens(istr, FileName);
|
||||
|
@ -439,8 +439,8 @@ void CppCheck::executeRules(const std::string &tokenlist, const Tokenizer &token
|
|||
#ifdef HAVE_RULES
|
||||
// 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)
|
||||
for (std::map<std::string, Settings::Rule>::const_iterator it = _settings.rules.begin(); it != _settings.rules.end(); ++it) {
|
||||
if (it->second.enabled && it->second.tokenlist == tokenlist)
|
||||
isrule = true;
|
||||
}
|
||||
|
||||
|
@ -454,9 +454,9 @@ void CppCheck::executeRules(const std::string &tokenlist, const Tokenizer &token
|
|||
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)
|
||||
for (std::map<std::string, Settings::Rule>::const_iterator it = _settings.rules.begin(); it != _settings.rules.end(); ++it) {
|
||||
const Settings::Rule &rule = it->second;
|
||||
if (rule.pattern.empty() || rule.id.empty() || rule.severity.empty() || rule.tokenlist != tokenlist || !rule.enabled)
|
||||
continue;
|
||||
|
||||
const char *error = nullptr;
|
||||
|
@ -511,6 +511,26 @@ void CppCheck::executeRules(const std::string &tokenlist, const Tokenizer &token
|
|||
|
||||
// Report error
|
||||
reportErr(errmsg);
|
||||
|
||||
// Disable rules that must be disabled
|
||||
std::istringstream disable(rule.disable_rules);
|
||||
do {
|
||||
std::string rule_to_disable;
|
||||
disable >> rule_to_disable;
|
||||
if (rule_to_disable != "") {
|
||||
_settings.rules[rule_to_disable].enabled = false;
|
||||
}
|
||||
} while (disable);
|
||||
|
||||
// Enable rules that must be enabled
|
||||
std::istringstream enable(rule.enable_rules);
|
||||
do {
|
||||
std::string rule_to_enable;
|
||||
enable >> rule_to_enable;
|
||||
if (rule_to_enable != "") {
|
||||
_settings.rules[rule_to_enable].enabled = true;
|
||||
}
|
||||
} while (enable);
|
||||
}
|
||||
|
||||
pcre_free(re);
|
||||
|
|
|
@ -218,7 +218,10 @@ public:
|
|||
Rule()
|
||||
: tokenlist("simple") // use simple tokenlist
|
||||
, id("rule") // default id
|
||||
, severity("style") { // default severity
|
||||
, severity("style") // default severity
|
||||
, disable_rules("") // default disabled rules
|
||||
, enable_rules("") // default enabled rules
|
||||
, enabled(true) {
|
||||
}
|
||||
|
||||
std::string tokenlist;
|
||||
|
@ -226,12 +229,15 @@ public:
|
|||
std::string id;
|
||||
std::string severity;
|
||||
std::string summary;
|
||||
std::string disable_rules;
|
||||
std::string enable_rules;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Extra rules
|
||||
*/
|
||||
std::list<Rule> rules;
|
||||
std::map<std::string, Rule> rules;
|
||||
|
||||
/** Is the 'configuration checking' wanted? */
|
||||
bool checkConfiguration;
|
||||
|
|
Loading…
Reference in New Issue