summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Kandeler <christian.kandeler@theqtcompany.com>2015-06-19 15:37:16 +0200
committerChristian Kandeler <christian.kandeler@theqtcompany.com>2015-08-25 11:42:53 +0300
commitd9affc16c4b52edb0ea38b20bc80437c4afffbf9 (patch)
treeb00f3e017bc2ae67ea81680aa9e0a88aeb73d937
parent501aad8d2c5af964e4a27f4bf969929c1395a3dd (diff)
downloadqt-creator-d9affc16c4b52edb0ea38b20bc80437c4afffbf9.tar.gz
Adapt to new diagnostics presentation API in AnalyzerBase.
Task-number: QCE-34 Change-Id: Ia86fa082b3798ba42ec209b0e417e8a8ca0f8fa7 Reviewed-by: Nikolai Kosjar <nikolai.kosjar@theqtcompany.com>
-rw-r--r--plugins/clangstaticanalyzer/clangstaticanalyzerdiagnostic.cpp15
-rw-r--r--plugins/clangstaticanalyzer/clangstaticanalyzerdiagnostic.h21
-rw-r--r--plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticmodel.cpp215
-rw-r--r--plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticmodel.h19
-rw-r--r--plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticview.cpp248
-rw-r--r--plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticview.h15
-rw-r--r--plugins/clangstaticanalyzer/clangstaticanalyzerlogfilereader.cpp14
-rw-r--r--plugins/clangstaticanalyzer/clangstaticanalyzertool.cpp8
-rw-r--r--plugins/clangstaticanalyzer/clangstaticanalyzertool.h2
-rw-r--r--plugins/clangstaticanalyzer/clangstaticanalyzerutils.cpp2
-rw-r--r--plugins/clangstaticanalyzer/clangstaticanalyzerutils.h6
-rw-r--r--plugins/clangstaticanalyzer/tests/clangstaticanalyzerautotest.qbs1
-rw-r--r--plugins/clangstaticanalyzer/tests/clangstaticanalyzerlogfilereader/tst_clangstaticanalyzerlogfilereader.cpp38
-rw-r--r--plugins/clangstaticanalyzer/tests/tests.pri1
14 files changed, 230 insertions, 375 deletions
diff --git a/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnostic.cpp b/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnostic.cpp
index 2f626a6afd..4e5f20a6bf 100644
--- a/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnostic.cpp
+++ b/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnostic.cpp
@@ -21,21 +21,6 @@
namespace ClangStaticAnalyzer {
namespace Internal {
-Location::Location()
- : line(0), column(0)
-{
-}
-
-Location::Location(const QString &filePath, int line, int column)
- : filePath(filePath), line(line), column(column)
-{
-}
-
-bool Location::isValid() const
-{
- return !filePath.isEmpty() && line >= 0 && column >= 0;
-}
-
ExplainingStep::ExplainingStep()
: depth(0)
{
diff --git a/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnostic.h b/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnostic.h
index 4ab2e3c30d..fe744a555b 100644
--- a/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnostic.h
+++ b/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnostic.h
@@ -19,6 +19,8 @@
#ifndef CLANGSTATICANALZYERDIAGNOSTIC_H
#define CLANGSTATICANALZYERDIAGNOSTIC_H
+#include <analyzerbase/diagnosticlocation.h>
+
#include <QList>
#include <QMetaType>
#include <QString>
@@ -26,19 +28,6 @@
namespace ClangStaticAnalyzer {
namespace Internal {
-class Location
-{
-public:
- Location();
- Location(const QString &filePath, int line, int column);
-
- bool isValid() const;
-
- QString filePath;
- int line;
- int column;
-};
-
class ExplainingStep
{
public:
@@ -48,8 +37,8 @@ public:
QString message;
QString extendedMessage;
- Location location;
- QList<Location> ranges;
+ Analyzer::DiagnosticLocation location;
+ QList<Analyzer::DiagnosticLocation> ranges;
int depth;
};
@@ -63,7 +52,7 @@ public:
QString type;
QString issueContextKind;
QString issueContext;
- Location location;
+ Analyzer::DiagnosticLocation location;
QList<ExplainingStep> explainingSteps;
};
diff --git a/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticmodel.cpp b/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticmodel.cpp
index 0cc4dfb9a0..c96e9c7528 100644
--- a/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticmodel.cpp
+++ b/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticmodel.cpp
@@ -18,6 +18,7 @@
#include "clangstaticanalyzerdiagnosticmodel.h"
+#include "clangstaticanalyzerdiagnosticview.h"
#include "clangstaticanalyzerprojectsettingsmanager.h"
#include "clangstaticanalyzerutils.h"
@@ -28,32 +29,53 @@
#include <QCoreApplication>
#include <QFileInfo>
+#include <cmath>
+
namespace ClangStaticAnalyzer {
namespace Internal {
-ClangStaticAnalyzerDiagnosticModel::ClangStaticAnalyzerDiagnosticModel(QObject *parent)
- : QAbstractListModel(parent)
+class DiagnosticItem : public Utils::TreeItem
{
-}
+public:
+ DiagnosticItem(const Diagnostic &diag);
-void ClangStaticAnalyzerDiagnosticModel::addDiagnostics(const QList<Diagnostic> &diagnostics)
+ Diagnostic diagnostic() const { return m_diagnostic; }
+
+private:
+ QVariant data(int column, int role) const override;
+
+ const Diagnostic m_diagnostic;
+};
+
+class ExplainingStepItem : public Utils::TreeItem
{
- beginInsertRows(QModelIndex(), m_diagnostics.size(),
- m_diagnostics.size() + diagnostics.size() - 1 );
- m_diagnostics += diagnostics;
- endInsertRows();
+public:
+ ExplainingStepItem(const ExplainingStep &step);
+
+private:
+ QVariant data(int column, int role) const override;
+
+ const ExplainingStep m_step;
+};
+
+ClangStaticAnalyzerDiagnosticModel::ClangStaticAnalyzerDiagnosticModel(QObject *parent)
+ : Utils::TreeModel(parent)
+{
+ setHeader(QStringList() << tr("Issue") << tr("Location"));
}
-void ClangStaticAnalyzerDiagnosticModel::clear()
+void ClangStaticAnalyzerDiagnosticModel::addDiagnostics(const QList<Diagnostic> &diagnostics)
{
- beginResetModel();
- m_diagnostics.clear();
- endResetModel();
+ foreach (const Diagnostic &d, diagnostics)
+ rootItem()->appendChild(new DiagnosticItem(d));
}
-int ClangStaticAnalyzerDiagnosticModel::rowCount(const QModelIndex &parent) const
+QList<Diagnostic> ClangStaticAnalyzerDiagnosticModel::diagnostics() const
{
- return parent.isValid() ? 0 : m_diagnostics.count();
+ QList<Diagnostic> diags;
+ foreach (const Utils::TreeItem * const item, rootItem()->children())
+ diags << static_cast<const DiagnosticItem *>(item)->diagnostic();
+ return diags;
}
static QString createDiagnosticToolTipString(const Diagnostic &diagnostic)
@@ -100,28 +122,162 @@ static QString createDiagnosticToolTipString(const Diagnostic &diagnostic)
return html;
}
-QVariant ClangStaticAnalyzerDiagnosticModel::data(const QModelIndex &index, int role) const
+static QString createExplainingStepToolTipString(const ExplainingStep &step)
{
- if (!index.isValid())
- return QVariant();
+ if (step.message == step.extendedMessage)
+ return createFullLocationString(step.location);
+
+ typedef QPair<QString, QString> StringPair;
+ QList<StringPair> lines;
+
+ if (!step.message.isEmpty()) {
+ lines << qMakePair(
+ QCoreApplication::translate("ClangStaticAnalyzer::ExplainingStep", "Message:"),
+ step.message.toHtmlEscaped());
+ }
+ if (!step.extendedMessage.isEmpty()) {
+ lines << qMakePair(
+ QCoreApplication::translate("ClangStaticAnalyzer::ExplainingStep", "Extended Message:"),
+ step.extendedMessage.toHtmlEscaped());
+ }
+
+ lines << qMakePair(
+ QCoreApplication::translate("ClangStaticAnalyzer::ExplainingStep", "Location:"),
+ createFullLocationString(step.location));
+
+ QString html = QLatin1String("<html>"
+ "<head>"
+ "<style>dt { font-weight:bold; } dd { font-family: monospace; }</style>\n"
+ "<body><dl>");
+
+ foreach (const StringPair &pair, lines) {
+ html += QLatin1String("<dt>");
+ html += pair.first;
+ html += QLatin1String("</dt><dd>");
+ html += pair.second;
+ html += QLatin1String("</dd>\n");
+ }
+ html += QLatin1String("</dl></body></html>");
+ return html;
+}
+
+static QString createLocationString(const Analyzer::DiagnosticLocation &location)
+{
+ const QString filePath = location.filePath;
+ const QString lineNumber = QString::number(location.line);
+ const QString fileAndLine = filePath + QLatin1Char(':') + lineNumber;
+ return QLatin1String("in ") + fileAndLine;
+}
+
+static QString createExplainingStepNumberString(int number)
+{
+ const int fieldWidth = 2;
+ return QString::fromLatin1("%1:").arg(number, fieldWidth);
+}
+
+static QString createExplainingStepString(const ExplainingStep &explainingStep, int number)
+{
+ return createExplainingStepNumberString(number)
+ + QLatin1Char(' ')
+ + explainingStep.extendedMessage
+ + QLatin1Char(' ')
+ + createLocationString(explainingStep.location);
+}
+
+static QString fullText(const Diagnostic &diagnostic)
+{
+ // Summary.
+ QString text = diagnostic.category + QLatin1String(": ") + diagnostic.type;
+ if (diagnostic.type != diagnostic.description)
+ text += QLatin1String(": ") + diagnostic.description;
+ text += QLatin1Char('\n');
+
+ // Explaining steps.
+ int explainingStepNumber = 1;
+ foreach (const ExplainingStep &explainingStep, diagnostic.explainingSteps) {
+ text += createExplainingStepString(explainingStep, explainingStepNumber++)
+ + QLatin1Char('\n');
+ }
+
+ text.chop(1); // Trailing newline.
+ return text;
+}
+
- if (index.parent().isValid())
+DiagnosticItem::DiagnosticItem(const Diagnostic &diag) : m_diagnostic(diag)
+{
+ // Don't show explaining steps if they add no information.
+ if (diag.explainingSteps.count() == 1) {
+ const ExplainingStep &step = diag.explainingSteps.first();
+ if (step.message == diag.description && step.location == diag.location)
+ return;
+ }
+
+ foreach (const ExplainingStep &s, diag.explainingSteps)
+ appendChild(new ExplainingStepItem(s));
+}
+
+QVariant locationData(int role, const Analyzer::DiagnosticLocation &location)
+{
+ switch (role) {
+ case Analyzer::DetailedErrorView::LocationRole:
+ return QVariant::fromValue(location);
+ case Qt::ToolTipRole:
+ return location.filePath.isEmpty() ? QVariant() : QVariant(location.filePath);
+ default:
return QVariant();
+ }
+}
+
+QVariant DiagnosticItem::data(int column, int role) const
+{
+ if (column == Analyzer::DetailedErrorView::LocationColumn)
+ return locationData(role, m_diagnostic.location);
- const int row = index.row();
- if (row < 0 || row >= m_diagnostics.size())
+ // DiagnosticColumn
+ switch (role) {
+ case Analyzer::DetailedErrorView::FullTextRole:
+ return fullText(m_diagnostic);
+ case ClangStaticAnalyzerDiagnosticModel::DiagnosticRole:
+ return QVariant::fromValue(m_diagnostic);
+ case Qt::DisplayRole:
+ return m_diagnostic.description;
+ case Qt::ToolTipRole:
+ return createDiagnosticToolTipString(m_diagnostic);
+ default:
return QVariant();
+ }
+}
- const Diagnostic diagnostic = m_diagnostics.at(row);
+ExplainingStepItem::ExplainingStepItem(const ExplainingStep &step) : m_step(step)
+{
+}
- if (role == Qt::DisplayRole)
- return QString(QLatin1String("Some specific diagnostic")); // TODO: Remove?
- else if (role == Qt::ToolTipRole)
- return createDiagnosticToolTipString(diagnostic);
- else if (role == Qt::UserRole)
- return QVariant::fromValue<Diagnostic>(diagnostic);
+QVariant ExplainingStepItem::data(int column, int role) const
+{
+ if (column == Analyzer::DetailedErrorView::LocationColumn)
+ return locationData(role, m_step.location);
- return QVariant();
+ // DiagnosticColumn
+ switch (role) {
+ case Analyzer::DetailedErrorView::FullTextRole:
+ return fullText(static_cast<DiagnosticItem *>(parent())->diagnostic());
+ case ClangStaticAnalyzerDiagnosticModel::DiagnosticRole:
+ return QVariant::fromValue(static_cast<DiagnosticItem *>(parent())->diagnostic());
+ case Qt::DisplayRole: {
+ const int row = parent()->children().indexOf(const_cast<ExplainingStepItem *>(this)) + 1;
+ const int padding = static_cast<int>(std::log10(parent()->rowCount()))
+ - static_cast<int>(std::log10(row));
+ return QString::fromLatin1("%1%2: %3")
+ .arg(QString(padding, QLatin1Char(' ')))
+ .arg(row)
+ .arg(m_step.message);
+ }
+ case Qt::ToolTipRole:
+ return createExplainingStepToolTipString(m_step);
+ default:
+ return QVariant();
+ }
}
@@ -165,7 +321,8 @@ void ClangStaticAnalyzerDiagnosticFilterModel::addSuppressedDiagnostic(
bool ClangStaticAnalyzerDiagnosticFilterModel::filterAcceptsRow(int sourceRow,
const QModelIndex &sourceParent) const
{
- Q_UNUSED(sourceParent);
+ if (sourceParent.isValid())
+ return true;
const Diagnostic diag = static_cast<ClangStaticAnalyzerDiagnosticModel *>(sourceModel())
->diagnostics().at(sourceRow);
foreach (const SuppressedDiagnostic &d, m_suppressedDiagnostics) {
diff --git a/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticmodel.h b/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticmodel.h
index 492624627a..0c8ab90b20 100644
--- a/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticmodel.h
+++ b/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticmodel.h
@@ -19,12 +19,13 @@
#ifndef CLANGSTATICANALYZERDIAGNOSTICMODEL_H
#define CLANGSTATICANALYZERDIAGNOSTICMODEL_H
-#include "clangstaticanalyzerlogfilereader.h"
+#include "clangstaticanalyzerdiagnostic.h"
#include "clangstaticanalyzerprojectsettings.h"
+#include <analyzerbase/detailederrorview.h>
#include <utils/fileutils.h>
+#include <utils/treemodel.h>
-#include <QAbstractListModel>
#include <QPointer>
#include <QSortFilterProxyModel>
@@ -33,7 +34,7 @@ namespace ProjectExplorer { class Project; }
namespace ClangStaticAnalyzer {
namespace Internal {
-class ClangStaticAnalyzerDiagnosticModel : public QAbstractListModel
+class ClangStaticAnalyzerDiagnosticModel : public Utils::TreeModel
{
Q_OBJECT
@@ -41,15 +42,11 @@ public:
ClangStaticAnalyzerDiagnosticModel(QObject *parent = 0);
void addDiagnostics(const QList<Diagnostic> &diagnostics);
- QList<Diagnostic> diagnostics() const { return m_diagnostics; }
- void clear();
+ QList<Diagnostic> diagnostics() const;
- // QAbstractListModel interface
- int rowCount(const QModelIndex &parent = QModelIndex()) const;
- QVariant data(const QModelIndex &index, int role) const;
-
-private:
- QList<Diagnostic> m_diagnostics;
+ enum ItemRole {
+ DiagnosticRole = Analyzer::DetailedErrorView::FullTextRole + 1
+ };
};
class ClangStaticAnalyzerDiagnosticFilterModel : public QSortFilterProxyModel
diff --git a/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticview.cpp b/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticview.cpp
index a4c3fd66e3..c466599766 100644
--- a/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticview.cpp
+++ b/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticview.cpp
@@ -18,7 +18,6 @@
#include "clangstaticanalyzerdiagnosticview.h"
-#include "clangstaticanalyzerlogfilereader.h"
#include "clangstaticanalyzerdiagnosticmodel.h"
#include "clangstaticanalyzerprojectsettings.h"
#include "clangstaticanalyzerprojectsettingsmanager.h"
@@ -28,266 +27,27 @@
#include <utils/qtcassert.h>
#include <QAction>
-#include <QCoreApplication>
#include <QDebug>
-#include <QFileInfo>
-#include <QLabel>
-#include <QVBoxLayout>
using namespace Analyzer;
-namespace {
-
-QLabel *createCommonLabel()
-{
- QLabel *label = new QLabel;
- label->setWordWrap(true);
- label->setContentsMargins(0, 0, 0, 0);
- label->setMargin(0);
- label->setIndent(10);
- return label;
-}
-
-QString createSummaryText(const ClangStaticAnalyzer::Internal::Diagnostic &diagnostic,
- const QPalette &palette)
-{
- const QColor color = palette.color(QPalette::Text);
- const QString linkStyle = QString::fromLatin1("style=\"color:rgba(%1, %2, %3, %4);\"")
- .arg(color.red())
- .arg(color.green())
- .arg(color.blue())
- .arg(int(0.7 * 255));
- const QString fileName = QFileInfo(diagnostic.location.filePath).fileName();
- const QString location = fileName + QLatin1Char(' ')
- + QString::number(diagnostic.location.line);
- return QString::fromLatin1("%1&nbsp;&nbsp;<span %3>%2</span>")
- .arg(diagnostic.description.toHtmlEscaped(),
- location,
- linkStyle);
-}
-
-QLabel *createSummaryLabel(const ClangStaticAnalyzer::Internal::Diagnostic &diagnostic)
-{
- QLabel *label = createCommonLabel();
- QPalette palette = label->palette();
- palette.setBrush(QPalette::Text, palette.highlightedText());
- label->setPalette(palette);
- label->setText(createSummaryText(diagnostic, palette));
- return label;
-}
-
-QLabel *createExplainingStepLabel(const QFont &font, bool useAlternateRowPalette)
-{
- QLabel *label = createCommonLabel();
-
- // Font
- QFont fixedPitchFont = font;
- fixedPitchFont.setFixedPitch(true);
- label->setFont(fixedPitchFont);
-
- // Background
- label->setAutoFillBackground(true);
- if (useAlternateRowPalette) {
- QPalette p = label->palette();
- p.setBrush(QPalette::Base, p.alternateBase());
- label->setPalette(p);
- }
-
- return label;
-}
-
-QString createLocationString(const ClangStaticAnalyzer::Internal::Location &location,
- bool withMarkup, bool withAbsolutePath)
-{
- const QString filePath = location.filePath;
- const QString lineNumber = QString::number(location.line);
- const QString columnNumber = QString::number(location.column - 1);
- const QString fileAndLine = (withAbsolutePath ? filePath : QFileInfo(filePath).fileName())
- + QLatin1Char(':') + lineNumber;
-
- if (withMarkup) {
- return QLatin1String("in <a href=\"file://")
- + filePath + QLatin1Char(':') + lineNumber + QLatin1Char(':') + columnNumber
- + QLatin1String("\">")
- + fileAndLine
- + QLatin1String("</a>");
- } else {
- return QLatin1String("in ") + fileAndLine;
- }
-}
-
-QString createExplainingStepNumberString(int number, bool withMarkup)
-{
- const int fieldWidth = 2;
- const QString result = QString::fromLatin1("%1:").arg(number, fieldWidth);
- return withMarkup
- ? QLatin1String("<code style='white-space:pre'>") + result + QLatin1String("</code>")
- : result;
-}
-
-QString createExplainingStepToolTipString(const ClangStaticAnalyzer::Internal::ExplainingStep &step)
-{
- if (step.message == step.extendedMessage)
- return createFullLocationString(step.location);
-
- typedef QPair<QString, QString> StringPair;
- QList<StringPair> lines;
-
- if (!step.message.isEmpty()) {
- lines << qMakePair(
- QCoreApplication::translate("ClangStaticAnalyzer::ExplainingStep", "Message:"),
- step.message.toHtmlEscaped());
- }
- if (!step.extendedMessage.isEmpty()) {
- lines << qMakePair(
- QCoreApplication::translate("ClangStaticAnalyzer::ExplainingStep", "Extended Message:"),
- step.extendedMessage.toHtmlEscaped());
- }
-
- lines << qMakePair(
- QCoreApplication::translate("ClangStaticAnalyzer::ExplainingStep", "Location:"),
- createFullLocationString(step.location));
-
- QString html = QLatin1String("<html>"
- "<head>"
- "<style>dt { font-weight:bold; } dd { font-family: monospace; }</style>\n"
- "<body><dl>");
-
- foreach (const StringPair &pair, lines) {
- html += QLatin1String("<dt>");
- html += pair.first;
- html += QLatin1String("</dt><dd>");
- html += pair.second;
- html += QLatin1String("</dd>\n");
- }
- html += QLatin1String("</dl></body></html>");
- return html;
-}
-
-QString createExplainingStepString(
- const ClangStaticAnalyzer::Internal::ExplainingStep &explainingStep,
- int number, bool withMarkup, bool withAbsolutePath)
-{
- return createExplainingStepNumberString(number, withMarkup)
- + QLatin1Char(' ')
- + (withMarkup
- ? explainingStep.extendedMessage.toHtmlEscaped()
- : explainingStep.extendedMessage)
- + QLatin1Char(' ')
- + createLocationString(explainingStep.location, withMarkup, withAbsolutePath);
-}
-
-} // anonymous namespace
-
namespace ClangStaticAnalyzer {
namespace Internal {
-ClangStaticAnalyzerDiagnosticDelegate::ClangStaticAnalyzerDiagnosticDelegate(QListView *parent)
- : DetailedErrorDelegate(parent)
-{
-}
-
-DetailedErrorDelegate::SummaryLineInfo ClangStaticAnalyzerDiagnosticDelegate::summaryInfo(
- const QModelIndex &index) const
-{
- const Diagnostic diagnostic = index.data(Qt::UserRole).value<Diagnostic>();
- QTC_ASSERT(diagnostic.isValid(), return SummaryLineInfo());
-
- DetailedErrorDelegate::SummaryLineInfo info;
- info.errorText = diagnostic.description;
- info.errorLocation = createLocationString(diagnostic.location,
- /*withMarkup=*/ false,
- /*withAbsolutePath=*/ false);
- return info;
-}
-
-Diagnostic ClangStaticAnalyzerDiagnosticDelegate::getDiagnostic(const QModelIndex &index) const
-{
- return index.data(Qt::UserRole).value<Diagnostic>();
-}
-
-QWidget *ClangStaticAnalyzerDiagnosticDelegate::createDetailsWidget(const QFont &font,
- const QModelIndex &index,
- QWidget *parent) const
-{
- QWidget *widget = new QWidget(parent);
-
- const Diagnostic diagnostic = getDiagnostic(index);
- if (!diagnostic.isValid())
- return widget;
-
- QVBoxLayout *layout = new QVBoxLayout;
-
- // Add summary label
- QLabel *summaryLineLabel = createSummaryLabel(diagnostic);
- connect(summaryLineLabel, &QLabel::linkActivated,
- this, &ClangStaticAnalyzerDiagnosticDelegate::openLinkInEditor);
- layout->addWidget(summaryLineLabel);
-
- // Add labels for explaining steps
- int explainingStepNumber = 1;
- foreach (const ExplainingStep &explainingStep, diagnostic.explainingSteps) {
- const QString text = createExplainingStepString(explainingStep,
- explainingStepNumber++,
- /*withMarkup=*/ true,
- /*withAbsolutePath=*/ false);
- QLabel *label = createExplainingStepLabel(font, explainingStepNumber % 2 == 0);
- label->setParent(widget);
- label->setText(text);
- label->setToolTip(createExplainingStepToolTipString(explainingStep));
- connect(label, &QLabel::linkActivated,
- this, &ClangStaticAnalyzerDiagnosticDelegate::openLinkInEditor);
- layout->addWidget(label);
- }
-
- layout->setContentsMargins(0, 0, 0, 0);
- layout->setSpacing(0);
- widget->setLayout(layout);
- return widget;
-}
-
-QString ClangStaticAnalyzerDiagnosticDelegate::textualRepresentation() const
-{
- QTC_ASSERT(m_detailsIndex.isValid(), return QString());
-
- const Diagnostic diagnostic = getDiagnostic(m_detailsIndex);
- QTC_ASSERT(diagnostic.isValid(), return QString());
-
- // Create summary
- QString clipboardText = diagnostic.category + QLatin1String(": ") + diagnostic.type;
- if (diagnostic.type != diagnostic.description)
- clipboardText += QLatin1String(": ") + diagnostic.description;
- clipboardText += QLatin1Char('\n');
-
- // Create explaining steps
- int explainingStepNumber = 1;
- foreach (const ExplainingStep &explainingStep, diagnostic.explainingSteps) {
- clipboardText += createExplainingStepString(explainingStep,
- explainingStepNumber++,
- /*withMarkup=*/ false,
- /*withAbsolutePath=*/ true) + QLatin1Char('\n');
- }
-
- clipboardText.chop(1); // Remove \n
- return clipboardText;
-}
-
ClangStaticAnalyzerDiagnosticView::ClangStaticAnalyzerDiagnosticView(QWidget *parent)
: Analyzer::DetailedErrorView(parent)
{
- ClangStaticAnalyzerDiagnosticDelegate *delegate
- = new ClangStaticAnalyzerDiagnosticDelegate(this);
- setItemDelegate(delegate);
m_suppressAction = new QAction(tr("Suppress this diagnostic"), this);
connect(m_suppressAction, &QAction::triggered, [this](bool) { suppressCurrentDiagnostic(); });
}
void ClangStaticAnalyzerDiagnosticView::suppressCurrentDiagnostic()
{
- const QModelIndexList indexes = selectedIndexes();
+ const QModelIndexList indexes = selectionModel()->selectedRows();
QTC_ASSERT(indexes.count() == 1, return);
- const Diagnostic diag = static_cast<ClangStaticAnalyzerDiagnosticDelegate *>(itemDelegate())
- ->getDiagnostic(indexes.first());
+ const Diagnostic diag = model()->data(indexes.first(),
+ ClangStaticAnalyzerDiagnosticModel::DiagnosticRole)
+ .value<Diagnostic>();
QTC_ASSERT(diag.isValid(), return);
// If the original project was closed, we work directly on the filter model, otherwise
diff --git a/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticview.h b/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticview.h
index b9b5fa6fc3..0b00ada75c 100644
--- a/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticview.h
+++ b/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticview.h
@@ -23,7 +23,6 @@
namespace ClangStaticAnalyzer {
namespace Internal {
-class Diagnostic;
class ClangStaticAnalyzerDiagnosticView : public Analyzer::DetailedErrorView
{
@@ -40,20 +39,6 @@ private:
QAction *m_suppressAction;
};
-class ClangStaticAnalyzerDiagnosticDelegate : public Analyzer::DetailedErrorDelegate
-{
-public:
- ClangStaticAnalyzerDiagnosticDelegate(QListView *parent);
-
- SummaryLineInfo summaryInfo(const QModelIndex &index) const;
- Diagnostic getDiagnostic(const QModelIndex &index) const;
-
-private:
- QWidget *createDetailsWidget(const QFont &font, const QModelIndex &index,
- QWidget *parent) const;
- QString textualRepresentation() const;
-};
-
} // namespace Internal
} // namespace ClangStaticAnalyzer
diff --git a/plugins/clangstaticanalyzer/clangstaticanalyzerlogfilereader.cpp b/plugins/clangstaticanalyzer/clangstaticanalyzerlogfilereader.cpp
index 55f7bf0547..95851ea1c4 100644
--- a/plugins/clangstaticanalyzer/clangstaticanalyzerlogfilereader.cpp
+++ b/plugins/clangstaticanalyzer/clangstaticanalyzerlogfilereader.cpp
@@ -48,8 +48,8 @@ private:
void readDiagnosticsDict();
QList<ExplainingStep> readPathArray();
ExplainingStep readPathDict();
- Location readLocationDict(bool elementIsRead = false);
- QList<Location> readRangesArray();
+ Analyzer::DiagnosticLocation readLocationDict(bool elementIsRead = false);
+ QList<Analyzer::DiagnosticLocation> readRangesArray();
QString readString();
QStringList readStringArray();
@@ -277,9 +277,9 @@ ExplainingStep ClangStaticAnalyzerLogFileReader::readPathDict()
return explainingStep;
}
-Location ClangStaticAnalyzerLogFileReader::readLocationDict(bool elementIsRead)
+Analyzer::DiagnosticLocation ClangStaticAnalyzerLogFileReader::readLocationDict(bool elementIsRead)
{
- Location location;
+ Analyzer::DiagnosticLocation location;
if (elementIsRead) {
QTC_ASSERT(m_xml.isStartElement() && m_xml.name() == QLatin1String("dict"),
return location);
@@ -310,14 +310,14 @@ Location ClangStaticAnalyzerLogFileReader::readLocationDict(bool elementIsRead)
if (lineOk && columnOk && fileIndexOk) {
QTC_ASSERT(fileIndex < m_referencedFiles.size(), return location);
- location = Location(m_referencedFiles.at(fileIndex), line, column);
+ location = Analyzer::DiagnosticLocation(m_referencedFiles.at(fileIndex), line, column);
}
return location;
}
-QList<Location> ClangStaticAnalyzerLogFileReader::readRangesArray()
+QList<Analyzer::DiagnosticLocation> ClangStaticAnalyzerLogFileReader::readRangesArray()
{
- QList<Location> result;
+ QList<Analyzer::DiagnosticLocation> result;
// It's an array of arrays...
QTC_ASSERT(m_xml.readNextStartElement() && m_xml.name() == QLatin1String("array"),
diff --git a/plugins/clangstaticanalyzer/clangstaticanalyzertool.cpp b/plugins/clangstaticanalyzer/clangstaticanalyzertool.cpp
index 08ad19f170..749766b02f 100644
--- a/plugins/clangstaticanalyzer/clangstaticanalyzertool.cpp
+++ b/plugins/clangstaticanalyzer/clangstaticanalyzertool.cpp
@@ -19,6 +19,7 @@
#include "clangstaticanalyzertool.h"
#include "clangstaticanalyzerconstants.h"
+#include "clangstaticanalyzerdiagnostic.h"
#include "clangstaticanalyzerdiagnosticmodel.h"
#include "clangstaticanalyzerdiagnosticview.h"
#include "clangstaticanalyzerruncontrol.h"
@@ -88,11 +89,10 @@ QWidget *ClangStaticAnalyzerTool::createWidgets()
// Diagnostic View
//
m_diagnosticView = new ClangStaticAnalyzerDiagnosticView;
- m_diagnosticView->setObjectName(QLatin1String("ClangStaticAnalyzerIssuesView"));
m_diagnosticView->setFrameStyle(QFrame::NoFrame);
m_diagnosticView->setAttribute(Qt::WA_MacShowFocusRect, false);
- m_diagnosticModel = new ClangStaticAnalyzerDiagnosticModel(m_diagnosticView);
- m_diagnosticFilterModel = new ClangStaticAnalyzerDiagnosticFilterModel(m_diagnosticView);
+ m_diagnosticModel = new ClangStaticAnalyzerDiagnosticModel(this);
+ m_diagnosticFilterModel = new ClangStaticAnalyzerDiagnosticFilterModel(this);
m_diagnosticFilterModel->setSourceModel(m_diagnosticModel);
m_diagnosticView->setModel(m_diagnosticFilterModel);
m_diagnosticView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
@@ -302,7 +302,7 @@ void ClangStaticAnalyzerTool::handleStateUpdate()
QTC_ASSERT(m_diagnosticModel, return);
QTC_ASSERT(m_diagnosticFilterModel, return);
- const int issuesFound = m_diagnosticModel->rowCount();
+ const int issuesFound = m_diagnosticModel->diagnostics().count();
const int issuesVisible = m_diagnosticFilterModel->rowCount();
m_goBack->setEnabled(issuesVisible > 1);
m_goNext->setEnabled(issuesVisible > 1);
diff --git a/plugins/clangstaticanalyzer/clangstaticanalyzertool.h b/plugins/clangstaticanalyzer/clangstaticanalyzertool.h
index 3cc1ff1865..52585558d3 100644
--- a/plugins/clangstaticanalyzer/clangstaticanalyzertool.h
+++ b/plugins/clangstaticanalyzer/clangstaticanalyzertool.h
@@ -72,7 +72,7 @@ private:
ClangStaticAnalyzerDiagnosticModel *m_diagnosticModel;
ClangStaticAnalyzerDiagnosticFilterModel *m_diagnosticFilterModel;
- Analyzer::DetailedErrorView *m_diagnosticView;
+ ClangStaticAnalyzerDiagnosticView *m_diagnosticView;
QAction *m_goBack;
QAction *m_goNext;
diff --git a/plugins/clangstaticanalyzer/clangstaticanalyzerutils.cpp b/plugins/clangstaticanalyzer/clangstaticanalyzerutils.cpp
index b3ba34da69..3516af4771 100644
--- a/plugins/clangstaticanalyzer/clangstaticanalyzerutils.cpp
+++ b/plugins/clangstaticanalyzer/clangstaticanalyzerutils.cpp
@@ -70,7 +70,7 @@ QString clangExecutable(const QString &fileNameOrPath, bool *isValid)
return executable;
}
-QString createFullLocationString(const ClangStaticAnalyzer::Internal::Location &location)
+QString createFullLocationString(const Analyzer::DiagnosticLocation &location)
{
const QString filePath = location.filePath;
const QString lineNumber = QString::number(location.line);
diff --git a/plugins/clangstaticanalyzer/clangstaticanalyzerutils.h b/plugins/clangstaticanalyzer/clangstaticanalyzerutils.h
index 9885fc7390..9fda05578e 100644
--- a/plugins/clangstaticanalyzer/clangstaticanalyzerutils.h
+++ b/plugins/clangstaticanalyzer/clangstaticanalyzerutils.h
@@ -27,17 +27,17 @@ QT_BEGIN_NAMESPACE
class QString;
QT_END_NAMESPACE
+namespace Analyzer { class DiagnosticLocation; }
+
namespace ClangStaticAnalyzer {
namespace Internal {
-class Location;
-
bool isClangExecutableUsable(const QString &filePath, QString *errorMessage = 0);
QString clangExecutable(const QString &fileNameOrPath, bool *isValid);
QString clangExecutableFromSettings(Core::Id toolchainType, bool *isValid);
-QString createFullLocationString(const ClangStaticAnalyzer::Internal::Location &location);
+QString createFullLocationString(const Analyzer::DiagnosticLocation &location);
} // namespace Internal
} // namespace ClangStaticAnalyzer
diff --git a/plugins/clangstaticanalyzer/tests/clangstaticanalyzerautotest.qbs b/plugins/clangstaticanalyzer/tests/clangstaticanalyzerautotest.qbs
index ab51ab2e6f..88dfcb32a1 100644
--- a/plugins/clangstaticanalyzer/tests/clangstaticanalyzerautotest.qbs
+++ b/plugins/clangstaticanalyzer/tests/clangstaticanalyzerautotest.qbs
@@ -2,6 +2,7 @@ import qbs
QtcAutotest {
Depends { name: "Qt.widgets" }
+ Depends { name: "AnalyzerBase" }
Depends { name: "Utils" }
property path pluginDir: "../../"
diff --git a/plugins/clangstaticanalyzer/tests/clangstaticanalyzerlogfilereader/tst_clangstaticanalyzerlogfilereader.cpp b/plugins/clangstaticanalyzer/tests/clangstaticanalyzerlogfilereader/tst_clangstaticanalyzerlogfilereader.cpp
index ebd0e5ab00..e3ef8af7db 100644
--- a/plugins/clangstaticanalyzer/tests/clangstaticanalyzerlogfilereader/tst_clangstaticanalyzerlogfilereader.cpp
+++ b/plugins/clangstaticanalyzer/tests/clangstaticanalyzerlogfilereader/tst_clangstaticanalyzerlogfilereader.cpp
@@ -24,38 +24,18 @@
enum { debug = 0 };
-namespace ClangStaticAnalyzer {
-namespace Internal {
-
-static bool operator==(const Location &first, const Location &second)
-{
- return first.filePath == second.filePath
- && first.line == second.line
- && first.column == second.column;
-}
-
-} // namespace Internal
-} // namespace ClangStaticAnalyzer
-
+using namespace Analyzer;
using namespace ClangStaticAnalyzer::Internal;
namespace {
-QDebug operator<<(QDebug dbg, const Location &location)
-{
- dbg.nospace() << "Location(" << location.filePath << ", "
- << location.line << ", "
- << location.column << ')';
- return dbg.space();
-}
-
QDebug operator<<(QDebug dbg, const ExplainingStep &step)
{
dbg << '\n'
<< " ExplainingStep\n"
<< " location:" << step.location << '\n'
<< " ranges:\n";
- foreach (const Location &location, step.ranges)
+ foreach (const DiagnosticLocation &location, step.ranges)
dbg << " " << location << '\n';
dbg
<< " message:" << step.message << '\n'
@@ -148,23 +128,23 @@ void ClangStaticAnalyzerLogFileReaderTest::readFileWithDiagnostics()
QCOMPARE(d1.type, d1.description);
QCOMPARE(d1.issueContextKind, QLatin1String("function"));
QCOMPARE(d1.issueContext, QLatin1String("test"));
- QCOMPARE(d1.location, Location(commonPath, 36, 3));
+ QCOMPARE(d1.location, DiagnosticLocation(commonPath, 36, 3));
QCOMPARE(d1.explainingSteps.size(), 2);
const ExplainingStep step1 = d1.explainingSteps.at(0);
- QCOMPARE(step1.location, Location(commonPath, 35, 3));
+ QCOMPARE(step1.location, DiagnosticLocation(commonPath, 35, 3));
QCOMPARE(step1.ranges.size(), 2);
- QCOMPARE(step1.ranges.at(0), Location(commonPath, 35, 3));
- QCOMPARE(step1.ranges.at(1), Location(commonPath, 35, 9));
+ QCOMPARE(step1.ranges.at(0), DiagnosticLocation(commonPath, 35, 3));
+ QCOMPARE(step1.ranges.at(1), DiagnosticLocation(commonPath, 35, 9));
QCOMPARE(step1.depth, 0);
QCOMPARE(step1.message, QLatin1String("Null pointer value stored to 'foo'"));
QCOMPARE(step1.extendedMessage, step1.message);
const ExplainingStep step2 = d1.explainingSteps.at(1);
- QCOMPARE(step2.location, Location(commonPath, 36, 3));
+ QCOMPARE(step2.location, DiagnosticLocation(commonPath, 36, 3));
QCOMPARE(step2.ranges.size(), 2);
- QCOMPARE(step2.ranges.at(0), Location(commonPath, 36, 3));
- QCOMPARE(step2.ranges.at(1), Location(commonPath, 36, 5));
+ QCOMPARE(step2.ranges.at(0), DiagnosticLocation(commonPath, 36, 3));
+ QCOMPARE(step2.ranges.at(1), DiagnosticLocation(commonPath, 36, 5));
QCOMPARE(step2.depth, 0);
QCOMPARE(step2.message, QLatin1String("Called function pointer is null (null dereference)"));
QCOMPARE(step2.extendedMessage, step2.message);
diff --git a/plugins/clangstaticanalyzer/tests/tests.pri b/plugins/clangstaticanalyzer/tests/tests.pri
index b7cfc9154c..8975fc8448 100644
--- a/plugins/clangstaticanalyzer/tests/tests.pri
+++ b/plugins/clangstaticanalyzer/tests/tests.pri
@@ -1,4 +1,5 @@
QTC_LIB_DEPENDS += utils
+QTC_PLUGIN_DEPENDS += analyzerbase
isEmpty(IDE_SOURCE_TREE): IDE_SOURCE_TREE=$$(QTC_SOURCE)
isEmpty(IDE_BUILD_TREE): IDE_BUILD_TREE=$$(QTC_BUILD)