diff --git a/gui/csvreport.cpp b/gui/csvreport.cpp index 9f82544cf..bca3ce80d 100644 --- a/gui/csvreport.cpp +++ b/gui/csvreport.cpp @@ -58,8 +58,8 @@ void CsvReport::WriteError(const ErrorItem &error) gui/test.cpp,23,error,Mismatching allocation and deallocation: k */ - const QString file = QDir::toNativeSeparators(error.files[error.files.size() - 1]); - QString line = QString("%1,%2,").arg(file).arg(error.lines[error.lines.size() - 1]); + const QString file = QDir::toNativeSeparators(error.errorPath.back().file); + QString line = QString("%1,%2,").arg(file).arg(error.errorPath.back().line); line += QString("%1,%2").arg(GuiSeverity::toString(error.severity)).arg(error.summary); mTxtWriter << line << endl; diff --git a/gui/erroritem.cpp b/gui/erroritem.cpp index 5af2e0f29..ce305440a 100644 --- a/gui/erroritem.cpp +++ b/gui/erroritem.cpp @@ -18,34 +18,55 @@ #include "erroritem.h" +QErrorPathItem::QErrorPathItem(const ErrorLogger::ErrorMessage::FileLocation &loc) + : file(QString::fromStdString(loc.getfile(false))) + , line(loc.line) + , col(loc.col) + , info(QString::fromStdString(loc.getinfo())) +{ +} + +QErrorPathItem::QErrorPathItem(const QErrorPathItem &e) + : file(e.file) + , line(e.line) + , col(e.col) + , info(e.info) +{ +} + ErrorItem::ErrorItem() : severity(Severity::none) , inconclusive(false) + , cwe(-1) { } -ErrorItem::ErrorItem(const ErrorLine &line) - : file(line.file) - , files(line.file) - , errorId(line.errorId) - , severity(line.severity) - , inconclusive(line.inconclusive) - , summary(line.summary) - , message(line.message) +ErrorItem::ErrorItem(const ErrorLogger::ErrorMessage &errmsg) + : errorId(QString::fromStdString(errmsg._id)) + , severity(errmsg._severity) + , inconclusive(errmsg._inconclusive) + , summary(QString::fromStdString(errmsg.shortMessage())) + , message(QString::fromStdString(errmsg.verboseMessage())) + , cwe(errmsg._cwe.id) { - lines.append(line.line); + for (std::list::const_iterator loc = errmsg._callStack.begin(); + loc != errmsg._callStack.end(); + ++loc) { + errorPath << QErrorPathItem(*loc); + } } + QString ErrorItem::ToString() const { - QString str = file + " - " + errorId + " - "; + QString str = errorPath.back().file + " - " + errorId + " - "; if (inconclusive) str += "inconclusive "; str += GuiSeverity::toString(severity) +"\n"; str += summary + "\n"; str += message + "\n"; - for (int i = 0; i < files.size(); i++) { - str += " " + files[i] + ": " + QString::number(lines[i]) + "\n"; + for (int i = 0; i < errorPath.size(); i++) { + str += " " + errorPath[i].file + ": " + QString::number(errorPath[i].line) + "\n"; } return str; } diff --git a/gui/erroritem.h b/gui/erroritem.h index 065bff932..3b3cb648e 100644 --- a/gui/erroritem.h +++ b/gui/erroritem.h @@ -46,6 +46,20 @@ public: } }; +/** +* @brief A class containing data for one error path item +*/ +class QErrorPathItem { +public: + QErrorPathItem() : line(0), col(-1) {} + explicit QErrorPathItem(const ErrorLogger::ErrorMessage::FileLocation &loc); + explicit QErrorPathItem(const QErrorPathItem &e); + QString file; + unsigned int line; + int col; + QString info; +}; + /** * @brief A class containing error data for one error. * @@ -57,7 +71,7 @@ public: class ErrorItem { public: ErrorItem(); - explicit ErrorItem(const ErrorLine &line); + explicit ErrorItem(const ErrorLogger::ErrorMessage &errmsg); /** * @brief Convert error item to string. @@ -65,15 +79,14 @@ public: */ QString ToString() const; - QString file; - QStringList files; QString file0; - QList lines; QString errorId; Severity::SeverityType severity; bool inconclusive; QString summary; QString message; + int cwe; + QList errorPath; }; Q_DECLARE_METATYPE(ErrorItem); @@ -84,8 +97,8 @@ Q_DECLARE_METATYPE(ErrorItem); class ErrorLine { public: QString file; - QString file0; unsigned int line; + QString file0; QString errorId; bool inconclusive; Severity::SeverityType severity; diff --git a/gui/printablereport.cpp b/gui/printablereport.cpp index e85dac8c9..5e0a918b8 100644 --- a/gui/printablereport.cpp +++ b/gui/printablereport.cpp @@ -45,8 +45,8 @@ void PrintableReport::WriteFooter() void PrintableReport::WriteError(const ErrorItem &error) { - const QString file = QDir::toNativeSeparators(error.files[error.files.size() - 1]); - QString line = QString("%1,%2,").arg(file).arg(error.lines[error.lines.size() - 1]); + const QString file = QDir::toNativeSeparators(error.errorPath.back().file); + QString line = QString("%1,%2,").arg(file).arg(error.errorPath.back().line); line += QString("%1,%2").arg(GuiSeverity::toString(error.severity)).arg(error.summary); mFormattedReport += line; diff --git a/gui/resultstree.cpp b/gui/resultstree.cpp index 63f9a600e..6551de02e 100644 --- a/gui/resultstree.cpp +++ b/gui/resultstree.cpp @@ -114,11 +114,11 @@ QStandardItem *ResultsTree::CreateLineNumberItem(const QString &linenumber) bool ResultsTree::AddErrorItem(const ErrorItem &item) { - if (item.files.isEmpty()) { + if (item.errorPath.isEmpty()) { return false; } - QString realfile = StripPath(item.files[0], false); + QString realfile = StripPath(item.errorPath.back().file, false); if (realfile.isEmpty()) { realfile = tr("Undefined file"); @@ -130,7 +130,7 @@ bool ResultsTree::AddErrorItem(const ErrorItem &item) if (!hide && !mFilter.isEmpty()) { if (!item.summary.contains(mFilter, Qt::CaseInsensitive) && !item.message.contains(mFilter, Qt::CaseInsensitive) && - !item.file.contains(mFilter, Qt::CaseInsensitive) && + !item.errorPath.back().file.contains(mFilter, Qt::CaseInsensitive) && !item.errorId.contains(mFilter, Qt::CaseInsensitive)) { hide = true; } @@ -143,15 +143,15 @@ bool ResultsTree::AddErrorItem(const ErrorItem &item) ErrorLine line; line.file = realfile; + line.line = item.errorPath.back().line; line.errorId = item.errorId; line.inconclusive = item.inconclusive; - line.line = item.lines[0]; line.summary = item.summary; line.message = item.message; line.severity = item.severity; //Create the base item for the error and ensure it has a proper //file item as a parent - QStandardItem* fileItem = EnsureFileItem(item.files[0], item.file0, hide); + QStandardItem* fileItem = EnsureFileItem(item.errorPath.back().file, item.file0, hide); QStandardItem* stditem = AddBacktraceFiles(fileItem, line, hide, @@ -167,34 +167,38 @@ bool ResultsTree::AddErrorItem(const ErrorItem &item) data["severity"] = ShowTypes::SeverityToShowType(item.severity); data["summary"] = item.summary; data["message"] = item.message; - data["file"] = item.files[0]; - data["line"] = item.lines[0]; + data["file"] = item.errorPath.back().file; + data["line"] = item.errorPath.back().line; data["id"] = item.errorId; data["inconclusive"] = item.inconclusive; data["file0"] = StripPath(item.file0, true); stditem->setData(QVariant(data)); //Add backtrace files as children - for (int i = 1; i < item.files.size(); i++) { - line.file = StripPath(item.files[i], false); - line.line = item.lines[i]; - QStandardItem *child_item; - child_item = AddBacktraceFiles(stditem, - line, - hide, - ":images/go-down.png", - true); + if (item.errorPath.size() > 1U) { + for (int i = 0; i < item.errorPath.size(); i++) { + const QErrorPathItem &e = item.errorPath[i]; + line.file = e.file; + line.line = e.line; + line.message = line.summary = e.info; + QStandardItem *child_item; + child_item = AddBacktraceFiles(stditem, + line, + hide, + ":images/go-down.png", + true); - //Add user data to that item - QMap child_data; - child_data["severity"] = ShowTypes::SeverityToShowType(line.severity); - child_data["summary"] = line.summary; - child_data["message"] = line.message; - child_data["file"] = item.files[i]; - child_data["line"] = line.line; - child_data["id"] = line.errorId; - child_data["inconclusive"] = line.inconclusive; - child_item->setData(QVariant(child_data)); + //Add user data to that item + QMap child_data; + child_data["severity"] = ShowTypes::SeverityToShowType(line.severity); + child_data["summary"] = line.summary; + child_data["message"] = line.message; + child_data["file"] = e.file; + child_data["line"] = e.line; + child_data["id"] = line.errorId; + child_data["inconclusive"] = line.inconclusive; + child_item->setData(QVariant(child_data)); + } } // Partially refresh the tree: Unhide file item if necessary @@ -209,7 +213,6 @@ QStandardItem *ResultsTree::AddBacktraceFiles(QStandardItem *parent, const bool hide, const QString &icon, bool childOfMessage) - { if (!parent) { return 0; @@ -217,29 +220,14 @@ QStandardItem *ResultsTree::AddBacktraceFiles(QStandardItem *parent, QList list; // Ensure shown path is with native separators - const QString file = QDir::toNativeSeparators(item.file); - list << CreateNormalItem(file); - if (childOfMessage) - list << CreateNormalItem(""); - else { - const QString severity = SeverityToTranslatedString(item.severity); - list << CreateNormalItem(severity); - } - list << CreateLineNumberItem(QString("%1").arg(item.line)); - if (childOfMessage) - list << CreateNormalItem(""); - else - list << CreateNormalItem(item.errorId); - if (childOfMessage) - list << CreateNormalItem(""); - else - list << CreateCheckboxItem(item.inconclusive); + list << CreateNormalItem(QDir::toNativeSeparators(item.file)) + << CreateNormalItem(childOfMessage ? tr("note") : SeverityToTranslatedString(item.severity)) + << CreateLineNumberItem(QString::number(item.line)) + << CreateNormalItem(childOfMessage ? QString() : item.errorId) + << (childOfMessage ? CreateNormalItem(QString()) : CreateCheckboxItem(item.inconclusive)) + << CreateNormalItem(item.summary); //TODO message has parameter names so we'll need changes to the core //cppcheck so we can get proper translations - if (childOfMessage) - list << CreateNormalItem(""); - else - list << CreateNormalItem(item.summary.toLatin1()); // Check for duplicate rows and don't add them if found for (int i = 0; i < parent->rowCount(); i++) { @@ -1014,11 +1002,14 @@ void ResultsTree::SaveErrors(Report *report, QStandardItem *item) const item.errorId = data["id"].toString(); item.inconclusive = data["inconclusive"].toBool(); item.file0 = data["file0"].toString(); - QString file = StripPath(data["file"].toString(), true); - unsigned int line = data["line"].toUInt(); - item.files << file; - item.lines << line; + if (error->rowCount() == 0) { + QErrorPathItem e; + e.file = StripPath(data["file"].toString(), true); + e.line = data["line"].toUInt(); + e.info = data["message"].toString(); + item.errorPath << e; + } for (int j = 0; j < error->rowCount(); j++) { QStandardItem *child_error = error->child(j, 0); @@ -1027,11 +1018,11 @@ void ResultsTree::SaveErrors(Report *report, QStandardItem *item) const //Convert it to QVariantMap QVariantMap child_data = child_userdata.toMap(); - file = StripPath(child_data["file"].toString(), true); - line = child_data["line"].toUInt(); - - item.files << file; - item.lines << line; + QErrorPathItem e; + e.file = StripPath(child_data["file"].toString(), true); + e.line = child_data["line"].toUInt(); + e.info = child_data["message"].toString(); + item.errorPath << e; } report->WriteError(item); diff --git a/gui/threadresult.cpp b/gui/threadresult.cpp index de3b5b05d..97b68514e 100644 --- a/gui/threadresult.cpp +++ b/gui/threadresult.cpp @@ -60,28 +60,7 @@ void ThreadResult::FileChecked(const QString &file) void ThreadResult::reportErr(const ErrorLogger::ErrorMessage &msg) { QMutexLocker locker(&mutex); - - QList lines; - QStringList files; - - for (std::list::const_iterator tok = msg._callStack.begin(); - tok != msg._callStack.end(); - ++tok) { - files << QString::fromStdString((*tok).getfile(false)); - lines << (*tok).line; - } - - ErrorItem item; - item.file = QString::fromStdString(callStackToString(msg._callStack)); - item.files = files; - item.errorId = QString::fromStdString(msg._id); - item.lines = lines; - item.summary = QString::fromStdString(msg.shortMessage()); - item.message = QString::fromStdString(msg.verboseMessage()); - item.severity = msg._severity; - item.inconclusive = msg._inconclusive; - item.file0 = QString::fromStdString(msg.file0); - + const ErrorItem item(msg); if (msg._severity != Severity::debug) emit Error(item); else diff --git a/gui/txtreport.cpp b/gui/txtreport.cpp index 362862501..a71e5d56c 100644 --- a/gui/txtreport.cpp +++ b/gui/txtreport.cpp @@ -56,14 +56,14 @@ void TxtReport::WriteError(const ErrorItem &error) QString line; - for (int i = 0; i < error.lines.size(); i++) { - const QString file = QDir::toNativeSeparators(error.files[i]); - line += QString("[%1:%2]").arg(file).arg(error.lines[i]); - if (i < error.lines.size() - 1 && !error.lines.isEmpty()) { + for (int i = 0; i < error.errorPath.size(); i++) { + const QString file = QDir::toNativeSeparators(error.errorPath[i].file); + line += QString("[%1:%2]").arg(file).arg(error.errorPath[i].line); + if (i < error.errorPath.size() - 1 && !error.errorPath.isEmpty()) { line += " -> "; } - if (i == error.lines.size() - 1) { + if (i == error.errorPath.size() - 1) { line += ": "; } } diff --git a/gui/xmlreportv1.cpp b/gui/xmlreportv1.cpp index d041936d4..de79b01a2 100644 --- a/gui/xmlreportv1.cpp +++ b/gui/xmlreportv1.cpp @@ -92,10 +92,10 @@ void XmlReportV1::WriteError(const ErrorItem &error) return; mXmlWriter->writeStartElement(ErrorElementName); - QString file = QDir::toNativeSeparators(error.files[error.files.size() - 1]); + QString file = QDir::toNativeSeparators(error.errorPath.back().file); file = XmlReport::quoteMessage(file); mXmlWriter->writeAttribute(FilenameAttribute, file); - const QString line = QString::number(error.lines[error.lines.size() - 1]); + const QString line = QString::number(error.errorPath.back().line); mXmlWriter->writeAttribute(LineAttribute, line); mXmlWriter->writeAttribute(IdAttribute, error.errorId); @@ -155,10 +155,10 @@ ErrorItem XmlReportV1::ReadError(QXmlStreamReader *reader) QXmlStreamAttributes attribs = reader->attributes(); QString file = attribs.value("", FilenameAttribute).toString(); file = XmlReport::unquoteMessage(file); - item.file = file; - item.files.push_back(file); - const int line = attribs.value("", LineAttribute).toString().toUInt(); - item.lines.push_back(line); + QErrorPathItem e; + e.file = file; + e.line = attribs.value("", LineAttribute).toString().toUInt(); + item.errorPath << e; item.errorId = attribs.value("", IdAttribute).toString(); item.severity = GuiSeverity::fromString(attribs.value("", SeverityAttribute).toString()); diff --git a/gui/xmlreportv2.cpp b/gui/xmlreportv2.cpp index 31e6ce6c9..8f0663fa2 100644 --- a/gui/xmlreportv2.cpp +++ b/gui/xmlreportv2.cpp @@ -33,8 +33,12 @@ static const char CppcheckElementName[] = "cppcheck"; static const char ErrorElementName[] = "error"; static const char ErrorsElementName[] = "errors"; static const char LocationElementName[] = "location"; +static const char ColAttribute[] = "col"; +static const char CWEAttribute[] = "cwe"; static const char FilenameAttribute[] = "file"; static const char IncludedFromFilenameAttribute[] = "file0"; +static const char InconclusiveAttribute[] = "inconclusive"; +static const char InfoAttribute[] = "info"; static const char LineAttribute[] = "line"; static const char IdAttribute[] = "id"; static const char SeverityAttribute[] = "severity"; @@ -103,10 +107,6 @@ void XmlReportV2::WriteError(const ErrorItem &error) */ - // Don't write inconclusive errors to XML V2 until we decide the format - if (error.inconclusive) - return; - mXmlWriter->writeStartElement(ErrorElementName); mXmlWriter->writeAttribute(IdAttribute, error.errorId); @@ -116,18 +116,24 @@ void XmlReportV2::WriteError(const ErrorItem &error) mXmlWriter->writeAttribute(MsgAttribute, summary); const QString message = XmlReport::quoteMessage(error.message); mXmlWriter->writeAttribute(VerboseAttribute, message); + if (error.inconclusive) + mXmlWriter->writeAttribute(InconclusiveAttribute, "true"); + if (error.cwe > 0) + mXmlWriter->writeAttribute(CWEAttribute, QString::number(error.cwe)); - for (int i = 0; i < error.files.count(); i++) { + for (int i = error.errorPath.count() - 1; i >= 0; i--) { mXmlWriter->writeStartElement(LocationElementName); - QString file = QDir::toNativeSeparators(error.files[i]); + QString file = QDir::toNativeSeparators(error.errorPath[i].file); if (!error.file0.isEmpty() && file != error.file0) { mXmlWriter->writeAttribute(IncludedFromFilenameAttribute, quoteMessage(error.file0)); } - file = XmlReport::quoteMessage(file); - mXmlWriter->writeAttribute(FilenameAttribute, file); - const QString line = QString::number(error.lines[i]); - mXmlWriter->writeAttribute(LineAttribute, line); + mXmlWriter->writeAttribute(FilenameAttribute, XmlReport::quoteMessage(file)); + mXmlWriter->writeAttribute(LineAttribute, QString::number(error.errorPath[i].line)); + if (error.errorPath[i].col > 0) + mXmlWriter->writeAttribute(ColAttribute, QString::number(error.errorPath[i].col)); + if (error.errorPath.count() > 1) + mXmlWriter->writeAttribute(InfoAttribute, XmlReport::quoteMessage(error.errorPath[i].info)); mXmlWriter->writeEndElement(); } @@ -199,6 +205,10 @@ ErrorItem XmlReportV2::ReadError(QXmlStreamReader *reader) item.summary = XmlReport::unquoteMessage(summary); const QString message = attribs.value("", VerboseAttribute).toString(); item.message = XmlReport::unquoteMessage(message); + if (attribs.hasAttribute("", InconclusiveAttribute)) + item.inconclusive = true; + if (attribs.hasAttribute("", CWEAttribute)) + item.cwe = attribs.value("", CWEAttribute).toString().toInt(); } bool errorRead = false; @@ -209,16 +219,17 @@ ErrorItem XmlReportV2::ReadError(QXmlStreamReader *reader) // Read location element from inside error element if (mXmlReader->name() == LocationElementName) { QXmlStreamAttributes attribs = mXmlReader->attributes(); - QString file = attribs.value("", FilenameAttribute).toString(); QString file0 = attribs.value("", IncludedFromFilenameAttribute).toString(); - file = XmlReport::unquoteMessage(file); - if (item.file.isEmpty()) - item.file = file; if (!file0.isEmpty()) item.file0 = XmlReport::unquoteMessage(file0); - item.files.push_back(file); - const int line = attribs.value("", LineAttribute).toString().toUInt(); - item.lines.push_back(line); + QErrorPathItem loc; + loc.file = XmlReport::unquoteMessage(attribs.value("", FilenameAttribute).toString()); + loc.line = attribs.value("", LineAttribute).toString().toUInt(); + if (attribs.hasAttribute("", ColAttribute)) + loc.col = attribs.value("", ColAttribute).toString().toInt(); + if (attribs.hasAttribute("", InfoAttribute)) + loc.info = XmlReport::unquoteMessage(attribs.value("", InfoAttribute).toString()); + item.errorPath.push_front(loc); } break;