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
*/
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;

View File

@ -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<ErrorLogger::ErrorMessage::FileLocation>::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;
}

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.
*
@ -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<unsigned int> lines;
QString errorId;
Severity::SeverityType severity;
bool inconclusive;
QString summary;
QString message;
int cwe;
QList<QErrorPathItem> 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;

View File

@ -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;

View File

@ -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<QString, QVariant> 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<QString, QVariant> 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<QStandardItem*> 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);

View File

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

View File

@ -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 += ": ";
}
}

View File

@ -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());

View File

@ -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)
</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;