forked from qt-creator/qt-creator
Cppcheck: Add ability to manually run cppcheck
Run cppcheck on selected files from current project via "Analyze"->"Cppcheck...." Show results in a separate view in the same manner as ClangTools plugin. Fixes: QTCREATORBUG-21673 Change-Id: Ibcaf4057a387a990f1da59025f15ba58f996953f Reviewed-by: Nikolai Kosjar <nikolai.kosjar@qt.io>
This commit is contained in:
@@ -1,9 +1,13 @@
|
||||
add_qtc_plugin(Cppcheck
|
||||
DEPENDS Qt5::Widgets
|
||||
PLUGIN_DEPENDS Core CppTools ProjectExplorer TextEditor
|
||||
PLUGIN_DEPENDS Core Debugger CppTools ProjectExplorer TextEditor
|
||||
SOURCES
|
||||
cppcheckconstants.h
|
||||
cppcheckdiagnostic.h
|
||||
cppcheckdiagnostic.cpp cppcheckdiagnostic.h
|
||||
cppcheckdiagnosticmanager.h
|
||||
cppcheckdiagnosticsmodel.cppмcppcheckdiagnosticsmodel.h
|
||||
cppcheckdiagnosticview.cpp cppcheckdiagnosticview.h
|
||||
cppcheckmanualrundialog.cpp cppcheckmanualrundialog.h
|
||||
cppcheckoptions.cpp cppcheckoptions.h
|
||||
cppcheckplugin.cpp cppcheckplugin.h
|
||||
cppcheckrunner.cpp cppcheckrunner.h
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
include(../../qtcreatorplugin.pri)
|
||||
|
||||
SOURCES += \
|
||||
cppcheckdiagnostic.cpp \
|
||||
cppcheckdiagnosticsmodel.cpp \
|
||||
cppcheckdiagnosticview.cpp \
|
||||
cppcheckmanualrundialog.cpp \
|
||||
cppcheckoptions.cpp \
|
||||
cppcheckplugin.cpp \
|
||||
cppcheckrunner.cpp \
|
||||
@@ -12,6 +16,10 @@ SOURCES += \
|
||||
HEADERS += \
|
||||
cppcheckconstants.h \
|
||||
cppcheckdiagnostic.h \
|
||||
cppcheckdiagnosticmanager.h \
|
||||
cppcheckdiagnosticsmodel.h \
|
||||
cppcheckdiagnosticview.h \
|
||||
cppcheckmanualrundialog.h \
|
||||
cppcheckoptions.h \
|
||||
cppcheckplugin.h \
|
||||
cppcheckrunner.h \
|
||||
|
||||
@@ -5,6 +5,7 @@ QtcPlugin {
|
||||
|
||||
Depends { name: "Core" }
|
||||
Depends { name: "CppTools" }
|
||||
Depends { name: "Debugger" }
|
||||
Depends { name: "ProjectExplorer" }
|
||||
Depends { name: "TextEditor" }
|
||||
Depends { name: "Utils" }
|
||||
@@ -13,7 +14,15 @@ QtcPlugin {
|
||||
|
||||
files: [
|
||||
"cppcheckconstants.h",
|
||||
"cppcheckdiagnostic.cpp",
|
||||
"cppcheckdiagnostic.h",
|
||||
"cppcheckdiagnosticmanager.h",
|
||||
"cppcheckdiagnosticsmodel.cpp",
|
||||
"cppcheckdiagnosticsmodel.h",
|
||||
"cppcheckdiagnosticview.cpp",
|
||||
"cppcheckdiagnosticview.h",
|
||||
"cppcheckmanualrundialog.cpp",
|
||||
"cppcheckmanualrundialog.h",
|
||||
"cppcheckoptions.cpp",
|
||||
"cppcheckoptions.h",
|
||||
"cppcheckplugin.cpp",
|
||||
|
||||
@@ -4,5 +4,6 @@ QTC_LIB_DEPENDS += \
|
||||
utils
|
||||
QTC_PLUGIN_DEPENDS += \
|
||||
cpptools \
|
||||
debugger \
|
||||
projectexplorer \
|
||||
texteditor
|
||||
|
||||
@@ -49,7 +49,11 @@ const char SETTINGS_SHOW_OUTPUT[] = "showOutput";
|
||||
const char SETTINGS_ADD_INCLUDE_PATHS[] = "addIncludePaths";
|
||||
const char SETTINGS_GUESS_ARGUMENTS[] = "guessArguments";
|
||||
|
||||
const char CHECK_PROGRESS_ID[] = "Cppcheck.Cppcheck.CheckingTask";
|
||||
const char CHECK_PROGRESS_ID[] = "Cppcheck.CheckingTask";
|
||||
|
||||
const char MANUAL_CHECK_PROGRESS_ID[] = "Cppcheck.ManualCheckingTask";
|
||||
const char MANUAL_RUN_ACTION[] = "Cppcheck.ManualRun";
|
||||
const char PERSPECTIVE_ID[] = "Cppcheck.Perspective";
|
||||
|
||||
} // namespace Constants
|
||||
} // namespace Cppcheck
|
||||
|
||||
42
src/plugins/cppcheck/cppcheckdiagnostic.cpp
Normal file
42
src/plugins/cppcheck/cppcheckdiagnostic.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2019 Sergey Morozov
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "cppcheckdiagnostic.h"
|
||||
|
||||
namespace Cppcheck {
|
||||
namespace Internal {
|
||||
|
||||
bool Diagnostic::operator==(const Diagnostic &r) const
|
||||
{
|
||||
return std::tie(severity, message, fileName, lineNumber)
|
||||
== std::tie(r.severity, r.message, r.fileName, r.lineNumber);
|
||||
}
|
||||
|
||||
quint32 qHash(const Diagnostic &diagnostic)
|
||||
{
|
||||
return qHash(diagnostic.message) ^ qHash(diagnostic.fileName) ^ diagnostic.lineNumber;
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace Cppcheck
|
||||
@@ -39,6 +39,7 @@ public:
|
||||
bool isValid() const {
|
||||
return !fileName.isEmpty() && lineNumber > 0;
|
||||
}
|
||||
bool operator==(const Diagnostic& diagnostic) const;
|
||||
|
||||
Severity severity = Severity::Information;
|
||||
QString severityText;
|
||||
@@ -48,5 +49,7 @@ public:
|
||||
int lineNumber = 0;
|
||||
};
|
||||
|
||||
quint32 qHash(const Diagnostic &diagnostic);
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Cppcheck
|
||||
|
||||
41
src/plugins/cppcheck/cppcheckdiagnosticmanager.h
Normal file
41
src/plugins/cppcheck/cppcheckdiagnosticmanager.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 Sergey Morozov
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Cppcheck {
|
||||
namespace Internal {
|
||||
|
||||
class Diagnostic;
|
||||
|
||||
class CppcheckDiagnosticManager
|
||||
{
|
||||
public:
|
||||
virtual ~CppcheckDiagnosticManager() = default;
|
||||
virtual void add(const Diagnostic &diagnostic) = 0;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Cppcheck
|
||||
143
src/plugins/cppcheck/cppcheckdiagnosticsmodel.cpp
Normal file
143
src/plugins/cppcheck/cppcheckdiagnosticsmodel.cpp
Normal file
@@ -0,0 +1,143 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2019 Sergey Morozov
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "cppcheckdiagnosticsmodel.h"
|
||||
|
||||
#include <coreplugin/fileiconprovider.h>
|
||||
|
||||
#include <debugger/analyzer/diagnosticlocation.h>
|
||||
|
||||
#include <utils/utilsicons.h>
|
||||
|
||||
namespace Cppcheck {
|
||||
namespace Internal {
|
||||
|
||||
using namespace Debugger;
|
||||
|
||||
FilePathItem::FilePathItem(const QString &filePath)
|
||||
: m_filePath(filePath)
|
||||
{}
|
||||
|
||||
QVariant FilePathItem::data(int column, int role) const
|
||||
{
|
||||
if (column == DiagnosticsModel::DiagnosticColumn) {
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
return m_filePath;
|
||||
case Qt::DecorationRole:
|
||||
return Core::FileIconProvider::icon(m_filePath);
|
||||
case Debugger::DetailedErrorView::FullTextRole:
|
||||
return m_filePath;
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
DiagnosticItem::DiagnosticItem(const Diagnostic &diagnostic)
|
||||
: m_diagnostic(diagnostic)
|
||||
{}
|
||||
|
||||
static QIcon getIcon(const Diagnostic::Severity severity)
|
||||
{
|
||||
switch (severity) {
|
||||
case Diagnostic::Severity::Error:
|
||||
return Utils::Icons::CRITICAL.icon();
|
||||
case Diagnostic::Severity::Warning:
|
||||
return Utils::Icons::WARNING.icon();
|
||||
default:
|
||||
return Utils::Icons::INFO.icon();
|
||||
}
|
||||
}
|
||||
|
||||
QVariant DiagnosticItem::data(int column, int role) const
|
||||
{
|
||||
if (column == DiagnosticsModel::DiagnosticColumn) {
|
||||
switch (role) {
|
||||
case DetailedErrorView::LocationRole: {
|
||||
const auto location = DiagnosticLocation(m_diagnostic.fileName.toString(),
|
||||
m_diagnostic.lineNumber,
|
||||
0);
|
||||
return QVariant::fromValue(location);
|
||||
}
|
||||
case Qt::DisplayRole:
|
||||
return QString("%1: %2").arg(m_diagnostic.lineNumber).arg(m_diagnostic.message);
|
||||
case Qt::ToolTipRole:
|
||||
return QString("%1: %2").arg(m_diagnostic.severityText, m_diagnostic.checkId);
|
||||
case Qt::DecorationRole:
|
||||
return getIcon(m_diagnostic.severity);
|
||||
case Debugger::DetailedErrorView::FullTextRole:
|
||||
return QString("%1:%2: %3")
|
||||
.arg(m_diagnostic.fileName.toString())
|
||||
.arg(m_diagnostic.lineNumber)
|
||||
.arg(m_diagnostic.message);
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
DiagnosticsModel::DiagnosticsModel(QObject *parent)
|
||||
: BaseModel(parent)
|
||||
{
|
||||
setHeader({tr("Diagnostic")});
|
||||
}
|
||||
|
||||
void DiagnosticsModel::clear()
|
||||
{
|
||||
const auto hasData = !m_diagnostics.isEmpty();
|
||||
m_filePathToItem.clear();
|
||||
m_diagnostics.clear();
|
||||
BaseModel::clear();
|
||||
if (hasData)
|
||||
emit hasDataChanged(false);
|
||||
}
|
||||
|
||||
void DiagnosticsModel::add(const Diagnostic &diagnostic)
|
||||
{
|
||||
if (m_diagnostics.contains(diagnostic))
|
||||
return;
|
||||
|
||||
const auto hasData = !m_diagnostics.isEmpty();
|
||||
m_diagnostics.insert(diagnostic);
|
||||
if (!hasData)
|
||||
emit hasDataChanged(true);
|
||||
|
||||
const QString filePath = diagnostic.fileName.toString();
|
||||
FilePathItem *&filePathItem = m_filePathToItem[filePath];
|
||||
if (!filePathItem) {
|
||||
filePathItem = new FilePathItem(filePath);
|
||||
rootItem()->appendChild(filePathItem);
|
||||
}
|
||||
|
||||
filePathItem->appendChild(new DiagnosticItem(diagnostic));
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Cppcheck
|
||||
81
src/plugins/cppcheck/cppcheckdiagnosticsmodel.h
Normal file
81
src/plugins/cppcheck/cppcheckdiagnosticsmodel.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2019 Sergey Morozov
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cppcheck/cppcheckdiagnostic.h>
|
||||
#include <cppcheck/cppcheckdiagnosticmanager.h>
|
||||
|
||||
#include <debugger/analyzer/detailederrorview.h>
|
||||
|
||||
#include <utils/treemodel.h>
|
||||
|
||||
namespace Cppcheck {
|
||||
namespace Internal {
|
||||
|
||||
class DiagnosticsModel;
|
||||
|
||||
class FilePathItem : public Utils::TreeItem
|
||||
{
|
||||
public:
|
||||
explicit FilePathItem(const QString &filePath);
|
||||
QVariant data(int column, int role) const override;
|
||||
|
||||
private:
|
||||
const QString m_filePath;
|
||||
};
|
||||
|
||||
class DiagnosticItem : public Utils::TreeItem
|
||||
{
|
||||
public:
|
||||
explicit DiagnosticItem(const Diagnostic &diagnostic);
|
||||
QVariant data(int column, int role) const override;
|
||||
|
||||
private:
|
||||
const Diagnostic m_diagnostic;
|
||||
};
|
||||
|
||||
using BaseModel = Utils::TreeModel<Utils::TreeItem, FilePathItem, DiagnosticItem>;
|
||||
|
||||
class DiagnosticsModel : public BaseModel, public CppcheckDiagnosticManager
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Column {DiagnosticColumn};
|
||||
|
||||
explicit DiagnosticsModel(QObject *parent = nullptr);
|
||||
void clear();
|
||||
void add(const Diagnostic &diagnostic) override;
|
||||
|
||||
signals:
|
||||
void hasDataChanged(bool hasData);
|
||||
|
||||
private:
|
||||
QHash<QString, FilePathItem *> m_filePathToItem;
|
||||
QSet<Diagnostic> m_diagnostics;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Cppcheck
|
||||
118
src/plugins/cppcheck/cppcheckdiagnosticview.cpp
Normal file
118
src/plugins/cppcheck/cppcheckdiagnosticview.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2019 Sergey Morozov
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "cppcheckdiagnosticview.h"
|
||||
|
||||
#include <coreplugin/editormanager/editormanager.h>
|
||||
|
||||
#include <debugger/analyzer/diagnosticlocation.h>
|
||||
|
||||
namespace Cppcheck {
|
||||
namespace Internal {
|
||||
|
||||
using namespace Debugger;
|
||||
|
||||
DiagnosticView::DiagnosticView(QWidget *parent)
|
||||
: DetailedErrorView(parent)
|
||||
{
|
||||
setFrameStyle(QFrame::NoFrame);
|
||||
setAttribute(Qt::WA_MacShowFocusRect, false);
|
||||
setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||
setAutoScroll(false);
|
||||
sortByColumn(DiagnosticColumn, Qt::AscendingOrder);
|
||||
setObjectName("CppcheckIssuesView");
|
||||
setWindowTitle(tr("Cppcheck Diagnostics"));
|
||||
setHeaderHidden(true);
|
||||
}
|
||||
|
||||
void DiagnosticView::goNext()
|
||||
{
|
||||
const auto totalFiles = model()->rowCount();
|
||||
if (totalFiles == 0)
|
||||
return;
|
||||
|
||||
const QModelIndex currentIndex = selectionModel()->currentIndex();
|
||||
const QModelIndex parent = currentIndex.parent();
|
||||
const auto onDiagnostic = parent.isValid();
|
||||
if (onDiagnostic && currentIndex.row() < model()->rowCount(parent) - 1) {
|
||||
selectIndex(currentIndex.sibling(currentIndex.row() + 1, 0));
|
||||
return;
|
||||
}
|
||||
auto newFileRow = 0;
|
||||
if (!currentIndex.isValid()) // not selected
|
||||
newFileRow = 0;
|
||||
else if (!onDiagnostic) // selected file
|
||||
newFileRow = currentIndex.row();
|
||||
else // selected last item in file
|
||||
newFileRow = parent.row() == totalFiles - 1 ? 0 : parent.row() + 1;
|
||||
const QModelIndex newParent = model()->index(newFileRow, 0);
|
||||
selectIndex(model()->index(0, 0, newParent));
|
||||
}
|
||||
|
||||
void DiagnosticView::goBack()
|
||||
{
|
||||
const auto totalFiles = model()->rowCount();
|
||||
if (totalFiles == 0)
|
||||
return;
|
||||
|
||||
const QModelIndex currentIndex = selectionModel()->currentIndex();
|
||||
const QModelIndex parent = currentIndex.parent();
|
||||
const auto onDiagnostic = parent.isValid();
|
||||
if (onDiagnostic && currentIndex.row() > 0) {
|
||||
selectIndex(currentIndex.sibling(currentIndex.row() - 1, 0));
|
||||
return;
|
||||
}
|
||||
auto newFileRow = 0;
|
||||
if (!currentIndex.isValid()) // not selected
|
||||
newFileRow = totalFiles - 1;
|
||||
else if (!onDiagnostic) // selected file
|
||||
newFileRow = currentIndex.row() == 0 ? totalFiles - 1 : currentIndex.row() - 1;
|
||||
else // selected first item in file
|
||||
newFileRow = parent.row() == 0 ? totalFiles - 1 : parent.row() - 1;
|
||||
const QModelIndex newParent = model()->index(newFileRow, 0);
|
||||
const auto newParentRows = model()->rowCount(newParent);
|
||||
selectIndex(model()->index(newParentRows - 1, 0, newParent));
|
||||
}
|
||||
|
||||
DiagnosticView::~DiagnosticView() = default;
|
||||
|
||||
void DiagnosticView::openEditorForCurrentIndex()
|
||||
{
|
||||
const QVariant v = model()->data(currentIndex(), Debugger::DetailedErrorView::LocationRole);
|
||||
const auto loc = v.value<Debugger::DiagnosticLocation>();
|
||||
if (loc.isValid())
|
||||
Core::EditorManager::openEditorAt(loc.filePath, loc.line, loc.column - 1);
|
||||
}
|
||||
|
||||
void DiagnosticView::mouseDoubleClickEvent(QMouseEvent *event)
|
||||
{
|
||||
openEditorForCurrentIndex();
|
||||
DetailedErrorView::mouseDoubleClickEvent(event);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Cppcheck
|
||||
|
||||
//#include "clangtoolsdiagnosticview.moc"
|
||||
49
src/plugins/cppcheck/cppcheckdiagnosticview.h
Normal file
49
src/plugins/cppcheck/cppcheckdiagnosticview.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2019 Sergey Morozov
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <debugger/analyzer/detailederrorview.h>
|
||||
|
||||
namespace Cppcheck {
|
||||
namespace Internal {
|
||||
|
||||
class DiagnosticView : public Debugger::DetailedErrorView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DiagnosticView(QWidget *parent = nullptr);
|
||||
~DiagnosticView() override;
|
||||
|
||||
void goNext() override;
|
||||
void goBack() override;
|
||||
|
||||
private:
|
||||
void openEditorForCurrentIndex();
|
||||
void mouseDoubleClickEvent(QMouseEvent *event) override;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Cppcheck
|
||||
108
src/plugins/cppcheck/cppcheckmanualrundialog.cpp
Normal file
108
src/plugins/cppcheck/cppcheckmanualrundialog.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2019 Sergey Morozov
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "cppcheckmanualrundialog.h"
|
||||
#include "cppcheckoptions.h"
|
||||
|
||||
#include <projectexplorer/selectablefilesmodel.h>
|
||||
|
||||
#include <cpptools/projectinfo.h>
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QBoxLayout>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QPushButton>
|
||||
|
||||
namespace Cppcheck {
|
||||
namespace Internal {
|
||||
|
||||
ManualRunDialog::ManualRunDialog(const CppcheckOptions &options,
|
||||
const ProjectExplorer::Project *project)
|
||||
: QDialog(),
|
||||
m_options(new OptionsWidget(this)),
|
||||
m_model(new ProjectExplorer::SelectableFilesFromDirModel(this))
|
||||
{
|
||||
QTC_ASSERT(project, return );
|
||||
|
||||
setWindowTitle(tr("Cppcheck run configuration"));
|
||||
|
||||
auto view = new QTreeView;
|
||||
view->setHeaderHidden(true);
|
||||
view->setModel(m_model);
|
||||
|
||||
connect(m_model, &ProjectExplorer::SelectableFilesFromDirModel::parsingFinished,
|
||||
view, [this, view] {
|
||||
m_model->applyFilter("*.cpp;*.cxx;*.c;*.cc;*.C", {});
|
||||
view->expandToDepth(0);
|
||||
});
|
||||
m_model->startParsing(project->rootProjectDirectory());
|
||||
|
||||
auto buttons = new QDialogButtonBox;
|
||||
buttons->setStandardButtons(QDialogButtonBox::Cancel);
|
||||
connect(buttons, &QDialogButtonBox::accepted,
|
||||
this, &QDialog::accept);
|
||||
connect(buttons, &QDialogButtonBox::rejected,
|
||||
this, &QDialog::reject);
|
||||
|
||||
auto analyzeButton = new QPushButton(tr("Analyze"));
|
||||
buttons->addButton(analyzeButton, QDialogButtonBox::AcceptRole);
|
||||
analyzeButton->setEnabled(m_model->hasCheckedFiles());
|
||||
connect(m_model, &QAbstractItemModel::dataChanged,
|
||||
analyzeButton, [this, analyzeButton]() {
|
||||
analyzeButton->setEnabled(m_model->hasCheckedFiles());
|
||||
});
|
||||
|
||||
auto layout = new QVBoxLayout(this);
|
||||
layout->addWidget(m_options);
|
||||
layout->addWidget(view);
|
||||
layout->addWidget(buttons);
|
||||
|
||||
if (auto layout = m_options->layout())
|
||||
layout->setMargin(0);
|
||||
|
||||
m_options->load(options);
|
||||
}
|
||||
|
||||
CppcheckOptions ManualRunDialog::options() const
|
||||
{
|
||||
CppcheckOptions result;
|
||||
m_options->save(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
Utils::FilePathList ManualRunDialog::filePaths() const
|
||||
{
|
||||
return m_model->selectedFiles();
|
||||
}
|
||||
|
||||
QSize ManualRunDialog::sizeHint() const
|
||||
{
|
||||
const auto original = QDialog::sizeHint();
|
||||
return {original.width() * 2, original.height()};
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Cppcheck
|
||||
63
src/plugins/cppcheck/cppcheckmanualrundialog.h
Normal file
63
src/plugins/cppcheck/cppcheckmanualrundialog.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2019 Sergey Morozov
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
namespace Utils {
|
||||
class FilePath;
|
||||
using FilePathList = QList<FilePath>;
|
||||
} // namespace Utils
|
||||
|
||||
namespace ProjectExplorer {
|
||||
class Project;
|
||||
class SelectableFilesFromDirModel;
|
||||
} // namespace ProjectExplorer
|
||||
|
||||
namespace Cppcheck {
|
||||
namespace Internal {
|
||||
|
||||
class OptionsWidget;
|
||||
class CppcheckOptions;
|
||||
|
||||
class ManualRunDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ManualRunDialog(const CppcheckOptions &options,
|
||||
const ProjectExplorer::Project *project);
|
||||
|
||||
CppcheckOptions options() const;
|
||||
Utils::FilePathList filePaths() const;
|
||||
QSize sizeHint() const override;
|
||||
|
||||
private:
|
||||
OptionsWidget *m_options;
|
||||
ProjectExplorer::SelectableFilesFromDirModel *m_model;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Cppcheck
|
||||
@@ -45,120 +45,98 @@
|
||||
namespace Cppcheck {
|
||||
namespace Internal {
|
||||
|
||||
class OptionsWidget final : public QWidget
|
||||
OptionsWidget::OptionsWidget(QWidget *parent)
|
||||
: QWidget(parent),
|
||||
m_binary(new Utils::PathChooser(this)),
|
||||
m_customArguments(new QLineEdit(this)),
|
||||
m_ignorePatterns(new QLineEdit(this)),
|
||||
m_warning(new QCheckBox(tr("Warnings"), this)),
|
||||
m_style(new QCheckBox(tr("Style"), this)),
|
||||
m_performance(new QCheckBox(tr("Performance"), this)),
|
||||
m_portability(new QCheckBox(tr("Portability"), this)),
|
||||
m_information(new QCheckBox(tr("Information"), this)),
|
||||
m_unusedFunction(new QCheckBox(tr("Unused functions"), this)),
|
||||
m_missingInclude(new QCheckBox(tr("Missing includes"), this)),
|
||||
m_inconclusive(new QCheckBox(tr("Inconclusive errors"), this)),
|
||||
m_forceDefines(new QCheckBox(tr("Check all define combinations"), this)),
|
||||
m_showOutput(new QCheckBox(tr("Show raw output"), this)),
|
||||
m_addIncludePaths(new QCheckBox(tr("Add include paths"), this)),
|
||||
m_guessArguments(new QCheckBox(tr("Calculate additional arguments"), this))
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(CppcheckOptionsPage)
|
||||
public:
|
||||
explicit OptionsWidget(QWidget *parent = nullptr)
|
||||
: QWidget(parent),
|
||||
m_binary(new Utils::PathChooser(this)),
|
||||
m_customArguments(new QLineEdit(this)),
|
||||
m_ignorePatterns(new QLineEdit(this)),
|
||||
m_warning(new QCheckBox(tr("Warnings"), this)),
|
||||
m_style(new QCheckBox(tr("Style"), this)),
|
||||
m_performance(new QCheckBox(tr("Performance"), this)),
|
||||
m_portability(new QCheckBox(tr("Portability"), this)),
|
||||
m_information(new QCheckBox(tr("Information"), this)),
|
||||
m_unusedFunction(new QCheckBox(tr("Unused functions"), this)),
|
||||
m_missingInclude(new QCheckBox(tr("Missing includes"), this)),
|
||||
m_inconclusive(new QCheckBox(tr("Inconclusive errors"), this)),
|
||||
m_forceDefines(new QCheckBox(tr("Check all define combinations"), this)),
|
||||
m_showOutput(new QCheckBox(tr("Show raw output"), this)),
|
||||
m_addIncludePaths(new QCheckBox(tr("Add include paths"), this)),
|
||||
m_guessArguments(new QCheckBox(tr("Calculate additional arguments"), this))
|
||||
{
|
||||
m_binary->setExpectedKind(Utils::PathChooser::ExistingCommand);
|
||||
m_binary->setCommandVersionArguments({"--version"});
|
||||
m_binary->setExpectedKind(Utils::PathChooser::ExistingCommand);
|
||||
m_binary->setCommandVersionArguments({"--version"});
|
||||
|
||||
auto variableChooser = new Core::VariableChooser(this);
|
||||
variableChooser->addSupportedWidget (m_customArguments);
|
||||
auto variableChooser = new Core::VariableChooser(this);
|
||||
variableChooser->addSupportedWidget (m_customArguments);
|
||||
|
||||
m_unusedFunction->setToolTip(tr("Disables multithreaded check."));
|
||||
m_ignorePatterns->setToolTip(tr("Comma-separated wildcards of full file paths. "
|
||||
"Files still can be checked if others include them."));
|
||||
m_addIncludePaths->setToolTip(tr("Can find missing includes but makes "
|
||||
"checking slower. Use only when needed."));
|
||||
m_guessArguments->setToolTip(tr("Like C++ standard and language."));
|
||||
m_unusedFunction->setToolTip(tr("Disables multithreaded check."));
|
||||
m_ignorePatterns->setToolTip(tr("Comma-separated wildcards of full file paths. "
|
||||
"Files still can be checked if others include them."));
|
||||
m_addIncludePaths->setToolTip(tr("Can find missing includes but makes "
|
||||
"checking slower. Use only when needed."));
|
||||
m_guessArguments->setToolTip(tr("Like C++ standard and language."));
|
||||
|
||||
auto layout = new QFormLayout(this);
|
||||
layout->addRow(tr("Binary:"), m_binary);
|
||||
auto layout = new QFormLayout(this);
|
||||
layout->addRow(tr("Binary:"), m_binary);
|
||||
|
||||
auto checks = new Utils::FlowLayout;
|
||||
layout->addRow(tr("Checks:"), checks);
|
||||
checks->addWidget(m_warning);
|
||||
checks->addWidget(m_style);
|
||||
checks->addWidget(m_performance);
|
||||
checks->addWidget(m_portability);
|
||||
checks->addWidget(m_information);
|
||||
checks->addWidget(m_unusedFunction);
|
||||
checks->addWidget(m_missingInclude);
|
||||
auto checks = new Utils::FlowLayout;
|
||||
layout->addRow(tr("Checks:"), checks);
|
||||
checks->addWidget(m_warning);
|
||||
checks->addWidget(m_style);
|
||||
checks->addWidget(m_performance);
|
||||
checks->addWidget(m_portability);
|
||||
checks->addWidget(m_information);
|
||||
checks->addWidget(m_unusedFunction);
|
||||
checks->addWidget(m_missingInclude);
|
||||
|
||||
layout->addRow(tr("Custom arguments:"), m_customArguments);
|
||||
layout->addRow(tr("Ignored file patterns:"), m_ignorePatterns);
|
||||
auto flags = new Utils::FlowLayout;
|
||||
layout->addRow(flags);
|
||||
flags->addWidget(m_inconclusive);
|
||||
flags->addWidget(m_forceDefines);
|
||||
flags->addWidget(m_showOutput);
|
||||
flags->addWidget(m_addIncludePaths);
|
||||
flags->addWidget(m_guessArguments);
|
||||
}
|
||||
layout->addRow(tr("Custom arguments:"), m_customArguments);
|
||||
layout->addRow(tr("Ignored file patterns:"), m_ignorePatterns);
|
||||
auto flags = new Utils::FlowLayout;
|
||||
layout->addRow(flags);
|
||||
flags->addWidget(m_inconclusive);
|
||||
flags->addWidget(m_forceDefines);
|
||||
flags->addWidget(m_showOutput);
|
||||
flags->addWidget(m_addIncludePaths);
|
||||
flags->addWidget(m_guessArguments);
|
||||
}
|
||||
|
||||
void load(const CppcheckOptions &options)
|
||||
{
|
||||
m_binary->setPath(options.binary);
|
||||
m_customArguments->setText(options.customArguments);
|
||||
m_ignorePatterns->setText(options.ignoredPatterns);
|
||||
m_warning->setChecked(options.warning);
|
||||
m_style->setChecked(options.style);
|
||||
m_performance->setChecked(options.performance);
|
||||
m_portability->setChecked(options.portability);
|
||||
m_information->setChecked(options.information);
|
||||
m_unusedFunction->setChecked(options.unusedFunction);
|
||||
m_missingInclude->setChecked(options.missingInclude);
|
||||
m_inconclusive->setChecked(options.inconclusive);
|
||||
m_forceDefines->setChecked(options.forceDefines);
|
||||
m_showOutput->setChecked(options.showOutput);
|
||||
m_addIncludePaths->setChecked(options.addIncludePaths);
|
||||
m_guessArguments->setChecked(options.guessArguments);
|
||||
}
|
||||
void OptionsWidget::load(const CppcheckOptions &options)
|
||||
{
|
||||
m_binary->setPath(options.binary);
|
||||
m_customArguments->setText(options.customArguments);
|
||||
m_ignorePatterns->setText(options.ignoredPatterns);
|
||||
m_warning->setChecked(options.warning);
|
||||
m_style->setChecked(options.style);
|
||||
m_performance->setChecked(options.performance);
|
||||
m_portability->setChecked(options.portability);
|
||||
m_information->setChecked(options.information);
|
||||
m_unusedFunction->setChecked(options.unusedFunction);
|
||||
m_missingInclude->setChecked(options.missingInclude);
|
||||
m_inconclusive->setChecked(options.inconclusive);
|
||||
m_forceDefines->setChecked(options.forceDefines);
|
||||
m_showOutput->setChecked(options.showOutput);
|
||||
m_addIncludePaths->setChecked(options.addIncludePaths);
|
||||
m_guessArguments->setChecked(options.guessArguments);
|
||||
}
|
||||
|
||||
void save(CppcheckOptions &options) const
|
||||
{
|
||||
options.binary = m_binary->path();
|
||||
options.customArguments = m_customArguments->text();
|
||||
options.ignoredPatterns = m_ignorePatterns->text();
|
||||
options.warning = m_warning->isChecked();
|
||||
options.style = m_style->isChecked();
|
||||
options.performance = m_performance->isChecked();
|
||||
options.portability = m_portability->isChecked();
|
||||
options.information = m_information->isChecked();
|
||||
options.unusedFunction = m_unusedFunction->isChecked();
|
||||
options.missingInclude = m_missingInclude->isChecked();
|
||||
options.inconclusive = m_inconclusive->isChecked();
|
||||
options.forceDefines = m_forceDefines->isChecked();
|
||||
options.showOutput = m_showOutput->isChecked();
|
||||
options.addIncludePaths = m_addIncludePaths->isChecked();
|
||||
options.guessArguments = m_guessArguments->isChecked();
|
||||
}
|
||||
|
||||
private:
|
||||
Utils::PathChooser *m_binary = nullptr;
|
||||
QLineEdit *m_customArguments = nullptr;
|
||||
QLineEdit *m_ignorePatterns = nullptr;
|
||||
QCheckBox *m_warning = nullptr;
|
||||
QCheckBox *m_style = nullptr;
|
||||
QCheckBox *m_performance = nullptr;
|
||||
QCheckBox *m_portability = nullptr;
|
||||
QCheckBox *m_information = nullptr;
|
||||
QCheckBox *m_unusedFunction = nullptr;
|
||||
QCheckBox *m_missingInclude = nullptr;
|
||||
QCheckBox *m_inconclusive = nullptr;
|
||||
QCheckBox *m_forceDefines = nullptr;
|
||||
QCheckBox *m_showOutput = nullptr;
|
||||
QCheckBox *m_addIncludePaths = nullptr;
|
||||
QCheckBox *m_guessArguments = nullptr;
|
||||
};
|
||||
void OptionsWidget::save(CppcheckOptions &options) const
|
||||
{
|
||||
options.binary = m_binary->path();
|
||||
options.customArguments = m_customArguments->text();
|
||||
options.ignoredPatterns = m_ignorePatterns->text();
|
||||
options.warning = m_warning->isChecked();
|
||||
options.style = m_style->isChecked();
|
||||
options.performance = m_performance->isChecked();
|
||||
options.portability = m_portability->isChecked();
|
||||
options.information = m_information->isChecked();
|
||||
options.unusedFunction = m_unusedFunction->isChecked();
|
||||
options.missingInclude = m_missingInclude->isChecked();
|
||||
options.inconclusive = m_inconclusive->isChecked();
|
||||
options.forceDefines = m_forceDefines->isChecked();
|
||||
options.showOutput = m_showOutput->isChecked();
|
||||
options.addIncludePaths = m_addIncludePaths->isChecked();
|
||||
options.guessArguments = m_guessArguments->isChecked();
|
||||
}
|
||||
|
||||
CppcheckOptionsPage::CppcheckOptionsPage(CppcheckTool &tool, CppcheckTrigger &trigger):
|
||||
m_tool(tool),
|
||||
|
||||
@@ -27,7 +27,16 @@
|
||||
|
||||
#include <coreplugin/dialogs/ioptionspage.h>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QPointer>
|
||||
#include <QWidget>
|
||||
|
||||
class QLineEdit;
|
||||
class QCheckBox;
|
||||
|
||||
namespace Utils {
|
||||
class PathChooser;
|
||||
}
|
||||
|
||||
namespace Cppcheck {
|
||||
namespace Internal {
|
||||
@@ -58,6 +67,32 @@ public:
|
||||
bool guessArguments = true;
|
||||
};
|
||||
|
||||
class OptionsWidget final : public QWidget
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(CppcheckOptionsPage)
|
||||
public:
|
||||
explicit OptionsWidget(QWidget *parent = nullptr);
|
||||
void load(const CppcheckOptions &options);
|
||||
void save(CppcheckOptions &options) const;
|
||||
|
||||
private:
|
||||
Utils::PathChooser *m_binary = nullptr;
|
||||
QLineEdit *m_customArguments = nullptr;
|
||||
QLineEdit *m_ignorePatterns = nullptr;
|
||||
QCheckBox *m_warning = nullptr;
|
||||
QCheckBox *m_style = nullptr;
|
||||
QCheckBox *m_performance = nullptr;
|
||||
QCheckBox *m_portability = nullptr;
|
||||
QCheckBox *m_information = nullptr;
|
||||
QCheckBox *m_unusedFunction = nullptr;
|
||||
QCheckBox *m_missingInclude = nullptr;
|
||||
QCheckBox *m_inconclusive = nullptr;
|
||||
QCheckBox *m_forceDefines = nullptr;
|
||||
QCheckBox *m_showOutput = nullptr;
|
||||
QCheckBox *m_addIncludePaths = nullptr;
|
||||
QCheckBox *m_guessArguments = nullptr;
|
||||
};
|
||||
|
||||
class CppcheckOptionsPage final : public Core::IOptionsPage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -23,16 +23,34 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "cppcheckoptions.h"
|
||||
#include "cppcheckplugin.h"
|
||||
#include "cppcheckconstants.h"
|
||||
#include "cppcheckdiagnosticview.h"
|
||||
#include "cppchecktextmarkmanager.h"
|
||||
#include "cppchecktool.h"
|
||||
#include "cppchecktrigger.h"
|
||||
#include "cppcheckdiagnosticsmodel.h"
|
||||
#include "cppcheckmanualrundialog.h"
|
||||
|
||||
#include <projectexplorer/session.h>
|
||||
#include <projectexplorer/projectexplorer.h>
|
||||
#include <projectexplorer/project.h>
|
||||
#include <projectexplorer/kitinformation.h>
|
||||
#include <projectexplorer/target.h>
|
||||
|
||||
#include <coreplugin/actionmanager/actioncontainer.h>
|
||||
#include <coreplugin/actionmanager/actionmanager.h>
|
||||
|
||||
#include <debugger/analyzer/analyzerconstants.h>
|
||||
#include <debugger/debuggermainwindow.h>
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/utilsicons.h>
|
||||
|
||||
namespace Cppcheck {
|
||||
namespace Internal {
|
||||
|
||||
class CppcheckPluginPrivate final
|
||||
class CppcheckPluginPrivate final : public QObject
|
||||
{
|
||||
public:
|
||||
explicit CppcheckPluginPrivate();
|
||||
@@ -40,13 +58,98 @@ public:
|
||||
CppcheckTool tool;
|
||||
CppcheckTrigger trigger;
|
||||
CppcheckOptionsPage options;
|
||||
DiagnosticsModel manualRunModel;
|
||||
CppcheckTool manualRunTool;
|
||||
Utils::Perspective perspective{Constants::PERSPECTIVE_ID,
|
||||
tr("Cppcheck", "CppcheckPlugin")};
|
||||
QAction *manualRunAction;
|
||||
|
||||
void startManualRun();
|
||||
void updateManualRunAction();
|
||||
};
|
||||
|
||||
CppcheckPluginPrivate::CppcheckPluginPrivate() :
|
||||
tool(marks),
|
||||
tool(marks, Constants::CHECK_PROGRESS_ID),
|
||||
trigger(marks, tool),
|
||||
options(tool, trigger)
|
||||
options(tool, trigger),
|
||||
manualRunTool(manualRunModel, Constants::MANUAL_CHECK_PROGRESS_ID)
|
||||
{
|
||||
manualRunTool.updateOptions(tool.options());
|
||||
|
||||
auto manualRunView = new DiagnosticView;
|
||||
manualRunView->setModel(&manualRunModel);
|
||||
perspective.addWindow(manualRunView, Utils::Perspective::SplitVertical, nullptr);
|
||||
|
||||
{
|
||||
// Go to previous diagnostic
|
||||
auto action = new QAction(this);
|
||||
action->setEnabled(false);
|
||||
action->setIcon(Utils::Icons::PREV_TOOLBAR.icon());
|
||||
action->setToolTip(tr("Go to previous diagnostic."));
|
||||
connect(action, &QAction::triggered,
|
||||
manualRunView, &Debugger::DetailedErrorView::goBack);
|
||||
connect (&manualRunModel, &DiagnosticsModel::hasDataChanged,
|
||||
action, &QAction::setEnabled);
|
||||
perspective.addToolBarAction(action);
|
||||
}
|
||||
|
||||
{
|
||||
// Go to next diagnostic
|
||||
auto action = new QAction(this);
|
||||
action->setEnabled(false);
|
||||
action->setIcon(Utils::Icons::NEXT_TOOLBAR.icon());
|
||||
action->setToolTip(tr("Go to next diagnostic."));
|
||||
connect(action, &QAction::triggered,
|
||||
manualRunView, &Debugger::DetailedErrorView::goNext);
|
||||
connect (&manualRunModel, &DiagnosticsModel::hasDataChanged,
|
||||
action, &QAction::setEnabled);
|
||||
perspective.addToolBarAction(action);
|
||||
}
|
||||
|
||||
{
|
||||
// Clear data
|
||||
auto action = new QAction(this);
|
||||
action->setEnabled(false);
|
||||
action->setIcon(Utils::Icons::CLEAN_TOOLBAR.icon());
|
||||
action->setToolTip(tr("Clear"));
|
||||
connect(action, &QAction::triggered,
|
||||
&manualRunModel, &DiagnosticsModel::clear);
|
||||
connect (&manualRunModel, &DiagnosticsModel::hasDataChanged,
|
||||
action, &QAction::setEnabled);
|
||||
perspective.addToolBarAction(action);
|
||||
}
|
||||
}
|
||||
|
||||
void CppcheckPluginPrivate::startManualRun() {
|
||||
auto project = ProjectExplorer::SessionManager::startupProject();
|
||||
if (!project)
|
||||
return;
|
||||
|
||||
ManualRunDialog dialog(manualRunTool.options(), project);
|
||||
if (dialog.exec() == ManualRunDialog::Rejected)
|
||||
return;
|
||||
|
||||
manualRunModel.clear();
|
||||
|
||||
const auto files = dialog.filePaths();
|
||||
if (files.isEmpty())
|
||||
return;
|
||||
|
||||
manualRunTool.setProject(project);
|
||||
manualRunTool.updateOptions(dialog.options());
|
||||
manualRunTool.check(files);
|
||||
perspective.select();
|
||||
}
|
||||
|
||||
void CppcheckPluginPrivate::updateManualRunAction()
|
||||
{
|
||||
using namespace ProjectExplorer;
|
||||
const Project *project = SessionManager::startupProject();
|
||||
const Target *target = SessionManager::startupTarget();
|
||||
const Core::Id cxx = ProjectExplorer::Constants::CXX_LANGUAGE_ID;
|
||||
const bool canRun = target && project->projectLanguages().contains(cxx)
|
||||
&& ToolChainKitAspect::toolChain(target->kit(), cxx);
|
||||
manualRunAction->setEnabled(canRun);
|
||||
}
|
||||
|
||||
CppcheckPlugin::CppcheckPlugin() = default;
|
||||
@@ -60,6 +163,23 @@ bool CppcheckPlugin::initialize(const QStringList &arguments, QString *errorStri
|
||||
|
||||
d.reset(new CppcheckPluginPrivate);
|
||||
|
||||
using namespace Core;
|
||||
ActionContainer *menu = ActionManager::actionContainer(Debugger::Constants::M_DEBUG_ANALYZER);
|
||||
|
||||
{
|
||||
auto action = new QAction(tr("Cppcheck..."), this);
|
||||
menu->addAction(ActionManager::registerAction(action, Constants::MANUAL_RUN_ACTION),
|
||||
Debugger::Constants::G_ANALYZER_TOOLS);
|
||||
connect(action, &QAction::triggered,
|
||||
d.get(), &CppcheckPluginPrivate::startManualRun);
|
||||
d->manualRunAction = action;
|
||||
}
|
||||
|
||||
using ProjectExplorer::ProjectExplorerPlugin;
|
||||
connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::updateRunActions,
|
||||
d.get(), &CppcheckPluginPrivate::updateManualRunAction);
|
||||
d->updateManualRunAction();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cppcheck/cppcheckdiagnosticmanager.h>
|
||||
|
||||
#include <utils/fileutils.h>
|
||||
|
||||
#include <unordered_map>
|
||||
@@ -35,13 +37,13 @@ namespace Internal {
|
||||
class Diagnostic;
|
||||
class CppcheckTextMark;
|
||||
|
||||
class CppcheckTextMarkManager final
|
||||
class CppcheckTextMarkManager final : public CppcheckDiagnosticManager
|
||||
{
|
||||
public:
|
||||
explicit CppcheckTextMarkManager();
|
||||
~CppcheckTextMarkManager();
|
||||
~CppcheckTextMarkManager() override;
|
||||
|
||||
void add(const Diagnostic &diagnostic);
|
||||
void add(const Diagnostic &diagnostic) override;
|
||||
void clearFiles(const Utils::FilePathList &files);
|
||||
|
||||
private:
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "cppcheckconstants.h"
|
||||
#include "cppcheckdiagnostic.h"
|
||||
#include "cppcheckoptions.h"
|
||||
#include "cppcheckrunner.h"
|
||||
@@ -45,10 +44,12 @@
|
||||
namespace Cppcheck {
|
||||
namespace Internal {
|
||||
|
||||
CppcheckTool::CppcheckTool(CppcheckTextMarkManager &marks) :
|
||||
m_marks(marks),
|
||||
CppcheckTool::CppcheckTool(CppcheckDiagnosticManager &manager,
|
||||
const Core::Id &progressId) :
|
||||
m_manager(manager),
|
||||
m_progressRegexp("^.* checked (\\d+)% done$"),
|
||||
m_messageRegexp("^(.+),(\\d+),(\\w+),(\\w+),(.*)$")
|
||||
m_messageRegexp("^(.+),(\\d+),(\\w+),(\\w+),(.*)$"),
|
||||
m_progressId(progressId)
|
||||
{
|
||||
m_runner = std::make_unique<CppcheckRunner>(*this);
|
||||
QTC_ASSERT(m_progressRegexp.isValid(), return);
|
||||
@@ -246,8 +247,7 @@ void CppcheckTool::startParsing()
|
||||
|
||||
m_progress = std::make_unique<QFutureInterface<void>>();
|
||||
const Core::FutureProgress *progress = Core::ProgressManager::addTask(
|
||||
m_progress->future(), QObject::tr("Cppcheck"),
|
||||
Constants::CHECK_PROGRESS_ID);
|
||||
m_progress->future(), QObject::tr("Cppcheck"), m_progressId);
|
||||
QObject::connect(progress, &Core::FutureProgress::canceled,
|
||||
this, [this]{stop({});});
|
||||
m_progress->setProgressRange(0, 100);
|
||||
@@ -310,7 +310,7 @@ void CppcheckTool::parseErrorLine(const QString &line)
|
||||
diagnostic.checkId = match.captured(Id);
|
||||
diagnostic.message = match.captured(Message);
|
||||
if (diagnostic.isValid())
|
||||
m_marks.add(diagnostic);
|
||||
m_manager.add(diagnostic);
|
||||
}
|
||||
|
||||
void CppcheckTool::finishParsing()
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace Cppcheck {
|
||||
namespace Internal {
|
||||
|
||||
class CppcheckRunner;
|
||||
class CppcheckTextMarkManager;
|
||||
class CppcheckDiagnosticManager;
|
||||
class CppcheckOptions;
|
||||
|
||||
class CppcheckTool final : public QObject
|
||||
@@ -58,7 +58,7 @@ class CppcheckTool final : public QObject
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CppcheckTool(CppcheckTextMarkManager &marks);
|
||||
CppcheckTool(CppcheckDiagnosticManager &manager, const Core::Id &progressId);
|
||||
~CppcheckTool() override;
|
||||
|
||||
void updateOptions(const CppcheckOptions &options);
|
||||
@@ -78,7 +78,7 @@ private:
|
||||
void addToQueue(const Utils::FilePathList &files, CppTools::ProjectPart &part);
|
||||
QStringList additionalArguments(const CppTools::ProjectPart &part) const;
|
||||
|
||||
CppcheckTextMarkManager &m_marks;
|
||||
CppcheckDiagnosticManager &m_manager;
|
||||
CppcheckOptions m_options;
|
||||
QPointer<ProjectExplorer::Project> m_project;
|
||||
std::unique_ptr<CppcheckRunner> m_runner;
|
||||
@@ -87,6 +87,7 @@ private:
|
||||
QVector<QRegExp> m_filters;
|
||||
QRegularExpression m_progressRegexp;
|
||||
QRegularExpression m_messageRegexp;
|
||||
Core::Id m_progressId;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
Reference in New Issue
Block a user