Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix #13362: Misra report on command line #7096

Open
wants to merge 36 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
30d5440
add command line option and setting for report-type
ludviggunne Dec 10, 2024
7148104
add classification and guideline fields to ErrorMessage
ludviggunne Dec 10, 2024
eee69e5
set classification and guideline for ErrorMessage
ludviggunne Dec 10, 2024
2699d11
update make dependencies
ludviggunne Dec 10, 2024
dc5b54e
add guidline/classification to xml output
ludviggunne Dec 10, 2024
1652e5a
show classification and guideline in stderr
ludviggunne Dec 11, 2024
ff5f3bf
set guidline/classification for cert c/c++
ludviggunne Dec 11, 2024
d943057
add description for report-type option
ludviggunne Dec 11, 2024
ab45d00
fix warning
ludviggunne Dec 11, 2024
3ef82a5
fix warning
ludviggunne Dec 11, 2024
dbd8abb
use existing split function
ludviggunne Dec 11, 2024
1baccfc
hoist stoi calls
ludviggunne Dec 12, 2024
cae8682
decouple guideline/classification logic from ErrorMessage
ludviggunne Dec 12, 2024
50b90e2
add vector variant of splitString
ludviggunne Dec 12, 2024
2061c60
movec reporttype logic to checkers.*
ludviggunne Dec 12, 2024
914b65f
use library ReportType in GUI
ludviggunne Dec 12, 2024
f3067cc
formatting
ludviggunne Dec 13, 2024
5faf85f
use library getGuideline/getClassification in GUI
ludviggunne Dec 18, 2024
9b013d1
set message guideline/classification in StdLogger::reportErr
ludviggunne Dec 18, 2024
ca160c6
move guideline mapping to library
ludviggunne Dec 18, 2024
0c84359
update cmake dependencies for gui tests
ludviggunne Dec 27, 2024
f7a90f5
add uint8_t base for ReportType
ludviggunne Dec 27, 2024
66271b5
add FALLTHROUGH macro
ludviggunne Dec 27, 2024
09167fc
add cmdlineparser tests
ludviggunne Dec 27, 2024
56a1b58
add errorlogger tests
ludviggunne Dec 27, 2024
78e16a7
add defaultReportType test
ludviggunne Dec 27, 2024
a8e19ad
update cppcheck manual and cli usage
ludviggunne Dec 27, 2024
49fe94a
refactor splitString
ludviggunne Dec 30, 2024
9ee60f6
explicit ReportType values
ludviggunne Dec 30, 2024
c4f6bf4
update releasenotes.txt
ludviggunne Dec 30, 2024
277169a
update .ts files
ludviggunne Jan 5, 2025
e245967
Revert "update .ts files"
ludviggunne Jan 12, 2025
b955c4f
change default template argument for splitString
ludviggunne Jan 18, 2025
d808b30
move guideline/classification functions to errorlogger
ludviggunne Jan 12, 2025
8f6d965
add CPPCHECKLIB to declarations
ludviggunne Jan 19, 2025
78b6a52
remove some unused includes
ludviggunne Jan 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 34 additions & 34 deletions Makefile

Large diffs are not rendered by default.

32 changes: 32 additions & 0 deletions cli/cmdlineparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1227,6 +1227,29 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
mSettings.reportProgress = tmp;
}

else if (std::strncmp(argv[i], "--report-type=", 14) == 0) {
const std::string typeStr = argv[i] + 14;
if (typeStr == "normal") {
mSettings.reportType = ReportType::normal;
} else if (typeStr == "autosar") {
mSettings.reportType = ReportType::autosar;
} else if (typeStr == "certC") {
mSettings.reportType = ReportType::certC;
} else if (typeStr == "certCpp") {
mSettings.reportType = ReportType::certCpp;
} else if (typeStr == "misraC") {
mSettings.reportType = ReportType::misraC;
} else if (typeStr == "misraCpp2008") {
mSettings.reportType = ReportType::misraCpp2008;
} else if (typeStr == "misraCpp2023") {
mSettings.reportType = ReportType::misraCpp2023;
} else {
mLogger.printError("Unknown report type \'" + typeStr + "\'");
return Result::Fail;
}
mSettings.guidelineMapping = createGuidelineMapping(mSettings.reportType);
}

// Rule given at command line
else if (std::strncmp(argv[i], "--rule=", 7) == 0) {
#ifdef HAVE_RULES
Expand Down Expand Up @@ -1824,6 +1847,15 @@ void CmdLineParser::printHelp() const
" currently only possible to apply the base paths to\n"
" files that are on a lower level in the directory tree.\n"
" --report-progress Report progress messages while checking a file (single job only).\n"
" --report-type=<type> Add guideline and classification fields for specified coding standard.\n"
ludviggunne marked this conversation as resolved.
Show resolved Hide resolved
" The available report types are:\n"
" * normal Default, only show cppcheck error ID and severity)\n"
" * autosar Autosar\n"
" * certC Cert C\n"
" * certCpp Cert Cpp\n"
" * misraC Misra C\n"
" * misraCpp2008 Misra C++ 2008\n"
" * misraCpp2023 Misra C++ 2023\n"
" --rule=<rule> Match regular expression.\n"
" --rule-file=<file> Use given rule file. For more information, see:\n"
" http://sourceforge.net/projects/cppcheck/files/Articles/\n"
Expand Down
11 changes: 8 additions & 3 deletions cli/cppcheckexecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -626,12 +626,17 @@ void StdLogger::reportErr(const ErrorMessage &msg)
if (!mSettings.emitDuplicates && !mShownErrors.insert(msg.toString(mSettings.verbose)).second)
return;

ErrorMessage msgCopy = msg;
msgCopy.guideline = getGuideline(msgCopy.id, mSettings.reportType,
mSettings.guidelineMapping, msgCopy.severity);
msgCopy.classification = getClassification(msgCopy.guideline, mSettings.reportType);

if (mSettings.outputFormat == Settings::OutputFormat::sarif)
mSarifReport.addFinding(msg);
mSarifReport.addFinding(msgCopy);
else if (mSettings.xml)
reportErr(msg.toXML());
reportErr(msgCopy.toXML());
else
reportErr(msg.toString(mSettings.verbose, mSettings.templateFormat, mSettings.templateLocation));
reportErr(msgCopy.toString(mSettings.verbose, mSettings.templateFormat, mSettings.templateLocation));
}

/**
Expand Down
3 changes: 2 additions & 1 deletion gui/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
#include <QMap>
#include <QString>

#include "errorlogger.h"

/// @addtogroup GUI
/// @{

Expand Down Expand Up @@ -52,7 +54,6 @@

// Report type
#define SETTINGS_REPORT_TYPE "Report type"
enum class ReportType : std::uint8_t { normal=0, autosar=1, certC=2, certCpp=3, misraC=4, misraCpp2008=5, misraCpp2023=6 };

// Show * states
#define SETTINGS_SHOW_STYLE "Show style"
Expand Down
128 changes: 7 additions & 121 deletions gui/resultstree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,110 +98,15 @@ 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<QString,QString>& guidelines, const QString& errorId, Severity severity) {
if (reportType == ReportType::autosar) {
if (errorId.startsWith("premium-autosar-"))
return errorId.mid(16);
if (errorId.startsWith("premium-misra-cpp-2008-"))
return "M" + errorId.mid(23);
}
if (reportType == ReportType::certC || reportType == ReportType::certCpp) {
if (errorId.startsWith("premium-cert-"))
return errorId.mid(13).toUpper();
}
if (errorId.startsWith("premium-"))
return getGuideline(reportType, guidelines, errorId.mid(8), severity);
if (reportType == ReportType::misraC && (errorId.startsWith("misra-c20") || errorId.startsWith("misra-c-20")))
return errorId.mid(errorId.lastIndexOf("-") + 1);
if (reportType == ReportType::misraCpp2008 && errorId.startsWith("misra-cpp-2008-"))
return errorId.mid(15);
if (reportType == ReportType::misraCpp2023 && errorId.startsWith("misra-cpp-2023-"))
return errorId.mid(15);
const QString& 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<std::string, std::string> &guidelineMapping,
const QString& errorId, Severity severity) {
return QString::fromStdString(getGuideline(errorId.toStdString(),
reportType, guidelineMapping,
severity));
}

static QString getClassification(ReportType reportType, const QString& guideline) {
if (guideline.isEmpty())
return QString();
auto getFromInfo = [](const std::vector<checkers::Info>& info, const QString& guideline) -> QString {
for (const checkers::Info& i: info) {
// cppcheck-suppress useStlAlgorithm
if (guideline.compare(i.guideline, Qt::CaseInsensitive) == 0)
return i.classification;
}
return QString();
};
if (reportType == ReportType::autosar)
return getFromInfo(checkers::autosarInfo, guideline);
if (reportType == ReportType::certC || reportType == ReportType::certCpp) {
if (guideline.endsWith("-CPP"))
return getFromInfo(checkers::certCppInfo, guideline);
if (guideline.endsWith("-C"))
return getFromInfo(checkers::certCInfo, guideline);
}
else if (reportType == ReportType::misraC) {
QStringList list = guideline.split(".");
if (list.size() == 2) {
bool ok = true;
const int a = list[0].toInt(&ok);
if (!ok)
return QString();
const int b = list[1].toInt(&ok);
if (!ok)
return QString();
for (const auto& info: checkers::misraC2012Rules) {
// cppcheck-suppress useStlAlgorithm
if (info.a == a && info.b == b)
return info.str;
}
}
}
else if (reportType == ReportType::misraCpp2008) {
QStringList list = guideline.split("-");
if (list.size() == 3) {
bool ok = true;
const int a = list[0].toInt(&ok);
if (!ok)
return QString();
const int b = list[1].toInt(&ok);
if (!ok)
return QString();
const int c = list[2].toInt(&ok);
if (!ok)
return QString();
for (const auto& info: checkers::misraCpp2008Rules) {
// cppcheck-suppress useStlAlgorithm
if (info.a == a && info.b == b && info.c == c)
return info.classification;
}
}
}
else if (reportType == ReportType::misraCpp2023) {
QStringList list = guideline.split(".");
if (list.size() == 3) {
bool ok = true;
const int a = list[0].toInt(&ok);
if (!ok)
return QString();
const int b = list[1].toInt(&ok);
if (!ok)
return QString();
const int c = list[2].toInt(&ok);
if (!ok)
return QString();
for (const auto& info: checkers::misraCpp2023Rules) {
// cppcheck-suppress useStlAlgorithm
if (info.a == a && info.b == b && info.c == c)
return info.classification;
}
}
}
return QString();
return QString::fromStdString(getClassification(guideline.toStdString(), reportType));
}

static Severity getSeverityFromClassification(const QString &c) {
Expand Down Expand Up @@ -262,26 +167,7 @@ void ResultsTree::keyPressEvent(QKeyEvent *event)
void ResultsTree::setReportType(ReportType reportType) {
mReportType = reportType;

auto readIdMapping = [this](const std::vector<checkers::IdMapping>& 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 = createGuidelineMapping(reportType);

for (int i = 0; i < mModel.rowCount(); ++i) {
const QStandardItem *fileItem = mModel.item(i, COLUMN_FILE);
Expand Down
2 changes: 1 addition & 1 deletion gui/resultstree.h
Original file line number Diff line number Diff line change
Expand Up @@ -540,7 +540,7 @@ protected slots:

ReportType mReportType = ReportType::normal;

QMap<QString,QString> mGuideline;
std::map<std::string, std::string> mGuideline;
};
/// @}
#endif // RESULTSTREE_H
2 changes: 1 addition & 1 deletion gui/resultsview.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

#include "report.h"
#include "showtypes.h"
#include "common.h"

#include <cstdint>

Expand All @@ -39,7 +40,6 @@ class QPrinter;
class QSettings;
class CheckStatistics;
class QPoint;
enum class ReportType : std::uint8_t;
namespace Ui {
class ResultsView;
}
Expand Down
19 changes: 17 additions & 2 deletions gui/test/resultstree/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ qt_wrap_cpp(test-resultstree_SRC
${CMAKE_SOURCE_DIR}/gui/threadhandler.h
${CMAKE_SOURCE_DIR}/gui/threadresult.h
)
if(USE_BUNDLED_TINYXML2)
list(APPEND test-resultstree_SRC $<TARGET_OBJECTS:tinyxml2_objs>)
endif()
list(APPEND test-resultstree_SRC $<TARGET_OBJECTS:simplecpp_objs> $<TARGET_OBJECTS:cppcheck-core>)
add_custom_target(build-resultstree-deps SOURCES ${test-resultstree_SRC})
add_dependencies(gui-build-deps build-resultstree-deps)
add_executable(test-resultstree
Expand All @@ -16,12 +20,23 @@ add_executable(test-resultstree
${CMAKE_SOURCE_DIR}/gui/showtypes.cpp
${CMAKE_SOURCE_DIR}/gui/report.cpp
${CMAKE_SOURCE_DIR}/gui/xmlreportv2.cpp
${CMAKE_SOURCE_DIR}/lib/checkers.cpp
${CMAKE_SOURCE_DIR}/lib/checkersidmapping.cpp
)
target_include_directories(test-resultstree PRIVATE ${CMAKE_SOURCE_DIR}/gui ${CMAKE_SOURCE_DIR}/lib)
target_externals_include_directories(test-resultstree PRIVATE ${CMAKE_SOURCE_DIR}/externals/simplecpp)
if(USE_BUNDLED_TINYXML2)
target_externals_include_directories(test-resultstree PRIVATE ${PROJECT_SOURCE_DIR}/externals/tinyxml2/)
else()
target_include_directories(test-resultstree SYSTEM PRIVATE ${tinyxml2_INCLUDE_DIRS})
endif()
if (HAVE_RULES)
target_link_libraries(test-resultstree ${PCRE_LIBRARY})
target_include_directories(test-resultstree SYSTEM PRIVATE ${PCRE_INCLUDE})
endif()
target_compile_definitions(test-resultstree PRIVATE SRCDIR="${CMAKE_CURRENT_SOURCE_DIR}")
target_link_libraries(test-resultstree ${QT_CORE_LIB} ${QT_GUI_LIB} ${QT_WIDGETS_LIB} ${QT_TEST_LIB})
if(tinyxml2_FOUND AND NOT USE_BUNDLED_TINYXML2)
target_link_libraries(test-resultstree ${tinyxml2_LIBRARIES})
endif()

if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
# Q_UNUSED() in generated code
Expand Down
21 changes: 0 additions & 21 deletions gui/test/resultstree/testresultstree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,6 @@ void ProjectFile::setWarningTags(std::size_t /*unused*/, const QString& /*unused
bool ProjectFile::write(const QString & /*unused*/) {
return true;
}
std::string severityToString(Severity severity) {
return std::to_string((int)severity);
}
ApplicationList::ApplicationList(QObject *parent) : QObject(parent) {}
ApplicationList::~ApplicationList() = default;
int ApplicationList::getApplicationCount() const {
Expand Down Expand Up @@ -122,24 +119,6 @@ void ThreadResult::reportErr(const ErrorMessage & /*unused*/) {
throw 1;
}

// Mock LIB...
bool Path::isHeader(std::string const& /*unused*/) {
return false;
}
const std::set<std::string> ErrorLogger::mCriticalErrorIds;
std::string ErrorMessage::FileLocation::getfile(bool /*unused*/) const {
return std::string();
}
const char* CppCheck::version() {
return "1.0";
}
std::pair<std::string, std::string> Settings::getNameAndVersion(const std::string& /*unused*/) {
throw 1;
}
Severity severityFromString(const std::string& severity) {
return (Severity)std::stoi(severity);
}

// Test...

void TestResultsTree::test1() const
Expand Down
Loading
Loading