GUI: Update results

This commit is contained in:
Daniel Marjamäki 2017-05-21 08:25:55 +02:00
parent 94d39f6e91
commit a20fb4f36a
9 changed files with 143 additions and 128 deletions

View File

@ -58,8 +58,8 @@ void CsvReport::WriteError(const ErrorItem &error)
gui/test.cpp,23,error,Mismatching allocation and deallocation: k gui/test.cpp,23,error,Mismatching allocation and deallocation: k
*/ */
const QString file = QDir::toNativeSeparators(error.files[error.files.size() - 1]); const QString file = QDir::toNativeSeparators(error.errorPath.back().file);
QString line = QString("%1,%2,").arg(file).arg(error.lines[error.lines.size() - 1]); QString line = QString("%1,%2,").arg(file).arg(error.errorPath.back().line);
line += QString("%1,%2").arg(GuiSeverity::toString(error.severity)).arg(error.summary); line += QString("%1,%2").arg(GuiSeverity::toString(error.severity)).arg(error.summary);
mTxtWriter << line << endl; mTxtWriter << line << endl;

View File

@ -18,34 +18,55 @@
#include "erroritem.h" #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() ErrorItem::ErrorItem()
: severity(Severity::none) : severity(Severity::none)
, inconclusive(false) , inconclusive(false)
, cwe(-1)
{ {
} }
ErrorItem::ErrorItem(const ErrorLine &line) ErrorItem::ErrorItem(const ErrorLogger::ErrorMessage &errmsg)
: file(line.file) : errorId(QString::fromStdString(errmsg._id))
, files(line.file) , severity(errmsg._severity)
, errorId(line.errorId) , inconclusive(errmsg._inconclusive)
, severity(line.severity) , summary(QString::fromStdString(errmsg.shortMessage()))
, inconclusive(line.inconclusive) , message(QString::fromStdString(errmsg.verboseMessage()))
, summary(line.summary) , cwe(errmsg._cwe.id)
, message(line.message)
{ {
lines.append(line.line); for (std::list<ErrorLogger::ErrorMessage::FileLocation>::const_iterator loc = errmsg._callStack.begin();
loc != errmsg._callStack.end();
++loc) {
errorPath << QErrorPathItem(*loc);
}
} }
QString ErrorItem::ToString() const QString ErrorItem::ToString() const
{ {
QString str = file + " - " + errorId + " - "; QString str = errorPath.back().file + " - " + errorId + " - ";
if (inconclusive) if (inconclusive)
str += "inconclusive "; str += "inconclusive ";
str += GuiSeverity::toString(severity) +"\n"; str += GuiSeverity::toString(severity) +"\n";
str += summary + "\n"; str += summary + "\n";
str += message + "\n"; str += message + "\n";
for (int i = 0; i < files.size(); i++) { for (int i = 0; i < errorPath.size(); i++) {
str += " " + files[i] + ": " + QString::number(lines[i]) + "\n"; str += " " + errorPath[i].file + ": " + QString::number(errorPath[i].line) + "\n";
} }
return str; return str;
} }

View File

@ -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. * @brief A class containing error data for one error.
* *
@ -57,7 +71,7 @@ public:
class ErrorItem { class ErrorItem {
public: public:
ErrorItem(); ErrorItem();
explicit ErrorItem(const ErrorLine &line); explicit ErrorItem(const ErrorLogger::ErrorMessage &errmsg);
/** /**
* @brief Convert error item to string. * @brief Convert error item to string.
@ -65,15 +79,14 @@ public:
*/ */
QString ToString() const; QString ToString() const;
QString file;
QStringList files;
QString file0; QString file0;
QList<unsigned int> lines;
QString errorId; QString errorId;
Severity::SeverityType severity; Severity::SeverityType severity;
bool inconclusive; bool inconclusive;
QString summary; QString summary;
QString message; QString message;
int cwe;
QList<QErrorPathItem> errorPath;
}; };
Q_DECLARE_METATYPE(ErrorItem); Q_DECLARE_METATYPE(ErrorItem);
@ -84,8 +97,8 @@ Q_DECLARE_METATYPE(ErrorItem);
class ErrorLine { class ErrorLine {
public: public:
QString file; QString file;
QString file0;
unsigned int line; unsigned int line;
QString file0;
QString errorId; QString errorId;
bool inconclusive; bool inconclusive;
Severity::SeverityType severity; Severity::SeverityType severity;

View File

@ -45,8 +45,8 @@ void PrintableReport::WriteFooter()
void PrintableReport::WriteError(const ErrorItem &error) void PrintableReport::WriteError(const ErrorItem &error)
{ {
const QString file = QDir::toNativeSeparators(error.files[error.files.size() - 1]); const QString file = QDir::toNativeSeparators(error.errorPath.back().file);
QString line = QString("%1,%2,").arg(file).arg(error.lines[error.lines.size() - 1]); QString line = QString("%1,%2,").arg(file).arg(error.errorPath.back().line);
line += QString("%1,%2").arg(GuiSeverity::toString(error.severity)).arg(error.summary); line += QString("%1,%2").arg(GuiSeverity::toString(error.severity)).arg(error.summary);
mFormattedReport += line; mFormattedReport += line;

View File

@ -114,11 +114,11 @@ QStandardItem *ResultsTree::CreateLineNumberItem(const QString &linenumber)
bool ResultsTree::AddErrorItem(const ErrorItem &item) bool ResultsTree::AddErrorItem(const ErrorItem &item)
{ {
if (item.files.isEmpty()) { if (item.errorPath.isEmpty()) {
return false; return false;
} }
QString realfile = StripPath(item.files[0], false); QString realfile = StripPath(item.errorPath.back().file, false);
if (realfile.isEmpty()) { if (realfile.isEmpty()) {
realfile = tr("Undefined file"); realfile = tr("Undefined file");
@ -130,7 +130,7 @@ bool ResultsTree::AddErrorItem(const ErrorItem &item)
if (!hide && !mFilter.isEmpty()) { if (!hide && !mFilter.isEmpty()) {
if (!item.summary.contains(mFilter, Qt::CaseInsensitive) && if (!item.summary.contains(mFilter, Qt::CaseInsensitive) &&
!item.message.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)) { !item.errorId.contains(mFilter, Qt::CaseInsensitive)) {
hide = true; hide = true;
} }
@ -143,15 +143,15 @@ bool ResultsTree::AddErrorItem(const ErrorItem &item)
ErrorLine line; ErrorLine line;
line.file = realfile; line.file = realfile;
line.line = item.errorPath.back().line;
line.errorId = item.errorId; line.errorId = item.errorId;
line.inconclusive = item.inconclusive; line.inconclusive = item.inconclusive;
line.line = item.lines[0];
line.summary = item.summary; line.summary = item.summary;
line.message = item.message; line.message = item.message;
line.severity = item.severity; line.severity = item.severity;
//Create the base item for the error and ensure it has a proper //Create the base item for the error and ensure it has a proper
//file item as a parent //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, QStandardItem* stditem = AddBacktraceFiles(fileItem,
line, line,
hide, hide,
@ -167,34 +167,38 @@ bool ResultsTree::AddErrorItem(const ErrorItem &item)
data["severity"] = ShowTypes::SeverityToShowType(item.severity); data["severity"] = ShowTypes::SeverityToShowType(item.severity);
data["summary"] = item.summary; data["summary"] = item.summary;
data["message"] = item.message; data["message"] = item.message;
data["file"] = item.files[0]; data["file"] = item.errorPath.back().file;
data["line"] = item.lines[0]; data["line"] = item.errorPath.back().line;
data["id"] = item.errorId; data["id"] = item.errorId;
data["inconclusive"] = item.inconclusive; data["inconclusive"] = item.inconclusive;
data["file0"] = StripPath(item.file0, true); data["file0"] = StripPath(item.file0, true);
stditem->setData(QVariant(data)); stditem->setData(QVariant(data));
//Add backtrace files as children //Add backtrace files as children
for (int i = 1; i < item.files.size(); i++) { if (item.errorPath.size() > 1U) {
line.file = StripPath(item.files[i], false); for (int i = 0; i < item.errorPath.size(); i++) {
line.line = item.lines[i]; const QErrorPathItem &e = item.errorPath[i];
QStandardItem *child_item; line.file = e.file;
child_item = AddBacktraceFiles(stditem, line.line = e.line;
line, line.message = line.summary = e.info;
hide, QStandardItem *child_item;
":images/go-down.png", child_item = AddBacktraceFiles(stditem,
true); line,
hide,
":images/go-down.png",
true);
//Add user data to that item //Add user data to that item
QMap<QString, QVariant> child_data; QMap<QString, QVariant> child_data;
child_data["severity"] = ShowTypes::SeverityToShowType(line.severity); child_data["severity"] = ShowTypes::SeverityToShowType(line.severity);
child_data["summary"] = line.summary; child_data["summary"] = line.summary;
child_data["message"] = line.message; child_data["message"] = line.message;
child_data["file"] = item.files[i]; child_data["file"] = e.file;
child_data["line"] = line.line; child_data["line"] = e.line;
child_data["id"] = line.errorId; child_data["id"] = line.errorId;
child_data["inconclusive"] = line.inconclusive; child_data["inconclusive"] = line.inconclusive;
child_item->setData(QVariant(child_data)); child_item->setData(QVariant(child_data));
}
} }
// Partially refresh the tree: Unhide file item if necessary // Partially refresh the tree: Unhide file item if necessary
@ -209,7 +213,6 @@ QStandardItem *ResultsTree::AddBacktraceFiles(QStandardItem *parent,
const bool hide, const bool hide,
const QString &icon, const QString &icon,
bool childOfMessage) bool childOfMessage)
{ {
if (!parent) { if (!parent) {
return 0; return 0;
@ -217,29 +220,14 @@ QStandardItem *ResultsTree::AddBacktraceFiles(QStandardItem *parent,
QList<QStandardItem*> list; QList<QStandardItem*> list;
// Ensure shown path is with native separators // Ensure shown path is with native separators
const QString file = QDir::toNativeSeparators(item.file); list << CreateNormalItem(QDir::toNativeSeparators(item.file))
list << CreateNormalItem(file); << CreateNormalItem(childOfMessage ? tr("note") : SeverityToTranslatedString(item.severity))
if (childOfMessage) << CreateLineNumberItem(QString::number(item.line))
list << CreateNormalItem(""); << CreateNormalItem(childOfMessage ? QString() : item.errorId)
else { << (childOfMessage ? CreateNormalItem(QString()) : CreateCheckboxItem(item.inconclusive))
const QString severity = SeverityToTranslatedString(item.severity); << CreateNormalItem(item.summary);
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);
//TODO message has parameter names so we'll need changes to the core //TODO message has parameter names so we'll need changes to the core
//cppcheck so we can get proper translations //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 // Check for duplicate rows and don't add them if found
for (int i = 0; i < parent->rowCount(); i++) { 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.errorId = data["id"].toString();
item.inconclusive = data["inconclusive"].toBool(); item.inconclusive = data["inconclusive"].toBool();
item.file0 = data["file0"].toString(); item.file0 = data["file0"].toString();
QString file = StripPath(data["file"].toString(), true);
unsigned int line = data["line"].toUInt();
item.files << file; if (error->rowCount() == 0) {
item.lines << line; 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++) { for (int j = 0; j < error->rowCount(); j++) {
QStandardItem *child_error = error->child(j, 0); QStandardItem *child_error = error->child(j, 0);
@ -1027,11 +1018,11 @@ void ResultsTree::SaveErrors(Report *report, QStandardItem *item) const
//Convert it to QVariantMap //Convert it to QVariantMap
QVariantMap child_data = child_userdata.toMap(); QVariantMap child_data = child_userdata.toMap();
file = StripPath(child_data["file"].toString(), true); QErrorPathItem e;
line = child_data["line"].toUInt(); e.file = StripPath(child_data["file"].toString(), true);
e.line = child_data["line"].toUInt();
item.files << file; e.info = child_data["message"].toString();
item.lines << line; item.errorPath << e;
} }
report->WriteError(item); report->WriteError(item);

View File

@ -60,28 +60,7 @@ void ThreadResult::FileChecked(const QString &file)
void ThreadResult::reportErr(const ErrorLogger::ErrorMessage &msg) void ThreadResult::reportErr(const ErrorLogger::ErrorMessage &msg)
{ {
QMutexLocker locker(&mutex); QMutexLocker locker(&mutex);
const ErrorItem item(msg);
QList<unsigned int> lines;
QStringList files;
for (std::list<ErrorLogger::ErrorMessage::FileLocation>::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);
if (msg._severity != Severity::debug) if (msg._severity != Severity::debug)
emit Error(item); emit Error(item);
else else

View File

@ -56,14 +56,14 @@ void TxtReport::WriteError(const ErrorItem &error)
QString line; QString line;
for (int i = 0; i < error.lines.size(); i++) { for (int i = 0; i < error.errorPath.size(); i++) {
const QString file = QDir::toNativeSeparators(error.files[i]); const QString file = QDir::toNativeSeparators(error.errorPath[i].file);
line += QString("[%1:%2]").arg(file).arg(error.lines[i]); line += QString("[%1:%2]").arg(file).arg(error.errorPath[i].line);
if (i < error.lines.size() - 1 && !error.lines.isEmpty()) { if (i < error.errorPath.size() - 1 && !error.errorPath.isEmpty()) {
line += " -> "; line += " -> ";
} }
if (i == error.lines.size() - 1) { if (i == error.errorPath.size() - 1) {
line += ": "; line += ": ";
} }
} }

View File

@ -92,10 +92,10 @@ void XmlReportV1::WriteError(const ErrorItem &error)
return; return;
mXmlWriter->writeStartElement(ErrorElementName); 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); file = XmlReport::quoteMessage(file);
mXmlWriter->writeAttribute(FilenameAttribute, 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(LineAttribute, line);
mXmlWriter->writeAttribute(IdAttribute, error.errorId); mXmlWriter->writeAttribute(IdAttribute, error.errorId);
@ -155,10 +155,10 @@ ErrorItem XmlReportV1::ReadError(QXmlStreamReader *reader)
QXmlStreamAttributes attribs = reader->attributes(); QXmlStreamAttributes attribs = reader->attributes();
QString file = attribs.value("", FilenameAttribute).toString(); QString file = attribs.value("", FilenameAttribute).toString();
file = XmlReport::unquoteMessage(file); file = XmlReport::unquoteMessage(file);
item.file = file; QErrorPathItem e;
item.files.push_back(file); e.file = file;
const int line = attribs.value("", LineAttribute).toString().toUInt(); e.line = attribs.value("", LineAttribute).toString().toUInt();
item.lines.push_back(line); item.errorPath << e;
item.errorId = attribs.value("", IdAttribute).toString(); item.errorId = attribs.value("", IdAttribute).toString();
item.severity = GuiSeverity::fromString(attribs.value("", SeverityAttribute).toString()); item.severity = GuiSeverity::fromString(attribs.value("", SeverityAttribute).toString());

View File

@ -33,8 +33,12 @@ static const char CppcheckElementName[] = "cppcheck";
static const char ErrorElementName[] = "error"; static const char ErrorElementName[] = "error";
static const char ErrorsElementName[] = "errors"; static const char ErrorsElementName[] = "errors";
static const char LocationElementName[] = "location"; static const char LocationElementName[] = "location";
static const char ColAttribute[] = "col";
static const char CWEAttribute[] = "cwe";
static const char FilenameAttribute[] = "file"; static const char FilenameAttribute[] = "file";
static const char IncludedFromFilenameAttribute[] = "file0"; static const char IncludedFromFilenameAttribute[] = "file0";
static const char InconclusiveAttribute[] = "inconclusive";
static const char InfoAttribute[] = "info";
static const char LineAttribute[] = "line"; static const char LineAttribute[] = "line";
static const char IdAttribute[] = "id"; static const char IdAttribute[] = "id";
static const char SeverityAttribute[] = "severity"; static const char SeverityAttribute[] = "severity";
@ -103,10 +107,6 @@ void XmlReportV2::WriteError(const ErrorItem &error)
</error> </error>
*/ */
// Don't write inconclusive errors to XML V2 until we decide the format
if (error.inconclusive)
return;
mXmlWriter->writeStartElement(ErrorElementName); mXmlWriter->writeStartElement(ErrorElementName);
mXmlWriter->writeAttribute(IdAttribute, error.errorId); mXmlWriter->writeAttribute(IdAttribute, error.errorId);
@ -116,18 +116,24 @@ void XmlReportV2::WriteError(const ErrorItem &error)
mXmlWriter->writeAttribute(MsgAttribute, summary); mXmlWriter->writeAttribute(MsgAttribute, summary);
const QString message = XmlReport::quoteMessage(error.message); const QString message = XmlReport::quoteMessage(error.message);
mXmlWriter->writeAttribute(VerboseAttribute, 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); 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) { if (!error.file0.isEmpty() && file != error.file0) {
mXmlWriter->writeAttribute(IncludedFromFilenameAttribute, quoteMessage(error.file0)); mXmlWriter->writeAttribute(IncludedFromFilenameAttribute, quoteMessage(error.file0));
} }
file = XmlReport::quoteMessage(file); mXmlWriter->writeAttribute(FilenameAttribute, XmlReport::quoteMessage(file));
mXmlWriter->writeAttribute(FilenameAttribute, file); mXmlWriter->writeAttribute(LineAttribute, QString::number(error.errorPath[i].line));
const QString line = QString::number(error.lines[i]); if (error.errorPath[i].col > 0)
mXmlWriter->writeAttribute(LineAttribute, line); 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(); mXmlWriter->writeEndElement();
} }
@ -199,6 +205,10 @@ ErrorItem XmlReportV2::ReadError(QXmlStreamReader *reader)
item.summary = XmlReport::unquoteMessage(summary); item.summary = XmlReport::unquoteMessage(summary);
const QString message = attribs.value("", VerboseAttribute).toString(); const QString message = attribs.value("", VerboseAttribute).toString();
item.message = XmlReport::unquoteMessage(message); 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; bool errorRead = false;
@ -209,16 +219,17 @@ ErrorItem XmlReportV2::ReadError(QXmlStreamReader *reader)
// Read location element from inside error element // Read location element from inside error element
if (mXmlReader->name() == LocationElementName) { if (mXmlReader->name() == LocationElementName) {
QXmlStreamAttributes attribs = mXmlReader->attributes(); QXmlStreamAttributes attribs = mXmlReader->attributes();
QString file = attribs.value("", FilenameAttribute).toString();
QString file0 = attribs.value("", IncludedFromFilenameAttribute).toString(); QString file0 = attribs.value("", IncludedFromFilenameAttribute).toString();
file = XmlReport::unquoteMessage(file);
if (item.file.isEmpty())
item.file = file;
if (!file0.isEmpty()) if (!file0.isEmpty())
item.file0 = XmlReport::unquoteMessage(file0); item.file0 = XmlReport::unquoteMessage(file0);
item.files.push_back(file); QErrorPathItem loc;
const int line = attribs.value("", LineAttribute).toString().toUInt(); loc.file = XmlReport::unquoteMessage(attribs.value("", FilenameAttribute).toString());
item.lines.push_back(line); 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; break;