Skip to content

Commit

Permalink
Fix #12427 (premium misra C rule texts) (#5969)
Browse files Browse the repository at this point in the history
  • Loading branch information
danmar authored Feb 10, 2024
1 parent 7c790ca commit 930f52c
Show file tree
Hide file tree
Showing 10 changed files with 70 additions and 11 deletions.
8 changes: 0 additions & 8 deletions addons/misra.py
Original file line number Diff line number Diff line change
Expand Up @@ -4280,14 +4280,6 @@ def reportError(self, location, num1, num2):
errorId = 'c2012-' + str(num1) + '.' + str(num2)
misra_severity = 'Undefined'
cppcheck_severity = 'style'
if self.path_premium_addon and ruleNum not in self.ruleTexts:
for line in cppcheckdata.cmd_output([self.path_premium_addon, '--cli', '--get-rule-text=' + errorId]).split('\n'):
if len(line) > 1 and not line.startswith('{'):
errmsg = line.strip()
rule = Rule(num1, num2)
rule.text = errmsg
self.ruleTexts[rule.num] = rule
break
if ruleNum in self.ruleTexts:
errmsg = self.ruleTexts[ruleNum].text
if self.ruleTexts[ruleNum].misra_severity:
Expand Down
2 changes: 2 additions & 0 deletions cli/cppcheckexecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,8 @@ int CppCheckExecutor::check(int argc, const char* const argv[])
mFiles = parser.getFiles();
mFileSettings = parser.getFileSettings();

settings.setMisraRuleTexts(executeCommand);

mStdLogger = new StdLogger(settings);

CppCheck cppCheck(*mStdLogger, true, executeCommand);
Expand Down
2 changes: 1 addition & 1 deletion gui/checkthread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
#endif

// NOLINTNEXTLINE(performance-unnecessary-value-param) - used as callback so we need to preserve the signature
static int executeCommand(std::string exe, std::vector<std::string> args, std::string redirect, std::string &output) // cppcheck-suppress passedByValueCallback
int CheckThread::executeCommand(std::string exe, std::vector<std::string> args, std::string redirect, std::string &output) // cppcheck-suppress passedByValue
{
output.clear();

Expand Down
2 changes: 2 additions & 0 deletions gui/checkthread.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ class CheckThread : public QThread {
*/
static QString clangTidyCmd();

static int executeCommand(std::string exe, std::vector<std::string> args, std::string redirect, std::string &output);

signals:

/**
Expand Down
2 changes: 2 additions & 0 deletions gui/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "applicationlist.h"
#include "aboutdialog.h"
#include "analyzerinfo.h"
#include "checkthread.h"
#include "common.h"
#include "cppcheck.h"
#include "errortypes.h"
Expand Down Expand Up @@ -1090,6 +1091,7 @@ QPair<bool,Settings> MainWindow::getCppcheckSettings()
if (!premiumArgs.contains("misra") && mProjectFile->getAddons().contains("misra"))
premiumArgs += " --misra-c-2012";
result.premiumArgs = premiumArgs.mid(1).toStdString();
result.setMisraRuleTexts(CheckThread::executeCommand);
}
}

Expand Down
3 changes: 1 addition & 2 deletions lib/cppcheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1473,8 +1473,7 @@ void CppCheck::executeAddons(const std::vector<std::string>& files, const std::s
errmsg.id = obj["addon"].get<std::string>() + "-" + obj["errorId"].get<std::string>();
if (misraC2023 && startsWith(errmsg.id, "misra-c2012-"))
errmsg.id = "misra-c2023-" + errmsg.id.substr(12);
const std::string text = obj["message"].get<std::string>();
errmsg.setmsg(text);
errmsg.setmsg(mSettings.getMisraRuleText(errmsg.id, obj["message"].get<std::string>()));
const std::string severity = obj["severity"].get<std::string>();
errmsg.severity = severityFromString(severity);
if (errmsg.severity == Severity::none || errmsg.severity == Severity::internal) {
Expand Down
2 changes: 2 additions & 0 deletions lib/cppcheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ class CPPCHECKLIB CppCheck : ErrorLogger {

bool isPremiumCodingStandardId(const std::string& id) const;

std::string getAddonMessage(const std::string& id, const std::string& text) const;

private:
#ifdef HAVE_RULES
/** Are there "simple" rules */
Expand Down
44 changes: 44 additions & 0 deletions lib/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "vfvalue.h"

#include <fstream>
#include <sstream>

#include "json.h"

Expand Down Expand Up @@ -545,3 +546,46 @@ bool Settings::isPremiumEnabled(const char id[]) const
return true;
return false;
}

void Settings::setMisraRuleTexts(const ExecuteCmdFn& executeCommand)
{
if (premiumArgs.find("--misra-c-20") != std::string::npos) {
const auto it = std::find_if(addonInfos.cbegin(), addonInfos.cend(), [](const AddonInfo& a) {
return a.name == "premiumaddon.json";
});
if (it != addonInfos.cend()) {
std::string arg;
if (premiumArgs.find("--misra-c-2023") != std::string::npos)
arg = "--misra-c-2023-rule-texts";
else
arg = "--misra-c-2012-rule-texts";
std::string output;
executeCommand(it->executable, {arg}, "2>&1", output);
setMisraRuleTexts(output);
}
}
}

void Settings::setMisraRuleTexts(const std::string& data)
{
mMisraRuleTexts.clear();
std::istringstream istr(data);
std::string line;
while (std::getline(istr, line)) {
std::string::size_type pos = line.find(' ');
if (pos == std::string::npos)
continue;
std::string id = line.substr(0, pos);
std::string text = line.substr(pos + 1);
if (id.empty() || text.empty())
continue;
mMisraRuleTexts[id] = text;
}
}

std::string Settings::getMisraRuleText(const std::string& id, const std::string& text) const {
if (id.compare(0, 9, "misra-c20") != 0)
return text;
const auto it = mMisraRuleTexts.find(id.substr(id.rfind('-') + 1));
return it != mMisraRuleTexts.end() ? it->second : text;
}
7 changes: 7 additions & 0 deletions lib/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ class CPPCHECKLIB WARN_UNUSED Settings {
/** @brief Extra arguments for Cppcheck Premium addon */
std::string premiumArgs;

/** Is checker id enabled by premiumArgs */
bool isPremiumEnabled(const char id[]) const;

/** @brief Using -E for debugging purposes */
Expand Down Expand Up @@ -452,9 +453,15 @@ class CPPCHECKLIB WARN_UNUSED Settings {
};
CheckLevel checkLevel = CheckLevel::normal;

using ExecuteCmdFn = std::function<int (std::string,std::vector<std::string>,std::string,std::string&)>;
void setMisraRuleTexts(const ExecuteCmdFn& executeCommand);
void setMisraRuleTexts(const std::string& data);
std::string getMisraRuleText(const std::string& id, const std::string& text) const;

private:
static std::string parseEnabled(const std::string &str, std::tuple<SimpleEnableGroup<Severity>, SimpleEnableGroup<Checks>> &groups);
std::string applyEnabled(const std::string &str, bool enable);
std::map<std::string, std::string> mMisraRuleTexts;
};

/// @}
Expand Down
9 changes: 9 additions & 0 deletions test/testsettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class TestSettings : public TestFixture {
TEST_CASE(loadCppcheckCfg);
TEST_CASE(loadCppcheckCfgSafety);
TEST_CASE(getNameAndVersion);
TEST_CASE(ruleTexts);
}

void simpleEnableGroup() const {
Expand Down Expand Up @@ -254,6 +255,14 @@ class TestSettings : public TestFixture {
ASSERT_EQUALS("12.3.4s", nameVersion.second);
}
}

void ruleTexts() const
{
Settings s;
s.setMisraRuleTexts("1.1 text 1\n1.2 text 2\n");
ASSERT_EQUALS("text 1", s.getMisraRuleText("misra-c2012-1.1", "---"));
ASSERT_EQUALS("text 2", s.getMisraRuleText("misra-c2012-1.2", "---"));
}
};

REGISTER_TEST(TestSettings)

0 comments on commit 930f52c

Please sign in to comment.