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 #12411 (GUI: product name and version in xml) #5947

Merged
merged 2 commits into from
Feb 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 3 additions & 3 deletions gui/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1166,7 +1166,7 @@ void MainWindow::analysisDone()
if (QDir(buildDir).exists()) {
mUI->mResults->saveStatistics(buildDir + "/statistics.txt");
mUI->mResults->updateFromOldReport(buildDir + "/lastResults.xml");
mUI->mResults->save(buildDir + "/lastResults.xml", Report::XMLV2);
mUI->mResults->save(buildDir + "/lastResults.xml", Report::XMLV2, mCppcheckCfgProductName);
}
}

Expand Down Expand Up @@ -1564,7 +1564,7 @@ void MainWindow::save()
type = Report::CSV;
}

mUI->mResults->save(selectedFile, type);
mUI->mResults->save(selectedFile, type, mCppcheckCfgProductName);
setPath(SETTINGS_LAST_RESULT_PATH, selectedFile);
}
}
Expand All @@ -1585,7 +1585,7 @@ void MainWindow::complianceReport()
tempResults.open();
tempResults.close();

mUI->mResults->save(tempResults.fileName(), Report::XMLV2);
mUI->mResults->save(tempResults.fileName(), Report::XMLV2, mCppcheckCfgProductName);

ComplianceReportDialog dlg(mProjectFile, tempResults.fileName());
dlg.exec();
Expand Down
2 changes: 1 addition & 1 deletion gui/resultstree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1231,7 +1231,7 @@ static int indexOf(const QList<ErrorItem> &list, const ErrorItem &item)
void ResultsTree::updateFromOldReport(const QString &filename)
{
QList<ErrorItem> oldErrors;
XmlReportV2 oldReport(filename);
XmlReportV2 oldReport(filename, QString());
if (oldReport.open()) {
oldErrors = oldReport.read();
oldReport.close();
Expand Down
6 changes: 3 additions & 3 deletions gui/resultsview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ void ResultsView::updateFromOldReport(const QString &filename) const
mUI->mTree->updateFromOldReport(filename);
}

void ResultsView::save(const QString &filename, Report::Type type) const
void ResultsView::save(const QString &filename, Report::Type type, const QString& productName) const
{
Report *report = nullptr;

Expand All @@ -216,7 +216,7 @@ void ResultsView::save(const QString &filename, Report::Type type) const
report = new TxtReport(filename);
break;
case Report::XMLV2:
report = new XmlReportV2(filename);
report = new XmlReportV2(filename, productName);
break;
}

Expand Down Expand Up @@ -408,7 +408,7 @@ void ResultsView::readErrorsXml(const QString &filename)
return;
}

XmlReportV2 report(filename);
XmlReportV2 report(filename, QString());
QList<ErrorItem> errors;
if (report.open()) {
errors = report.read();
Expand Down
3 changes: 2 additions & 1 deletion gui/resultsview.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,9 @@ class ResultsView : public QWidget {
*
* @param filename Filename to save results to
* @param type Type of the report.
* @param productName Custom product name
*/
void save(const QString &filename, Report::Type type) const;
void save(const QString &filename, Report::Type type, const QString& productName) const;

/**
* @brief Update results from old report (tag, sinceDate)
Expand Down
2 changes: 1 addition & 1 deletion gui/test/xmlreportv2/testxmlreportv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
void TestXmlReportV2::readXml() const
{
const QString filepath(QString(SRCDIR) + "/../data/xmlfiles/xmlreport_v2.xml");
XmlReportV2 report(filepath);
XmlReportV2 report(filepath, QString());
QVERIFY(report.open());
QList<ErrorItem> errors = report.read();
QCOMPARE(errors.size(), 6);
Expand Down
12 changes: 10 additions & 2 deletions gui/xmlreportv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,12 @@ static const QString IdAttribute = "id";
static const QString SeverityAttribute = "severity";
static const QString MsgAttribute = "msg";
static const QString VersionAttribute = "version";
static const QString ProductNameAttribute = "product-name";
static const QString VerboseAttribute = "verbose";

XmlReportV2::XmlReportV2(const QString &filename) :
XmlReportV2::XmlReportV2(const QString &filename, QString productName) :
XmlReport(filename),
mProductName(std::move(productName)),
mXmlReader(nullptr),
mXmlWriter(nullptr)
{}
Expand Down Expand Up @@ -87,12 +89,18 @@ bool XmlReportV2::open()

void XmlReportV2::writeHeader()
{
const auto nameAndVersion = Settings::getNameAndVersion(mProductName.toStdString());
const QString name = QString::fromStdString(nameAndVersion.first);
const QString version = nameAndVersion.first.empty() ? CppCheck::version() : QString::fromStdString(nameAndVersion.second);

mXmlWriter->setAutoFormatting(true);
mXmlWriter->writeStartDocument();
mXmlWriter->writeStartElement(ResultElementName);
mXmlWriter->writeAttribute(VersionAttribute, QString::number(2));
mXmlWriter->writeStartElement(CppcheckElementName);
mXmlWriter->writeAttribute(VersionAttribute, QString(CppCheck::version()));
if (!name.isEmpty())
mXmlWriter->writeAttribute(ProductNameAttribute, name);
mXmlWriter->writeAttribute(VersionAttribute, version);
mXmlWriter->writeEndElement();
mXmlWriter->writeStartElement(ErrorsElementName);
}
Expand Down
5 changes: 4 additions & 1 deletion gui/xmlreportv2.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class QXmlStreamWriter;
*/
class XmlReportV2 : public XmlReport {
public:
explicit XmlReportV2(const QString &filename);
explicit XmlReportV2(const QString &filename, QString productName);
~XmlReportV2() override;

/**
Expand Down Expand Up @@ -82,6 +82,9 @@ class XmlReportV2 : public XmlReport {
ErrorItem readError(const QXmlStreamReader *reader);

private:
/** Product name read from cppcheck.cfg */
const QString mProductName;

/**
* @brief XML stream reader for reading the report in XML format.
*/
Expand Down
11 changes: 3 additions & 8 deletions lib/errorlogger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -425,14 +425,9 @@ void ErrorMessage::deserialize(const std::string &data)

std::string ErrorMessage::getXMLHeader(std::string productName)
{
std::string version = CppCheck::version();
if (!productName.empty() && std::isdigit(productName.back())) {
const std::string::size_type pos = productName.find_last_not_of(".0123456789");
if (pos > 1 && pos != std::string::npos && productName[pos] == ' ') {
version = productName.substr(pos+1);
productName.erase(pos);
}
}
const auto nameAndVersion = Settings::getNameAndVersion(productName);
productName = nameAndVersion.first;
const std::string version = nameAndVersion.first.empty() ? CppCheck::version() : nameAndVersion.second;

tinyxml2::XMLPrinter printer;

Expand Down
22 changes: 22 additions & 0 deletions lib/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,28 @@ std::string Settings::loadCppcheckCfg()
return "";
}

std::pair<std::string, std::string> Settings::getNameAndVersion(const std::string& productName) {
if (productName.empty())
return {};
const std::string::size_type pos1 = productName.rfind(' ');
if (pos1 == std::string::npos)
return {};
if (pos1 + 2 >= productName.length())
return {};
for (auto pos2 = pos1 + 1; pos2 < productName.length(); ++pos2) {
const char c = productName[pos2];
const char prev = productName[pos2-1];
if (std::isdigit(c))
continue;
if (c == '.' && std::isdigit(prev))
continue;
if (c == 's' && pos2 + 1 == productName.length() && std::isdigit(prev))
continue;
return {};
}
return {productName.substr(0, pos1), productName.substr(pos1+1)};
}

std::string Settings::parseEnabled(const std::string &str, std::tuple<SimpleEnableGroup<Severity>, SimpleEnableGroup<Checks>> &groups)
{
// Enable parameters may be comma separated...
Expand Down
2 changes: 2 additions & 0 deletions lib/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ class CPPCHECKLIB WARN_UNUSED Settings {

std::string loadCppcheckCfg();

static std::pair<std::string, std::string> getNameAndVersion(const std::string& productName);

/** @brief addons, either filename of python/json file or json data */
std::unordered_set<std::string> addons;

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

void simpleEnableGroup() const {
Expand Down Expand Up @@ -238,6 +239,21 @@ class TestSettings : public TestFixture {
ASSERT_EQUALS(true, s.safety);
}
}

void getNameAndVersion() const
{
{
const auto nameVersion = Settings::getNameAndVersion("Cppcheck Premium 12.3.4");
ASSERT_EQUALS("Cppcheck Premium", nameVersion.first);
ASSERT_EQUALS("12.3.4", nameVersion.second);
}

{
const auto nameVersion = Settings::getNameAndVersion("Cppcheck Premium 12.3.4s");
ASSERT_EQUALS("Cppcheck Premium", nameVersion.first);
ASSERT_EQUALS("12.3.4s", nameVersion.second);
}
}
};

REGISTER_TEST(TestSettings)
Loading