From d9affc16c4b52edb0ea38b20bc80437c4afffbf9 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Fri, 19 Jun 2015 15:37:16 +0200 Subject: Adapt to new diagnostics presentation API in AnalyzerBase. Task-number: QCE-34 Change-Id: Ia86fa082b3798ba42ec209b0e417e8a8ca0f8fa7 Reviewed-by: Nikolai Kosjar --- .../clangstaticanalyzerdiagnostic.cpp | 15 -- .../clangstaticanalyzerdiagnostic.h | 21 +- .../clangstaticanalyzerdiagnosticmodel.cpp | 215 +++++++++++++++--- .../clangstaticanalyzerdiagnosticmodel.h | 19 +- .../clangstaticanalyzerdiagnosticview.cpp | 248 +-------------------- .../clangstaticanalyzerdiagnosticview.h | 15 -- .../clangstaticanalyzerlogfilereader.cpp | 14 +- .../clangstaticanalyzertool.cpp | 8 +- .../clangstaticanalyzer/clangstaticanalyzertool.h | 2 +- .../clangstaticanalyzerutils.cpp | 2 +- .../clangstaticanalyzer/clangstaticanalyzerutils.h | 6 +- .../tests/clangstaticanalyzerautotest.qbs | 1 + .../tst_clangstaticanalyzerlogfilereader.cpp | 38 +--- plugins/clangstaticanalyzer/tests/tests.pri | 1 + 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 + #include #include #include @@ -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 ranges; + Analyzer::DiagnosticLocation location; + QList ranges; int depth; }; @@ -63,7 +52,7 @@ public: QString type; QString issueContextKind; QString issueContext; - Location location; + Analyzer::DiagnosticLocation location; QList 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 #include +#include + 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 &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 &diagnostics) { - beginResetModel(); - m_diagnostics.clear(); - endResetModel(); + foreach (const Diagnostic &d, diagnostics) + rootItem()->appendChild(new DiagnosticItem(d)); } -int ClangStaticAnalyzerDiagnosticModel::rowCount(const QModelIndex &parent) const +QList ClangStaticAnalyzerDiagnosticModel::diagnostics() const { - return parent.isValid() ? 0 : m_diagnostics.count(); + QList diags; + foreach (const Utils::TreeItem * const item, rootItem()->children()) + diags << static_cast(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 StringPair; + QList 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("" + "" + "\n" + "
"); + + foreach (const StringPair &pair, lines) { + html += QLatin1String("
"); + html += pair.first; + html += QLatin1String("
"); + html += pair.second; + html += QLatin1String("
\n"); + } + html += QLatin1String("
"); + 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); +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(parent())->diagnostic()); + case ClangStaticAnalyzerDiagnosticModel::DiagnosticRole: + return QVariant::fromValue(static_cast(parent())->diagnostic()); + case Qt::DisplayRole: { + const int row = parent()->children().indexOf(const_cast(this)) + 1; + const int padding = static_cast(std::log10(parent()->rowCount())) + - static_cast(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(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 #include +#include -#include #include #include @@ -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 &diagnostics); - QList diagnostics() const { return m_diagnostics; } - void clear(); + QList diagnostics() const; - // QAbstractListModel interface - int rowCount(const QModelIndex &parent = QModelIndex()) const; - QVariant data(const QModelIndex &index, int role) const; - -private: - QList 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 #include -#include #include -#include -#include -#include 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  %2") - .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 ") - + fileAndLine - + QLatin1String(""); - } 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("") + result + QLatin1String("") - : result; -} - -QString createExplainingStepToolTipString(const ClangStaticAnalyzer::Internal::ExplainingStep &step) -{ - if (step.message == step.extendedMessage) - return createFullLocationString(step.location); - - typedef QPair StringPair; - QList 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("" - "" - "\n" - "
"); - - foreach (const StringPair &pair, lines) { - html += QLatin1String("
"); - html += pair.first; - html += QLatin1String("
"); - html += pair.second; - html += QLatin1String("
\n"); - } - html += QLatin1String("
"); - 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(); - 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(); -} - -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(itemDelegate()) - ->getDiagnostic(indexes.first()); + const Diagnostic diag = model()->data(indexes.first(), + ClangStaticAnalyzerDiagnosticModel::DiagnosticRole) + .value(); 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 readPathArray(); ExplainingStep readPathDict(); - Location readLocationDict(bool elementIsRead = false); - QList readRangesArray(); + Analyzer::DiagnosticLocation readLocationDict(bool elementIsRead = false); + QList 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 ClangStaticAnalyzerLogFileReader::readRangesArray() +QList ClangStaticAnalyzerLogFileReader::readRangesArray() { - QList result; + QList 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) -- cgit v1.2.3