diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index cc56b0baf9b5..dbf050df6461 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -20,6 +20,7 @@ #include "addoninfo.h" #include "check.h" +#include "checkers.h" #include "color.h" #include "config.h" #include "cppcheck.h" @@ -1169,6 +1170,7 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a mLogger.printError("Unknown report type \'" + typeStr + "\'"); return Result::Fail; } + mSettings.guidelineMapping = checkers::createGuidelineMapping(mSettings.reportType); } // Rule given at command line diff --git a/cli/cppcheckexecutor.cpp b/cli/cppcheckexecutor.cpp index 34e48819bd19..755885278c39 100644 --- a/cli/cppcheckexecutor.cpp +++ b/cli/cppcheckexecutor.cpp @@ -623,7 +623,8 @@ void StdLogger::reportErr(const ErrorMessage &msg) return; ErrorMessage msgCopy = msg; - msgCopy.guideline = checkers::getGuideline(msgCopy.id, mSettings.reportType); + msgCopy.guideline = checkers::getGuideline(msgCopy.id, mSettings.reportType, + mSettings.guidelineMapping, msgCopy.severity); msgCopy.classification = checkers::getClassification(msgCopy.guideline, mSettings.reportType); if (mSettings.outputFormat == Settings::OutputFormat::sarif) diff --git a/gui/resultstree.cpp b/gui/resultstree.cpp index 4a8bd4557d87..11f65d4238e5 100644 --- a/gui/resultstree.cpp +++ b/gui/resultstree.cpp @@ -98,17 +98,11 @@ static constexpr int COLUMN_SINCE_DATE = 10; static constexpr int COLUMN_TAGS = 11; static constexpr int COLUMN_CWE = 12; -static QString getGuideline(ReportType reportType, const QMap& guidelines, const QString& errorId, Severity severity) { - auto guideline = QString::fromStdString(checkers::getGuideline(errorId.toStdString(), reportType)); - if (!guideline.isEmpty()) - return guideline; - - guideline = guidelines.value(errorId); - if (!guideline.isEmpty()) - return guideline; - if (severity == Severity::error || severity == Severity::warning) - return guidelines.value("error"); - return QString(); +static QString getGuideline(ReportType reportType, const std::map &guidelineMapping, + const QString& errorId, Severity severity) { + return QString::fromStdString(checkers::getGuideline(errorId.toStdString(), + reportType, guidelineMapping, + severity)); } static QString getClassification(ReportType reportType, const QString& guideline) { @@ -173,26 +167,7 @@ void ResultsTree::keyPressEvent(QKeyEvent *event) void ResultsTree::setReportType(ReportType reportType) { mReportType = reportType; - auto readIdMapping = [this](const std::vector& idMapping, const char* ext = "") { - for (const auto& i: idMapping) - for (const QString& cppcheckId: QString(i.cppcheckId).split(",")) - mGuideline[cppcheckId] = QString(i.guideline) + ext; - }; - - if (reportType == ReportType::autosar) - readIdMapping(checkers::idMappingAutosar); - else if (reportType == ReportType::certC) - readIdMapping(checkers::idMappingCertC, "-C"); - else if (reportType == ReportType::certCpp) { - readIdMapping(checkers::idMappingCertC, "-C"); - readIdMapping(checkers::idMappingCertCpp, "-CPP"); - } - else if (reportType == ReportType::misraC) - readIdMapping(checkers::idMappingMisraC); - else if (reportType == ReportType::misraCpp2008) - readIdMapping(checkers::idMappingMisraCpp2008); - else if (reportType == ReportType::misraCpp2023) - readIdMapping(checkers::idMappingMisraCpp2023); + mGuideline = checkers::createGuidelineMapping(reportType); for (int i = 0; i < mModel.rowCount(); ++i) { const QStandardItem *fileItem = mModel.item(i, COLUMN_FILE); diff --git a/gui/resultstree.h b/gui/resultstree.h index 994b8c10e820..15dc4e371e0d 100644 --- a/gui/resultstree.h +++ b/gui/resultstree.h @@ -540,7 +540,7 @@ protected slots: ReportType mReportType = ReportType::normal; - QMap mGuideline; + std::map mGuideline; }; /// @} #endif // RESULTSTREE_H diff --git a/lib/checkers.cpp b/lib/checkers.cpp index 901f361c71ed..dcb7c34e0346 100644 --- a/lib/checkers.cpp +++ b/lib/checkers.cpp @@ -2173,38 +2173,107 @@ namespace checkers { } } - std::string getGuideline(const std::string &errId, ReportType reportType) + std::string getGuideline(const std::string &errId, ReportType reportType, + const std::map &guidelineMapping, + Severity severity) { + std::string guideline; + switch (reportType) { case ReportType::autosar: - if (errId.rfind("premium-autosar-", 0) == 0) - return errId.substr(16); + if (errId.rfind("premium-autosar-", 0) == 0) { + guideline = errId.substr(16); + break; + } if (errId.rfind("premium-misra-cpp-2008-", 0) == 0) - return "M" + errId.substr(23); - return ""; + guideline = "M" + errId.substr(23); + break; case ReportType::certC: case ReportType::certCpp: if (errId.rfind("premium-cert-", 0) == 0) { - std::string guideline = errId.substr(13); + guideline = errId.substr(13); std::transform(guideline.begin(), guideline.end(), guideline.begin(), static_cast(std::toupper)); - return guideline; } - return ""; + break; case ReportType::misraC: if (errId.rfind("misra-c20", 0) == 0) - return errId.substr(errId.rfind('-') + 1); - return ""; + guideline = errId.substr(errId.rfind('-') + 1); + break; case ReportType::misraCpp2008: if (errId.rfind("misra-cpp-2008-", 0) == 0) - return errId.substr(15); - return ""; + guideline = errId.substr(15); + break; case ReportType::misraCpp2023: if (errId.rfind("misra-cpp-2023-", 0) == 0) - return errId.substr(15); - return ""; + guideline = errId.substr(15); + break; default: + break; + } + + if (!guideline.empty()) + return guideline; + + auto it = guidelineMapping.find(errId); + + if (it != guidelineMapping.cend()) + return it->second; + + if (severity != Severity::error && severity != Severity::warning) return ""; + + it = guidelineMapping.find(errId); + + if (it != guidelineMapping.cend()) + return it->second; + + return ""; + } + + std::map createGuidelineMapping(ReportType reportType) { + std::map guidelineMapping; + const std::vector *idMapping1 = nullptr; + const std::vector *idMapping2 = nullptr; + std::string ext1, ext2; + + switch (reportType) { + case ReportType::autosar: + idMapping1 = &idMappingAutosar; + break; + case ReportType::certCpp: + idMapping2 = &idMappingCertCpp; + ext2 = "-CPP"; + // fallthrough + case ReportType::certC: + idMapping1 = &idMappingCertC; + ext1 = "-C"; + break; + case ReportType::misraC: + idMapping1 = &idMappingMisraC; + break; + case ReportType::misraCpp2008: + idMapping1 = &idMappingMisraCpp2008; + break; + case ReportType::misraCpp2023: + idMapping1 = &idMappingMisraCpp2023; + break; + default: + break; + } + + if (idMapping1) { + for (const auto &i : *idMapping1) + for (const std::string &cppcheckId : splitStringVector(i.cppcheckId, ',')) + guidelineMapping[cppcheckId] = i.guideline + ext1; } + + if (idMapping2) { + for (const auto &i : *idMapping2) + for (const std::string &cppcheckId : splitStringVector(i.cppcheckId, ',')) + guidelineMapping[cppcheckId] = i.guideline + ext2; + } + + return guidelineMapping; } } diff --git a/lib/checkers.h b/lib/checkers.h index c0daf0461b04..8ad0883bdd3d 100644 --- a/lib/checkers.h +++ b/lib/checkers.h @@ -24,6 +24,7 @@ #include #include "config.h" +#include "errortypes.h" namespace checkers { extern CPPCHECKLIB const std::map allCheckers; @@ -85,7 +86,10 @@ namespace checkers { extern std::vector certCppInfo; extern CPPCHECKLIB std::string getClassification(const std::string &guideline, ReportType reportType); - extern CPPCHECKLIB std::string getGuideline(const std::string &errId, ReportType reportType); + extern CPPCHECKLIB std::string getGuideline(const std::string &errId, ReportType reportType, + const std::map &guidelineMapping, + Severity severity); + extern CPPCHECKLIB std::map createGuidelineMapping(ReportType reportType); } #endif diff --git a/lib/settings.h b/lib/settings.h index 71c39c7248c9..9b5008e1af62 100644 --- a/lib/settings.h +++ b/lib/settings.h @@ -114,6 +114,9 @@ class CPPCHECKLIB WARN_UNUSED Settings { /** @brief Report type */ checkers::ReportType reportType = checkers::ReportType::normal; + /** @brief Maps cppcheck error ids to guidelines */ + std::map guidelineMapping; + /** @brief addons, either filename of python/json file or json data */ std::unordered_set addons;