forked from qt-creator/qt-creator
ClangTools: Merge ClangTidyClazyTool into ClangTool
Change-Id: Ieb6c4994ddcff9339a9cfb25c82e23dd2d2e8912 Reviewed-by: Cristian Adam <cristian.adam@qt.io> Reviewed-by: Nikolai Kosjar <nikolai.kosjar@qt.io>
This commit is contained in:
@@ -14,7 +14,6 @@ add_qtc_plugin(ClangTools
|
|||||||
clangfixitsrefactoringchanges.cpp clangfixitsrefactoringchanges.h
|
clangfixitsrefactoringchanges.cpp clangfixitsrefactoringchanges.h
|
||||||
clangselectablefilesdialog.cpp clangselectablefilesdialog.h clangselectablefilesdialog.ui
|
clangselectablefilesdialog.cpp clangselectablefilesdialog.h clangselectablefilesdialog.ui
|
||||||
clangtidyclazyrunner.cpp clangtidyclazyrunner.h
|
clangtidyclazyrunner.cpp clangtidyclazyrunner.h
|
||||||
clangtidyclazytool.cpp clangtidyclazytool.h
|
|
||||||
clangtool.cpp clangtool.h
|
clangtool.cpp clangtool.h
|
||||||
clangtoolruncontrol.cpp clangtoolruncontrol.h
|
clangtoolruncontrol.cpp clangtoolruncontrol.h
|
||||||
clangtoolrunner.cpp clangtoolrunner.h
|
clangtoolrunner.cpp clangtoolrunner.h
|
||||||
|
@@ -1,559 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
**
|
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
|
||||||
** 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 "clangtidyclazytool.h"
|
|
||||||
|
|
||||||
#include "clangfixitsrefactoringchanges.h"
|
|
||||||
#include "clangselectablefilesdialog.h"
|
|
||||||
#include "clangtoolruncontrol.h"
|
|
||||||
#include "clangtoolsconstants.h"
|
|
||||||
#include "clangtoolsdiagnosticmodel.h"
|
|
||||||
#include "clangtoolslogfilereader.h"
|
|
||||||
#include "clangtoolsdiagnosticview.h"
|
|
||||||
#include "clangtoolsprojectsettings.h"
|
|
||||||
#include "clangtoolssettings.h"
|
|
||||||
|
|
||||||
#include <coreplugin/actionmanager/actioncontainer.h>
|
|
||||||
#include <coreplugin/actionmanager/actionmanager.h>
|
|
||||||
#include <coreplugin/icore.h>
|
|
||||||
#include <coreplugin/messagebox.h>
|
|
||||||
|
|
||||||
#include <debugger/analyzer/analyzermanager.h>
|
|
||||||
|
|
||||||
#include <projectexplorer/kitinformation.h>
|
|
||||||
#include <projectexplorer/projectexplorer.h>
|
|
||||||
#include <projectexplorer/projectexplorericons.h>
|
|
||||||
#include <projectexplorer/target.h>
|
|
||||||
#include <projectexplorer/session.h>
|
|
||||||
|
|
||||||
#include <utils/fancylineedit.h>
|
|
||||||
#include <utils/utilsicons.h>
|
|
||||||
|
|
||||||
#include <QAction>
|
|
||||||
#include <QFileDialog>
|
|
||||||
#include <QToolButton>
|
|
||||||
|
|
||||||
using namespace Core;
|
|
||||||
using namespace CppTools;
|
|
||||||
using namespace Debugger;
|
|
||||||
using namespace ProjectExplorer;
|
|
||||||
using namespace Utils;
|
|
||||||
|
|
||||||
namespace ClangTools {
|
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
static ClangTidyClazyTool *s_instance;
|
|
||||||
|
|
||||||
class ApplyFixIts
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
class RefactoringFileInfo
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
bool isValid() const { return file.isValid(); }
|
|
||||||
|
|
||||||
FixitsRefactoringFile file;
|
|
||||||
QVector<DiagnosticItem *> diagnosticItems;
|
|
||||||
bool hasScheduledFixits = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
ApplyFixIts(const QVector<DiagnosticItem *> &diagnosticItems)
|
|
||||||
{
|
|
||||||
for (DiagnosticItem *diagnosticItem : diagnosticItems) {
|
|
||||||
const QString &filePath = diagnosticItem->diagnostic().location.filePath;
|
|
||||||
QTC_ASSERT(!filePath.isEmpty(), continue);
|
|
||||||
|
|
||||||
// Get or create refactoring file
|
|
||||||
RefactoringFileInfo &fileInfo = m_refactoringFileInfos[filePath];
|
|
||||||
if (!fileInfo.isValid())
|
|
||||||
fileInfo.file = FixitsRefactoringFile(filePath);
|
|
||||||
|
|
||||||
// Append item
|
|
||||||
fileInfo.diagnosticItems += diagnosticItem;
|
|
||||||
if (diagnosticItem->fixItStatus() == FixitStatus::Scheduled)
|
|
||||||
fileInfo.hasScheduledFixits = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void addFixitOperations(DiagnosticItem *diagnosticItem,
|
|
||||||
const FixitsRefactoringFile &file, bool apply)
|
|
||||||
{
|
|
||||||
if (!diagnosticItem->hasNewFixIts())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Did we already created the fixit operations?
|
|
||||||
ReplacementOperations currentOps = diagnosticItem->fixitOperations();
|
|
||||||
if (!currentOps.isEmpty()) {
|
|
||||||
for (ReplacementOperation *op : currentOps)
|
|
||||||
op->apply = apply;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Collect/construct the fixit operations
|
|
||||||
ReplacementOperations replacements;
|
|
||||||
|
|
||||||
for (const ExplainingStep &step : diagnosticItem->diagnostic().explainingSteps) {
|
|
||||||
if (!step.isFixIt)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const Debugger::DiagnosticLocation start = step.ranges.first();
|
|
||||||
const Debugger::DiagnosticLocation end = step.ranges.last();
|
|
||||||
const int startPos = file.position(start.filePath, start.line, start.column);
|
|
||||||
const int endPos = file.position(start.filePath, end.line, end.column);
|
|
||||||
|
|
||||||
auto op = new ReplacementOperation;
|
|
||||||
op->pos = startPos;
|
|
||||||
op->length = endPos - startPos;
|
|
||||||
op->text = step.message;
|
|
||||||
op->fileName = start.filePath;
|
|
||||||
op->apply = apply;
|
|
||||||
|
|
||||||
replacements += op;
|
|
||||||
}
|
|
||||||
|
|
||||||
diagnosticItem->setFixitOperations(replacements);
|
|
||||||
}
|
|
||||||
|
|
||||||
void apply(ClangToolsDiagnosticModel *model)
|
|
||||||
{
|
|
||||||
for (auto it = m_refactoringFileInfos.begin(); it != m_refactoringFileInfos.end(); ++it) {
|
|
||||||
RefactoringFileInfo &fileInfo = it.value();
|
|
||||||
|
|
||||||
QVector<DiagnosticItem *> itemsScheduledOrSchedulable;
|
|
||||||
QVector<DiagnosticItem *> itemsScheduled;
|
|
||||||
QVector<DiagnosticItem *> itemsSchedulable;
|
|
||||||
|
|
||||||
// Construct refactoring operations
|
|
||||||
for (DiagnosticItem *diagnosticItem : fileInfo.diagnosticItems) {
|
|
||||||
const FixitStatus fixItStatus = diagnosticItem->fixItStatus();
|
|
||||||
|
|
||||||
const bool isScheduled = fixItStatus == FixitStatus::Scheduled;
|
|
||||||
const bool isSchedulable = fileInfo.hasScheduledFixits
|
|
||||||
&& fixItStatus == FixitStatus::NotScheduled;
|
|
||||||
|
|
||||||
if (isScheduled || isSchedulable) {
|
|
||||||
addFixitOperations(diagnosticItem, fileInfo.file, isScheduled);
|
|
||||||
itemsScheduledOrSchedulable += diagnosticItem;
|
|
||||||
if (isScheduled)
|
|
||||||
itemsScheduled += diagnosticItem;
|
|
||||||
else
|
|
||||||
itemsSchedulable += diagnosticItem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Collect replacements
|
|
||||||
ReplacementOperations ops;
|
|
||||||
for (DiagnosticItem *item : itemsScheduledOrSchedulable)
|
|
||||||
ops += item->fixitOperations();
|
|
||||||
|
|
||||||
if (ops.empty())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Apply file
|
|
||||||
QVector<DiagnosticItem *> itemsApplied;
|
|
||||||
QVector<DiagnosticItem *> itemsFailedToApply;
|
|
||||||
QVector<DiagnosticItem *> itemsInvalidated;
|
|
||||||
|
|
||||||
fileInfo.file.setReplacements(ops);
|
|
||||||
model->removeWatchedPath(ops.first()->fileName);
|
|
||||||
if (fileInfo.file.apply()) {
|
|
||||||
itemsApplied = itemsScheduled;
|
|
||||||
} else {
|
|
||||||
itemsFailedToApply = itemsScheduled;
|
|
||||||
itemsInvalidated = itemsSchedulable;
|
|
||||||
}
|
|
||||||
model->addWatchedPath(ops.first()->fileName);
|
|
||||||
|
|
||||||
// Update DiagnosticItem state
|
|
||||||
for (DiagnosticItem *diagnosticItem : itemsScheduled)
|
|
||||||
diagnosticItem->setFixItStatus(FixitStatus::Applied);
|
|
||||||
for (DiagnosticItem *diagnosticItem : itemsFailedToApply)
|
|
||||||
diagnosticItem->setFixItStatus(FixitStatus::FailedToApply);
|
|
||||||
for (DiagnosticItem *diagnosticItem : itemsInvalidated)
|
|
||||||
diagnosticItem->setFixItStatus(FixitStatus::Invalidated);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
QMap<QString, RefactoringFileInfo> m_refactoringFileInfos;
|
|
||||||
};
|
|
||||||
|
|
||||||
ClangTidyClazyTool::ClangTidyClazyTool()
|
|
||||||
: ClangTool("Clang-Tidy and Clazy")
|
|
||||||
{
|
|
||||||
setObjectName("ClangTidyClazyTool");
|
|
||||||
s_instance = this;
|
|
||||||
|
|
||||||
m_diagnosticFilterModel = new DiagnosticFilterModel(this);
|
|
||||||
m_diagnosticFilterModel->setSourceModel(m_diagnosticModel);
|
|
||||||
m_diagnosticFilterModel->setDynamicSortFilter(true);
|
|
||||||
|
|
||||||
m_diagnosticView = new DiagnosticView;
|
|
||||||
initDiagnosticView();
|
|
||||||
m_diagnosticView->setModel(m_diagnosticFilterModel);
|
|
||||||
m_diagnosticView->setSortingEnabled(true);
|
|
||||||
m_diagnosticView->sortByColumn(Debugger::DetailedErrorView::DiagnosticColumn,
|
|
||||||
Qt::AscendingOrder);
|
|
||||||
m_diagnosticView->setObjectName(QLatin1String("ClangTidyClazyIssuesView"));
|
|
||||||
m_diagnosticView->setWindowTitle(tr("Clang-Tidy and Clazy Diagnostics"));
|
|
||||||
|
|
||||||
foreach (auto * const model,
|
|
||||||
QList<QAbstractItemModel *>({m_diagnosticModel, m_diagnosticFilterModel})) {
|
|
||||||
connect(model, &QAbstractItemModel::rowsInserted,
|
|
||||||
this, &ClangTidyClazyTool::handleStateUpdate);
|
|
||||||
connect(model, &QAbstractItemModel::rowsRemoved,
|
|
||||||
this, &ClangTidyClazyTool::handleStateUpdate);
|
|
||||||
connect(model, &QAbstractItemModel::modelReset,
|
|
||||||
this, &ClangTidyClazyTool::handleStateUpdate);
|
|
||||||
connect(model, &QAbstractItemModel::layoutChanged, // For QSortFilterProxyModel::invalidate()
|
|
||||||
this, &ClangTidyClazyTool::handleStateUpdate);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Go to previous diagnostic
|
|
||||||
auto action = new QAction(this);
|
|
||||||
action->setDisabled(true);
|
|
||||||
action->setIcon(Utils::Icons::PREV_TOOLBAR.icon());
|
|
||||||
action->setToolTip(tr("Go to previous diagnostic."));
|
|
||||||
connect(action, &QAction::triggered, m_diagnosticView, &DetailedErrorView::goBack);
|
|
||||||
m_goBack = action;
|
|
||||||
|
|
||||||
// Go to next diagnostic
|
|
||||||
action = new QAction(this);
|
|
||||||
action->setDisabled(true);
|
|
||||||
action->setIcon(Utils::Icons::NEXT_TOOLBAR.icon());
|
|
||||||
action->setToolTip(tr("Go to next diagnostic."));
|
|
||||||
connect(action, &QAction::triggered, m_diagnosticView, &DetailedErrorView::goNext);
|
|
||||||
m_goNext = action;
|
|
||||||
|
|
||||||
// Load diagnostics from file
|
|
||||||
action = new QAction(this);
|
|
||||||
action->setIcon(Utils::Icons::OPENFILE_TOOLBAR.icon());
|
|
||||||
action->setToolTip(tr("Load Diagnostics from YAML Files exported with \"-export-fixes\"."));
|
|
||||||
connect(action, &QAction::triggered, this, &ClangTidyClazyTool::loadDiagnosticsFromFiles);
|
|
||||||
m_loadExported = action;
|
|
||||||
|
|
||||||
// Clear data
|
|
||||||
action = new QAction(this);
|
|
||||||
action->setDisabled(true);
|
|
||||||
action->setIcon(Utils::Icons::CLEAN_TOOLBAR.icon());
|
|
||||||
action->setToolTip(tr("Clear"));
|
|
||||||
connect(action, &QAction::triggered, [this](){
|
|
||||||
m_clear->setEnabled(false);
|
|
||||||
m_diagnosticModel->clear();
|
|
||||||
Debugger::showPermanentStatusMessage(QString());
|
|
||||||
});
|
|
||||||
m_clear = action;
|
|
||||||
|
|
||||||
// Expand/Collapse
|
|
||||||
action = new QAction(this);
|
|
||||||
action->setDisabled(true);
|
|
||||||
action->setCheckable(true);
|
|
||||||
action->setIcon(Utils::Icons::EXPAND_ALL_TOOLBAR.icon());
|
|
||||||
action->setToolTip(tr("Expand All"));
|
|
||||||
connect(action, &QAction::toggled, [this](bool checked){
|
|
||||||
if (checked) {
|
|
||||||
m_expandCollapse->setToolTip(tr("Collapse All"));
|
|
||||||
m_diagnosticView->expandAll();
|
|
||||||
} else {
|
|
||||||
m_expandCollapse->setToolTip(tr("Expand All"));
|
|
||||||
m_diagnosticView->collapseAll();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
m_expandCollapse = action;
|
|
||||||
|
|
||||||
// Filter line edit
|
|
||||||
m_filterLineEdit = new Utils::FancyLineEdit();
|
|
||||||
m_filterLineEdit->setFiltering(true);
|
|
||||||
m_filterLineEdit->setPlaceholderText(tr("Filter Diagnostics"));
|
|
||||||
m_filterLineEdit->setHistoryCompleter("CppTools.ClangTidyClazyIssueFilter", true);
|
|
||||||
connect(m_filterLineEdit, &Utils::FancyLineEdit::filterChanged, [this](const QString &filter) {
|
|
||||||
m_diagnosticFilterModel->setFilterRegExp(
|
|
||||||
QRegExp(filter, Qt::CaseSensitive, QRegExp::WildcardUnix));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Apply fixits button
|
|
||||||
m_applyFixitsButton = new QToolButton;
|
|
||||||
m_applyFixitsButton->setText(tr("Apply Fixits"));
|
|
||||||
m_applyFixitsButton->setEnabled(false);
|
|
||||||
connect(m_diagnosticModel,
|
|
||||||
&ClangToolsDiagnosticModel::fixItsToApplyCountChanged,
|
|
||||||
[this](int c) {
|
|
||||||
m_applyFixitsButton->setEnabled(c);
|
|
||||||
static_cast<DiagnosticView *>(m_diagnosticView.data())->setSelectedFixItsCount(c);
|
|
||||||
});
|
|
||||||
connect(m_applyFixitsButton, &QToolButton::clicked, [this]() {
|
|
||||||
QVector<DiagnosticItem *> diagnosticItems;
|
|
||||||
m_diagnosticModel->forItemsAtLevel<2>([&](DiagnosticItem *item){
|
|
||||||
diagnosticItems += item;
|
|
||||||
});
|
|
||||||
|
|
||||||
ApplyFixIts(diagnosticItems).apply(m_diagnosticModel);
|
|
||||||
});
|
|
||||||
|
|
||||||
ActionContainer *menu = ActionManager::actionContainer(Debugger::Constants::M_DEBUG_ANALYZER);
|
|
||||||
const QString toolTip = tr("Clang-Tidy and Clazy use a customized Clang executable from the "
|
|
||||||
"Clang project to search for diagnostics.");
|
|
||||||
|
|
||||||
m_perspective.addWindow(m_diagnosticView, Perspective::SplitVertical, nullptr);
|
|
||||||
|
|
||||||
action = new QAction(tr("Clang-Tidy and Clazy..."), this);
|
|
||||||
action->setToolTip(toolTip);
|
|
||||||
menu->addAction(ActionManager::registerAction(action, "ClangTidyClazy.Action"),
|
|
||||||
Debugger::Constants::G_ANALYZER_TOOLS);
|
|
||||||
QObject::connect(action, &QAction::triggered, this, [this]() {
|
|
||||||
startTool(ClangTidyClazyTool::FileSelection::AskUser);
|
|
||||||
});
|
|
||||||
QObject::connect(m_startAction, &QAction::triggered, action, &QAction::triggered);
|
|
||||||
QObject::connect(m_startAction, &QAction::changed, action, [action, this] {
|
|
||||||
action->setEnabled(m_startAction->isEnabled());
|
|
||||||
});
|
|
||||||
|
|
||||||
QObject::connect(m_startOnCurrentFileAction, &QAction::triggered, this, [this] {
|
|
||||||
startTool(ClangTidyClazyTool::FileSelection::CurrentFile);
|
|
||||||
});
|
|
||||||
|
|
||||||
m_perspective.addToolBarAction(m_startAction);
|
|
||||||
m_perspective.addToolBarAction(m_startOnCurrentFileAction);
|
|
||||||
m_perspective.addToolBarAction(m_stopAction);
|
|
||||||
m_perspective.addToolBarAction(m_loadExported);
|
|
||||||
m_perspective.addToolBarAction(m_clear);
|
|
||||||
m_perspective.addToolBarAction(m_goBack);
|
|
||||||
m_perspective.addToolBarAction(m_goNext);
|
|
||||||
m_perspective.addToolBarAction(m_expandCollapse);
|
|
||||||
m_perspective.addToolBarWidget(m_filterLineEdit);
|
|
||||||
m_perspective.addToolBarWidget(m_applyFixitsButton);
|
|
||||||
|
|
||||||
updateRunActions();
|
|
||||||
|
|
||||||
connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::updateRunActions,
|
|
||||||
this, &ClangTidyClazyTool::updateRunActions);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ClangTidyClazyTool *ClangTidyClazyTool::instance()
|
|
||||||
{
|
|
||||||
return s_instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClangTidyClazyTool::selectPerspective()
|
|
||||||
{
|
|
||||||
m_perspective.select();
|
|
||||||
}
|
|
||||||
|
|
||||||
static RunSettings runSettings(Project *project)
|
|
||||||
{
|
|
||||||
auto *projectSettings = ClangToolsProjectSettingsManager::getSettings(project);
|
|
||||||
if (projectSettings->useGlobalSettings())
|
|
||||||
return ClangToolsSettings::instance()->runSettings();
|
|
||||||
return projectSettings->runSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClangTidyClazyTool::startTool(FileSelection fileSelection)
|
|
||||||
{
|
|
||||||
Project *project = SessionManager::startupProject();
|
|
||||||
QTC_ASSERT(project, return);
|
|
||||||
QTC_ASSERT(project->activeTarget(), return);
|
|
||||||
|
|
||||||
auto runControl = new RunControl(Constants::CLANGTIDYCLAZY_RUN_MODE);
|
|
||||||
runControl->setDisplayName(tr("Clang-Tidy and Clazy"));
|
|
||||||
runControl->setIcon(ProjectExplorer::Icons::ANALYZER_START_SMALL_TOOLBAR);
|
|
||||||
runControl->setTarget(project->activeTarget());
|
|
||||||
|
|
||||||
const FileInfos fileInfos = collectFileInfos(project, fileSelection);
|
|
||||||
if (fileInfos.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
const bool preventBuild = fileSelection == FileSelection::CurrentFile;
|
|
||||||
auto clangTool = new ClangToolRunWorker(runControl,
|
|
||||||
runSettings(project),
|
|
||||||
fileInfos,
|
|
||||||
preventBuild);
|
|
||||||
|
|
||||||
m_stopAction->disconnect();
|
|
||||||
connect(m_stopAction, &QAction::triggered, runControl, [runControl] {
|
|
||||||
runControl->appendMessage(tr("Clang-Tidy and Clazy tool stopped by user."),
|
|
||||||
NormalMessageFormat);
|
|
||||||
runControl->initiateStop();
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(runControl, &RunControl::stopped, this, [this, clangTool] {
|
|
||||||
bool success = clangTool->success();
|
|
||||||
setToolBusy(false);
|
|
||||||
m_running = false;
|
|
||||||
handleStateUpdate();
|
|
||||||
updateRunActions();
|
|
||||||
emit finished(success);
|
|
||||||
});
|
|
||||||
|
|
||||||
m_perspective.select();
|
|
||||||
|
|
||||||
m_diagnosticModel->clear();
|
|
||||||
|
|
||||||
setToolBusy(true);
|
|
||||||
m_diagnosticFilterModel->setProject(project);
|
|
||||||
m_running = true;
|
|
||||||
handleStateUpdate();
|
|
||||||
updateRunActions();
|
|
||||||
|
|
||||||
ProjectExplorerPlugin::startRunControl(runControl);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClangTidyClazyTool::updateRunActions()
|
|
||||||
{
|
|
||||||
if (m_toolBusy) {
|
|
||||||
QString tooltipText = tr("Clang-Tidy and Clazy are still running.");
|
|
||||||
|
|
||||||
m_startAction->setEnabled(false);
|
|
||||||
m_startAction->setToolTip(tooltipText);
|
|
||||||
|
|
||||||
m_startOnCurrentFileAction->setEnabled(false);
|
|
||||||
m_startOnCurrentFileAction->setToolTip(tooltipText);
|
|
||||||
|
|
||||||
m_stopAction->setEnabled(true);
|
|
||||||
m_loadExported->setEnabled(false);
|
|
||||||
m_clear->setEnabled(false);
|
|
||||||
} else {
|
|
||||||
QString toolTipStart = m_startAction->text();
|
|
||||||
QString toolTipStartOnCurrentFile = m_startOnCurrentFileAction->text();
|
|
||||||
|
|
||||||
Project *project = SessionManager::startupProject();
|
|
||||||
Target *target = project ? project->activeTarget() : nullptr;
|
|
||||||
const Core::Id cxx = ProjectExplorer::Constants::CXX_LANGUAGE_ID;
|
|
||||||
bool canRun = target && project->projectLanguages().contains(cxx)
|
|
||||||
&& ToolChainKitAspect::toolChain(target->kit(), cxx);
|
|
||||||
if (!canRun)
|
|
||||||
toolTipStart = toolTipStartOnCurrentFile = tr("This is not a C/C++ project.");
|
|
||||||
|
|
||||||
m_startAction->setEnabled(canRun);
|
|
||||||
m_startAction->setToolTip(toolTipStart);
|
|
||||||
|
|
||||||
m_startOnCurrentFileAction->setEnabled(canRun);
|
|
||||||
m_startOnCurrentFileAction->setToolTip(toolTipStartOnCurrentFile);
|
|
||||||
|
|
||||||
m_stopAction->setEnabled(false);
|
|
||||||
m_loadExported->setEnabled(true);
|
|
||||||
m_clear->setEnabled(m_diagnosticModel->diagnostics().count());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClangTidyClazyTool::loadDiagnosticsFromFiles()
|
|
||||||
{
|
|
||||||
// Ask user for files
|
|
||||||
const QStringList filePaths
|
|
||||||
= QFileDialog::getOpenFileNames(Core::ICore::mainWindow(),
|
|
||||||
tr("Select YAML Files with Diagnostics"),
|
|
||||||
QDir::homePath(),
|
|
||||||
tr("YAML Files (*.yml *.yaml);;All Files (*)"));
|
|
||||||
if (filePaths.isEmpty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Load files
|
|
||||||
Diagnostics diagnostics;
|
|
||||||
QString errors;
|
|
||||||
for (const QString &filePath : filePaths) {
|
|
||||||
QString currentError;
|
|
||||||
diagnostics << readExportedDiagnostics(Utils::FilePath::fromString(filePath),
|
|
||||||
{},
|
|
||||||
¤tError);
|
|
||||||
|
|
||||||
if (!currentError.isEmpty()) {
|
|
||||||
if (!errors.isEmpty())
|
|
||||||
errors.append("\n");
|
|
||||||
errors.append(currentError);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show errors
|
|
||||||
if (!errors.isEmpty())
|
|
||||||
AsynchronousMessageBox::critical(tr("Error Loading Diagnostics"), errors);
|
|
||||||
|
|
||||||
// Show imported
|
|
||||||
m_diagnosticModel->clear();
|
|
||||||
onNewDiagnosticsAvailable(diagnostics);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClangTidyClazyTool::handleStateUpdate()
|
|
||||||
{
|
|
||||||
QTC_ASSERT(m_goBack, return);
|
|
||||||
QTC_ASSERT(m_goNext, return);
|
|
||||||
QTC_ASSERT(m_diagnosticModel, return);
|
|
||||||
QTC_ASSERT(m_diagnosticFilterModel, return);
|
|
||||||
|
|
||||||
const int issuesFound = m_diagnosticModel->diagnostics().count();
|
|
||||||
const int issuesVisible = m_diagnosticFilterModel->rowCount();
|
|
||||||
m_goBack->setEnabled(issuesVisible > 1);
|
|
||||||
m_goNext->setEnabled(issuesVisible > 1);
|
|
||||||
m_clear->setEnabled(issuesFound > 0);
|
|
||||||
m_expandCollapse->setEnabled(issuesVisible);
|
|
||||||
|
|
||||||
m_loadExported->setEnabled(!m_running);
|
|
||||||
|
|
||||||
QString message;
|
|
||||||
if (m_running) {
|
|
||||||
if (issuesFound)
|
|
||||||
message = tr("Running - %n diagnostics", nullptr, issuesFound);
|
|
||||||
else
|
|
||||||
message = tr("Running - No diagnostics");
|
|
||||||
} else {
|
|
||||||
if (issuesFound)
|
|
||||||
message = tr("Finished - %n diagnostics", nullptr, issuesFound);
|
|
||||||
else
|
|
||||||
message = tr("Finished - No diagnostics");
|
|
||||||
}
|
|
||||||
|
|
||||||
Debugger::showPermanentStatusMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
Diagnostics ClangTidyClazyTool::read(OutputFileFormat outputFileFormat,
|
|
||||||
const QString &logFilePath,
|
|
||||||
const QString &mainFilePath,
|
|
||||||
const QSet<Utils::FilePath> &projectFiles,
|
|
||||||
QString *errorMessage) const
|
|
||||||
{
|
|
||||||
const auto acceptFromFilePath = [projectFiles](const Utils::FilePath &filePath) {
|
|
||||||
return projectFiles.contains(filePath);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (outputFileFormat == OutputFileFormat::Yaml) {
|
|
||||||
return readExportedDiagnostics(Utils::FilePath::fromString(logFilePath),
|
|
||||||
acceptFromFilePath,
|
|
||||||
errorMessage);
|
|
||||||
}
|
|
||||||
return readSerializedDiagnostics(Utils::FilePath::fromString(logFilePath),
|
|
||||||
Utils::FilePath::fromString(mainFilePath),
|
|
||||||
acceptFromFilePath,
|
|
||||||
errorMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClangTidyClazyTool::onNewDiagnosticsAvailable(const Diagnostics &diagnostics)
|
|
||||||
{
|
|
||||||
ClangTool::onNewDiagnosticsAvailable(diagnostics);
|
|
||||||
if (!m_diagnosticFilterModel->filterRegExp().pattern().isEmpty())
|
|
||||||
m_diagnosticFilterModel->invalidateFilter();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Internal
|
|
||||||
} // namespace ClangTools
|
|
||||||
|
|
@@ -1,87 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
**
|
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
|
||||||
** 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 "clangtool.h"
|
|
||||||
|
|
||||||
#include <debugger/debuggermainwindow.h>
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
class QToolButton;
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
namespace Utils { class FancyLineEdit; }
|
|
||||||
|
|
||||||
namespace ClangTools {
|
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
class DiagnosticFilterModel;
|
|
||||||
|
|
||||||
const char ClangTidyClazyPerspectiveId[] = "ClangTidyClazy.Perspective";
|
|
||||||
|
|
||||||
class ClangTidyClazyTool final : public ClangTool
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
ClangTidyClazyTool();
|
|
||||||
|
|
||||||
static ClangTidyClazyTool *instance();
|
|
||||||
|
|
||||||
void selectPerspective();
|
|
||||||
|
|
||||||
void startTool(FileSelection fileSelection) final;
|
|
||||||
|
|
||||||
Diagnostics read(OutputFileFormat outputFileFormat,
|
|
||||||
const QString &logFilePath,
|
|
||||||
const QString &mainFilePath,
|
|
||||||
const QSet<Utils::FilePath> &projectFiles,
|
|
||||||
QString *errorMessage) const final;
|
|
||||||
|
|
||||||
void onNewDiagnosticsAvailable(const Diagnostics &diagnostics) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void handleStateUpdate() final;
|
|
||||||
|
|
||||||
void updateRunActions();
|
|
||||||
void loadDiagnosticsFromFiles();
|
|
||||||
|
|
||||||
DiagnosticFilterModel *m_diagnosticFilterModel = nullptr;
|
|
||||||
|
|
||||||
Utils::FancyLineEdit *m_filterLineEdit = nullptr;
|
|
||||||
QToolButton *m_applyFixitsButton = nullptr;
|
|
||||||
|
|
||||||
QAction *m_goBack = nullptr;
|
|
||||||
QAction *m_goNext = nullptr;
|
|
||||||
QAction *m_loadExported = nullptr;
|
|
||||||
QAction *m_clear = nullptr;
|
|
||||||
QAction *m_expandCollapse = nullptr;
|
|
||||||
|
|
||||||
Utils::Perspective m_perspective{ClangTidyClazyPerspectiveId, tr("Clang-Tidy and Clazy")};
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Internal
|
|
||||||
} // namespace ClangTools
|
|
@@ -25,10 +25,16 @@
|
|||||||
|
|
||||||
#include "clangtool.h"
|
#include "clangtool.h"
|
||||||
|
|
||||||
|
#include "clangfixitsrefactoringchanges.h"
|
||||||
#include "clangselectablefilesdialog.h"
|
#include "clangselectablefilesdialog.h"
|
||||||
|
#include "clangtoolruncontrol.h"
|
||||||
#include "clangtoolsconstants.h"
|
#include "clangtoolsconstants.h"
|
||||||
#include "clangtoolsdiagnostic.h"
|
#include "clangtoolsdiagnostic.h"
|
||||||
#include "clangtoolsdiagnosticmodel.h"
|
#include "clangtoolsdiagnosticmodel.h"
|
||||||
|
#include "clangtoolsdiagnosticview.h"
|
||||||
|
#include "clangtoolslogfilereader.h"
|
||||||
|
#include "clangtoolsprojectsettings.h"
|
||||||
|
#include "clangtoolssettings.h"
|
||||||
#include "clangtoolsutils.h"
|
#include "clangtoolsutils.h"
|
||||||
|
|
||||||
#include <coreplugin/actionmanager/actioncontainer.h>
|
#include <coreplugin/actionmanager/actioncontainer.h>
|
||||||
@@ -36,6 +42,7 @@
|
|||||||
#include <coreplugin/coreconstants.h>
|
#include <coreplugin/coreconstants.h>
|
||||||
#include <coreplugin/editormanager/editormanager.h>
|
#include <coreplugin/editormanager/editormanager.h>
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
|
#include <coreplugin/messagebox.h>
|
||||||
|
|
||||||
#include <cpptools/cppmodelmanager.h>
|
#include <cpptools/cppmodelmanager.h>
|
||||||
|
|
||||||
@@ -44,19 +51,22 @@
|
|||||||
#include <projectexplorer/kitinformation.h>
|
#include <projectexplorer/kitinformation.h>
|
||||||
#include <projectexplorer/projectexplorer.h>
|
#include <projectexplorer/projectexplorer.h>
|
||||||
#include <projectexplorer/projectexplorericons.h>
|
#include <projectexplorer/projectexplorericons.h>
|
||||||
#include <projectexplorer/target.h>
|
|
||||||
#include <projectexplorer/session.h>
|
#include <projectexplorer/session.h>
|
||||||
|
#include <projectexplorer/target.h>
|
||||||
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
|
#include <utils/fancylineedit.h>
|
||||||
#include <utils/fancymainwindow.h>
|
#include <utils/fancymainwindow.h>
|
||||||
#include <utils/utilsicons.h>
|
#include <utils/utilsicons.h>
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
|
#include <QFileDialog>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QSortFilterProxyModel>
|
#include <QSortFilterProxyModel>
|
||||||
#include <QToolButton>
|
#include <QToolButton>
|
||||||
|
|
||||||
using namespace Core;
|
using namespace Core;
|
||||||
|
using namespace CppTools;
|
||||||
using namespace Debugger;
|
using namespace Debugger;
|
||||||
using namespace ProjectExplorer;
|
using namespace ProjectExplorer;
|
||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
@@ -64,6 +74,142 @@ using namespace Utils;
|
|||||||
namespace ClangTools {
|
namespace ClangTools {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
|
static ClangTool *s_instance;
|
||||||
|
|
||||||
|
class ApplyFixIts
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
class RefactoringFileInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool isValid() const { return file.isValid(); }
|
||||||
|
|
||||||
|
FixitsRefactoringFile file;
|
||||||
|
QVector<DiagnosticItem *> diagnosticItems;
|
||||||
|
bool hasScheduledFixits = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
ApplyFixIts(const QVector<DiagnosticItem *> &diagnosticItems)
|
||||||
|
{
|
||||||
|
for (DiagnosticItem *diagnosticItem : diagnosticItems) {
|
||||||
|
const QString &filePath = diagnosticItem->diagnostic().location.filePath;
|
||||||
|
QTC_ASSERT(!filePath.isEmpty(), continue);
|
||||||
|
|
||||||
|
// Get or create refactoring file
|
||||||
|
RefactoringFileInfo &fileInfo = m_refactoringFileInfos[filePath];
|
||||||
|
if (!fileInfo.isValid())
|
||||||
|
fileInfo.file = FixitsRefactoringFile(filePath);
|
||||||
|
|
||||||
|
// Append item
|
||||||
|
fileInfo.diagnosticItems += diagnosticItem;
|
||||||
|
if (diagnosticItem->fixItStatus() == FixitStatus::Scheduled)
|
||||||
|
fileInfo.hasScheduledFixits = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void addFixitOperations(DiagnosticItem *diagnosticItem,
|
||||||
|
const FixitsRefactoringFile &file, bool apply)
|
||||||
|
{
|
||||||
|
if (!diagnosticItem->hasNewFixIts())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Did we already created the fixit operations?
|
||||||
|
ReplacementOperations currentOps = diagnosticItem->fixitOperations();
|
||||||
|
if (!currentOps.isEmpty()) {
|
||||||
|
for (ReplacementOperation *op : currentOps)
|
||||||
|
op->apply = apply;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect/construct the fixit operations
|
||||||
|
ReplacementOperations replacements;
|
||||||
|
|
||||||
|
for (const ExplainingStep &step : diagnosticItem->diagnostic().explainingSteps) {
|
||||||
|
if (!step.isFixIt)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const Debugger::DiagnosticLocation start = step.ranges.first();
|
||||||
|
const Debugger::DiagnosticLocation end = step.ranges.last();
|
||||||
|
const int startPos = file.position(start.filePath, start.line, start.column);
|
||||||
|
const int endPos = file.position(start.filePath, end.line, end.column);
|
||||||
|
|
||||||
|
auto op = new ReplacementOperation;
|
||||||
|
op->pos = startPos;
|
||||||
|
op->length = endPos - startPos;
|
||||||
|
op->text = step.message;
|
||||||
|
op->fileName = start.filePath;
|
||||||
|
op->apply = apply;
|
||||||
|
|
||||||
|
replacements += op;
|
||||||
|
}
|
||||||
|
|
||||||
|
diagnosticItem->setFixitOperations(replacements);
|
||||||
|
}
|
||||||
|
|
||||||
|
void apply(ClangToolsDiagnosticModel *model)
|
||||||
|
{
|
||||||
|
for (auto it = m_refactoringFileInfos.begin(); it != m_refactoringFileInfos.end(); ++it) {
|
||||||
|
RefactoringFileInfo &fileInfo = it.value();
|
||||||
|
|
||||||
|
QVector<DiagnosticItem *> itemsScheduledOrSchedulable;
|
||||||
|
QVector<DiagnosticItem *> itemsScheduled;
|
||||||
|
QVector<DiagnosticItem *> itemsSchedulable;
|
||||||
|
|
||||||
|
// Construct refactoring operations
|
||||||
|
for (DiagnosticItem *diagnosticItem : fileInfo.diagnosticItems) {
|
||||||
|
const FixitStatus fixItStatus = diagnosticItem->fixItStatus();
|
||||||
|
|
||||||
|
const bool isScheduled = fixItStatus == FixitStatus::Scheduled;
|
||||||
|
const bool isSchedulable = fileInfo.hasScheduledFixits
|
||||||
|
&& fixItStatus == FixitStatus::NotScheduled;
|
||||||
|
|
||||||
|
if (isScheduled || isSchedulable) {
|
||||||
|
addFixitOperations(diagnosticItem, fileInfo.file, isScheduled);
|
||||||
|
itemsScheduledOrSchedulable += diagnosticItem;
|
||||||
|
if (isScheduled)
|
||||||
|
itemsScheduled += diagnosticItem;
|
||||||
|
else
|
||||||
|
itemsSchedulable += diagnosticItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect replacements
|
||||||
|
ReplacementOperations ops;
|
||||||
|
for (DiagnosticItem *item : itemsScheduledOrSchedulable)
|
||||||
|
ops += item->fixitOperations();
|
||||||
|
|
||||||
|
if (ops.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Apply file
|
||||||
|
QVector<DiagnosticItem *> itemsApplied;
|
||||||
|
QVector<DiagnosticItem *> itemsFailedToApply;
|
||||||
|
QVector<DiagnosticItem *> itemsInvalidated;
|
||||||
|
|
||||||
|
fileInfo.file.setReplacements(ops);
|
||||||
|
model->removeWatchedPath(ops.first()->fileName);
|
||||||
|
if (fileInfo.file.apply()) {
|
||||||
|
itemsApplied = itemsScheduled;
|
||||||
|
} else {
|
||||||
|
itemsFailedToApply = itemsScheduled;
|
||||||
|
itemsInvalidated = itemsSchedulable;
|
||||||
|
}
|
||||||
|
model->addWatchedPath(ops.first()->fileName);
|
||||||
|
|
||||||
|
// Update DiagnosticItem state
|
||||||
|
for (DiagnosticItem *diagnosticItem : itemsScheduled)
|
||||||
|
diagnosticItem->setFixItStatus(FixitStatus::Applied);
|
||||||
|
for (DiagnosticItem *diagnosticItem : itemsFailedToApply)
|
||||||
|
diagnosticItem->setFixItStatus(FixitStatus::FailedToApply);
|
||||||
|
for (DiagnosticItem *diagnosticItem : itemsInvalidated)
|
||||||
|
diagnosticItem->setFixItStatus(FixitStatus::Invalidated);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QMap<QString, RefactoringFileInfo> m_refactoringFileInfos;
|
||||||
|
};
|
||||||
|
|
||||||
static FileInfos sortedFileInfos(const QVector<CppTools::ProjectPart::Ptr> &projectParts)
|
static FileInfos sortedFileInfos(const QVector<CppTools::ProjectPart::Ptr> &projectParts)
|
||||||
{
|
{
|
||||||
FileInfos fileInfos;
|
FileInfos fileInfos;
|
||||||
@@ -93,9 +239,24 @@ static FileInfos sortedFileInfos(const QVector<CppTools::ProjectPart::Ptr> &proj
|
|||||||
return fileInfos;
|
return fileInfos;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClangTool::ClangTool(const QString &name)
|
static RunSettings runSettings(Project *project)
|
||||||
: m_name(name)
|
|
||||||
{
|
{
|
||||||
|
auto *projectSettings = ClangToolsProjectSettingsManager::getSettings(project);
|
||||||
|
if (projectSettings->useGlobalSettings())
|
||||||
|
return ClangToolsSettings::instance()->runSettings();
|
||||||
|
return projectSettings->runSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
ClangTool *ClangTool::instance()
|
||||||
|
{
|
||||||
|
return s_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClangTool::ClangTool()
|
||||||
|
: m_name("Clang-Tidy and Clazy")
|
||||||
|
{
|
||||||
|
setObjectName("ClangTidyClazyTool");
|
||||||
|
s_instance = this;
|
||||||
m_diagnosticModel = new ClangToolsDiagnosticModel(this);
|
m_diagnosticModel = new ClangToolsDiagnosticModel(this);
|
||||||
|
|
||||||
const Utils::Icon RUN_FILE_OVERLAY(
|
const Utils::Icon RUN_FILE_OVERLAY(
|
||||||
@@ -120,6 +281,150 @@ ClangTool::ClangTool(const QString &name)
|
|||||||
m_startOnCurrentFileAction = action;
|
m_startOnCurrentFileAction = action;
|
||||||
|
|
||||||
m_stopAction = Debugger::createStopAction();
|
m_stopAction = Debugger::createStopAction();
|
||||||
|
|
||||||
|
m_diagnosticFilterModel = new DiagnosticFilterModel(this);
|
||||||
|
m_diagnosticFilterModel->setSourceModel(m_diagnosticModel);
|
||||||
|
m_diagnosticFilterModel->setDynamicSortFilter(true);
|
||||||
|
|
||||||
|
m_diagnosticView = new DiagnosticView;
|
||||||
|
initDiagnosticView();
|
||||||
|
m_diagnosticView->setModel(m_diagnosticFilterModel);
|
||||||
|
m_diagnosticView->setSortingEnabled(true);
|
||||||
|
m_diagnosticView->sortByColumn(Debugger::DetailedErrorView::DiagnosticColumn,
|
||||||
|
Qt::AscendingOrder);
|
||||||
|
m_diagnosticView->setObjectName(QLatin1String("ClangTidyClazyIssuesView"));
|
||||||
|
m_diagnosticView->setWindowTitle(tr("Clang-Tidy and Clazy Diagnostics"));
|
||||||
|
|
||||||
|
foreach (auto * const model,
|
||||||
|
QList<QAbstractItemModel *>({m_diagnosticModel, m_diagnosticFilterModel})) {
|
||||||
|
connect(model, &QAbstractItemModel::rowsInserted,
|
||||||
|
this, &ClangTool::handleStateUpdate);
|
||||||
|
connect(model, &QAbstractItemModel::rowsRemoved,
|
||||||
|
this, &ClangTool::handleStateUpdate);
|
||||||
|
connect(model, &QAbstractItemModel::modelReset,
|
||||||
|
this, &ClangTool::handleStateUpdate);
|
||||||
|
connect(model, &QAbstractItemModel::layoutChanged, // For QSortFilterProxyModel::invalidate()
|
||||||
|
this, &ClangTool::handleStateUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go to previous diagnostic
|
||||||
|
action = new QAction(this);
|
||||||
|
action->setDisabled(true);
|
||||||
|
action->setIcon(Utils::Icons::PREV_TOOLBAR.icon());
|
||||||
|
action->setToolTip(tr("Go to previous diagnostic."));
|
||||||
|
connect(action, &QAction::triggered, m_diagnosticView, &DetailedErrorView::goBack);
|
||||||
|
m_goBack = action;
|
||||||
|
|
||||||
|
// Go to next diagnostic
|
||||||
|
action = new QAction(this);
|
||||||
|
action->setDisabled(true);
|
||||||
|
action->setIcon(Utils::Icons::NEXT_TOOLBAR.icon());
|
||||||
|
action->setToolTip(tr("Go to next diagnostic."));
|
||||||
|
connect(action, &QAction::triggered, m_diagnosticView, &DetailedErrorView::goNext);
|
||||||
|
m_goNext = action;
|
||||||
|
|
||||||
|
// Load diagnostics from file
|
||||||
|
action = new QAction(this);
|
||||||
|
action->setIcon(Utils::Icons::OPENFILE_TOOLBAR.icon());
|
||||||
|
action->setToolTip(tr("Load Diagnostics from YAML Files exported with \"-export-fixes\"."));
|
||||||
|
connect(action, &QAction::triggered, this, &ClangTool::loadDiagnosticsFromFiles);
|
||||||
|
m_loadExported = action;
|
||||||
|
|
||||||
|
// Clear data
|
||||||
|
action = new QAction(this);
|
||||||
|
action->setDisabled(true);
|
||||||
|
action->setIcon(Utils::Icons::CLEAN_TOOLBAR.icon());
|
||||||
|
action->setToolTip(tr("Clear"));
|
||||||
|
connect(action, &QAction::triggered, [this](){
|
||||||
|
m_clear->setEnabled(false);
|
||||||
|
m_diagnosticModel->clear();
|
||||||
|
Debugger::showPermanentStatusMessage(QString());
|
||||||
|
});
|
||||||
|
m_clear = action;
|
||||||
|
|
||||||
|
// Expand/Collapse
|
||||||
|
action = new QAction(this);
|
||||||
|
action->setDisabled(true);
|
||||||
|
action->setCheckable(true);
|
||||||
|
action->setIcon(Utils::Icons::EXPAND_ALL_TOOLBAR.icon());
|
||||||
|
action->setToolTip(tr("Expand All"));
|
||||||
|
connect(action, &QAction::toggled, [this](bool checked){
|
||||||
|
if (checked) {
|
||||||
|
m_expandCollapse->setToolTip(tr("Collapse All"));
|
||||||
|
m_diagnosticView->expandAll();
|
||||||
|
} else {
|
||||||
|
m_expandCollapse->setToolTip(tr("Expand All"));
|
||||||
|
m_diagnosticView->collapseAll();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
m_expandCollapse = action;
|
||||||
|
|
||||||
|
// Filter line edit
|
||||||
|
m_filterLineEdit = new Utils::FancyLineEdit();
|
||||||
|
m_filterLineEdit->setFiltering(true);
|
||||||
|
m_filterLineEdit->setPlaceholderText(tr("Filter Diagnostics"));
|
||||||
|
m_filterLineEdit->setHistoryCompleter("CppTools.ClangTidyClazyIssueFilter", true);
|
||||||
|
connect(m_filterLineEdit, &Utils::FancyLineEdit::filterChanged, [this](const QString &filter) {
|
||||||
|
m_diagnosticFilterModel->setFilterRegExp(
|
||||||
|
QRegExp(filter, Qt::CaseSensitive, QRegExp::WildcardUnix));
|
||||||
|
});
|
||||||
|
|
||||||
|
// Apply fixits button
|
||||||
|
m_applyFixitsButton = new QToolButton;
|
||||||
|
m_applyFixitsButton->setText(tr("Apply Fixits"));
|
||||||
|
m_applyFixitsButton->setEnabled(false);
|
||||||
|
connect(m_diagnosticModel,
|
||||||
|
&ClangToolsDiagnosticModel::fixItsToApplyCountChanged,
|
||||||
|
[this](int c) {
|
||||||
|
m_applyFixitsButton->setEnabled(c);
|
||||||
|
static_cast<DiagnosticView *>(m_diagnosticView.data())->setSelectedFixItsCount(c);
|
||||||
|
});
|
||||||
|
connect(m_applyFixitsButton, &QToolButton::clicked, [this]() {
|
||||||
|
QVector<DiagnosticItem *> diagnosticItems;
|
||||||
|
m_diagnosticModel->forItemsAtLevel<2>([&](DiagnosticItem *item){
|
||||||
|
diagnosticItems += item;
|
||||||
|
});
|
||||||
|
|
||||||
|
ApplyFixIts(diagnosticItems).apply(m_diagnosticModel);
|
||||||
|
});
|
||||||
|
|
||||||
|
ActionContainer *menu = ActionManager::actionContainer(Debugger::Constants::M_DEBUG_ANALYZER);
|
||||||
|
const QString toolTip = tr("Clang-Tidy and Clazy use a customized Clang executable from the "
|
||||||
|
"Clang project to search for diagnostics.");
|
||||||
|
|
||||||
|
m_perspective.addWindow(m_diagnosticView, Perspective::SplitVertical, nullptr);
|
||||||
|
|
||||||
|
action = new QAction(tr("Clang-Tidy and Clazy..."), this);
|
||||||
|
action->setToolTip(toolTip);
|
||||||
|
menu->addAction(ActionManager::registerAction(action, "ClangTidyClazy.Action"),
|
||||||
|
Debugger::Constants::G_ANALYZER_TOOLS);
|
||||||
|
QObject::connect(action, &QAction::triggered, this, [this]() {
|
||||||
|
startTool(ClangTool::FileSelection::AskUser);
|
||||||
|
});
|
||||||
|
QObject::connect(m_startAction, &QAction::triggered, action, &QAction::triggered);
|
||||||
|
QObject::connect(m_startAction, &QAction::changed, action, [action, this] {
|
||||||
|
action->setEnabled(m_startAction->isEnabled());
|
||||||
|
});
|
||||||
|
|
||||||
|
QObject::connect(m_startOnCurrentFileAction, &QAction::triggered, this, [this] {
|
||||||
|
startTool(ClangTool::FileSelection::CurrentFile);
|
||||||
|
});
|
||||||
|
|
||||||
|
m_perspective.addToolBarAction(m_startAction);
|
||||||
|
m_perspective.addToolBarAction(m_startOnCurrentFileAction);
|
||||||
|
m_perspective.addToolBarAction(m_stopAction);
|
||||||
|
m_perspective.addToolBarAction(m_loadExported);
|
||||||
|
m_perspective.addToolBarAction(m_clear);
|
||||||
|
m_perspective.addToolBarAction(m_goBack);
|
||||||
|
m_perspective.addToolBarAction(m_goNext);
|
||||||
|
m_perspective.addToolBarAction(m_expandCollapse);
|
||||||
|
m_perspective.addToolBarWidget(m_filterLineEdit);
|
||||||
|
m_perspective.addToolBarWidget(m_applyFixitsButton);
|
||||||
|
|
||||||
|
updateRunActions();
|
||||||
|
|
||||||
|
connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::updateRunActions,
|
||||||
|
this, &ClangTool::updateRunActions);
|
||||||
}
|
}
|
||||||
|
|
||||||
ClangTool::~ClangTool()
|
ClangTool::~ClangTool()
|
||||||
@@ -127,6 +432,78 @@ ClangTool::~ClangTool()
|
|||||||
delete m_diagnosticView;
|
delete m_diagnosticView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClangTool::selectPerspective()
|
||||||
|
{
|
||||||
|
m_perspective.select();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClangTool::startTool(ClangTool::FileSelection fileSelection)
|
||||||
|
{
|
||||||
|
Project *project = SessionManager::startupProject();
|
||||||
|
QTC_ASSERT(project, return);
|
||||||
|
QTC_ASSERT(project->activeTarget(), return);
|
||||||
|
|
||||||
|
auto runControl = new RunControl(Constants::CLANGTIDYCLAZY_RUN_MODE);
|
||||||
|
runControl->setDisplayName(tr("Clang-Tidy and Clazy"));
|
||||||
|
runControl->setIcon(ProjectExplorer::Icons::ANALYZER_START_SMALL_TOOLBAR);
|
||||||
|
runControl->setTarget(project->activeTarget());
|
||||||
|
|
||||||
|
const FileInfos fileInfos = collectFileInfos(project, fileSelection);
|
||||||
|
if (fileInfos.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const bool preventBuild = fileSelection == FileSelection::CurrentFile;
|
||||||
|
auto clangTool = new ClangToolRunWorker(runControl,
|
||||||
|
runSettings(project),
|
||||||
|
fileInfos,
|
||||||
|
preventBuild);
|
||||||
|
|
||||||
|
m_stopAction->disconnect();
|
||||||
|
connect(m_stopAction, &QAction::triggered, runControl, [runControl] {
|
||||||
|
runControl->appendMessage(tr("Clang-Tidy and Clazy tool stopped by user."),
|
||||||
|
NormalMessageFormat);
|
||||||
|
runControl->initiateStop();
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(runControl, &RunControl::stopped, this, [this, clangTool] {
|
||||||
|
bool success = clangTool->success();
|
||||||
|
setToolBusy(false);
|
||||||
|
m_running = false;
|
||||||
|
handleStateUpdate();
|
||||||
|
updateRunActions();
|
||||||
|
emit finished(success);
|
||||||
|
});
|
||||||
|
|
||||||
|
m_perspective.select();
|
||||||
|
|
||||||
|
m_diagnosticModel->clear();
|
||||||
|
|
||||||
|
setToolBusy(true);
|
||||||
|
m_diagnosticFilterModel->setProject(project);
|
||||||
|
m_running = true;
|
||||||
|
handleStateUpdate();
|
||||||
|
updateRunActions();
|
||||||
|
|
||||||
|
ProjectExplorerPlugin::startRunControl(runControl);
|
||||||
|
}
|
||||||
|
|
||||||
|
Diagnostics ClangTool::read(OutputFileFormat outputFileFormat, const QString &logFilePath, const QString &mainFilePath, const QSet<FilePath> &projectFiles, QString *errorMessage) const
|
||||||
|
{
|
||||||
|
const auto acceptFromFilePath = [projectFiles](const Utils::FilePath &filePath) {
|
||||||
|
return projectFiles.contains(filePath);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (outputFileFormat == OutputFileFormat::Yaml) {
|
||||||
|
return readExportedDiagnostics(Utils::FilePath::fromString(logFilePath),
|
||||||
|
acceptFromFilePath,
|
||||||
|
errorMessage);
|
||||||
|
}
|
||||||
|
return readSerializedDiagnostics(Utils::FilePath::fromString(logFilePath),
|
||||||
|
Utils::FilePath::fromString(mainFilePath),
|
||||||
|
acceptFromFilePath,
|
||||||
|
errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
FileInfos ClangTool::collectFileInfos(Project *project, FileSelection fileSelection) const
|
FileInfos ClangTool::collectFileInfos(Project *project, FileSelection fileSelection) const
|
||||||
{
|
{
|
||||||
auto projectInfo = CppTools::CppModelManager::instance()->projectInfo(project);
|
auto projectInfo = CppTools::CppModelManager::instance()->projectInfo(project);
|
||||||
@@ -174,6 +551,42 @@ void ClangTool::initDiagnosticView()
|
|||||||
m_diagnosticView->setAutoScroll(false);
|
m_diagnosticView->setAutoScroll(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClangTool::loadDiagnosticsFromFiles()
|
||||||
|
{
|
||||||
|
// Ask user for files
|
||||||
|
const QStringList filePaths
|
||||||
|
= QFileDialog::getOpenFileNames(Core::ICore::mainWindow(),
|
||||||
|
tr("Select YAML Files with Diagnostics"),
|
||||||
|
QDir::homePath(),
|
||||||
|
tr("YAML Files (*.yml *.yaml);;All Files (*)"));
|
||||||
|
if (filePaths.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Load files
|
||||||
|
Diagnostics diagnostics;
|
||||||
|
QString errors;
|
||||||
|
for (const QString &filePath : filePaths) {
|
||||||
|
QString currentError;
|
||||||
|
diagnostics << readExportedDiagnostics(Utils::FilePath::fromString(filePath),
|
||||||
|
{},
|
||||||
|
¤tError);
|
||||||
|
|
||||||
|
if (!currentError.isEmpty()) {
|
||||||
|
if (!errors.isEmpty())
|
||||||
|
errors.append("\n");
|
||||||
|
errors.append(currentError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show errors
|
||||||
|
if (!errors.isEmpty())
|
||||||
|
AsynchronousMessageBox::critical(tr("Error Loading Diagnostics"), errors);
|
||||||
|
|
||||||
|
// Show imported
|
||||||
|
m_diagnosticModel->clear();
|
||||||
|
onNewDiagnosticsAvailable(diagnostics);
|
||||||
|
}
|
||||||
|
|
||||||
QSet<Diagnostic> ClangTool::diagnostics() const
|
QSet<Diagnostic> ClangTool::diagnostics() const
|
||||||
{
|
{
|
||||||
return Utils::filtered(m_diagnosticModel->diagnostics(), [](const Diagnostic &diagnostic) {
|
return Utils::filtered(m_diagnosticModel->diagnostics(), [](const Diagnostic &diagnostic) {
|
||||||
@@ -186,6 +599,78 @@ void ClangTool::onNewDiagnosticsAvailable(const Diagnostics &diagnostics)
|
|||||||
{
|
{
|
||||||
QTC_ASSERT(m_diagnosticModel, return);
|
QTC_ASSERT(m_diagnosticModel, return);
|
||||||
m_diagnosticModel->addDiagnostics(diagnostics);
|
m_diagnosticModel->addDiagnostics(diagnostics);
|
||||||
|
if (!m_diagnosticFilterModel->filterRegExp().pattern().isEmpty())
|
||||||
|
m_diagnosticFilterModel->invalidateFilter();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClangTool::updateRunActions()
|
||||||
|
{
|
||||||
|
if (m_toolBusy) {
|
||||||
|
QString tooltipText = tr("Clang-Tidy and Clazy are still running.");
|
||||||
|
|
||||||
|
m_startAction->setEnabled(false);
|
||||||
|
m_startAction->setToolTip(tooltipText);
|
||||||
|
|
||||||
|
m_startOnCurrentFileAction->setEnabled(false);
|
||||||
|
m_startOnCurrentFileAction->setToolTip(tooltipText);
|
||||||
|
|
||||||
|
m_stopAction->setEnabled(true);
|
||||||
|
m_loadExported->setEnabled(false);
|
||||||
|
m_clear->setEnabled(false);
|
||||||
|
} else {
|
||||||
|
QString toolTipStart = m_startAction->text();
|
||||||
|
QString toolTipStartOnCurrentFile = m_startOnCurrentFileAction->text();
|
||||||
|
|
||||||
|
Project *project = SessionManager::startupProject();
|
||||||
|
Target *target = project ? project->activeTarget() : nullptr;
|
||||||
|
const Core::Id cxx = ProjectExplorer::Constants::CXX_LANGUAGE_ID;
|
||||||
|
bool canRun = target && project->projectLanguages().contains(cxx)
|
||||||
|
&& ToolChainKitAspect::toolChain(target->kit(), cxx);
|
||||||
|
if (!canRun)
|
||||||
|
toolTipStart = toolTipStartOnCurrentFile = tr("This is not a C/C++ project.");
|
||||||
|
|
||||||
|
m_startAction->setEnabled(canRun);
|
||||||
|
m_startAction->setToolTip(toolTipStart);
|
||||||
|
|
||||||
|
m_startOnCurrentFileAction->setEnabled(canRun);
|
||||||
|
m_startOnCurrentFileAction->setToolTip(toolTipStartOnCurrentFile);
|
||||||
|
|
||||||
|
m_stopAction->setEnabled(false);
|
||||||
|
m_loadExported->setEnabled(true);
|
||||||
|
m_clear->setEnabled(m_diagnosticModel->diagnostics().count());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClangTool::handleStateUpdate()
|
||||||
|
{
|
||||||
|
QTC_ASSERT(m_goBack, return);
|
||||||
|
QTC_ASSERT(m_goNext, return);
|
||||||
|
QTC_ASSERT(m_diagnosticModel, return);
|
||||||
|
QTC_ASSERT(m_diagnosticFilterModel, return);
|
||||||
|
|
||||||
|
const int issuesFound = m_diagnosticModel->diagnostics().count();
|
||||||
|
const int issuesVisible = m_diagnosticFilterModel->rowCount();
|
||||||
|
m_goBack->setEnabled(issuesVisible > 1);
|
||||||
|
m_goNext->setEnabled(issuesVisible > 1);
|
||||||
|
m_clear->setEnabled(issuesFound > 0);
|
||||||
|
m_expandCollapse->setEnabled(issuesVisible);
|
||||||
|
|
||||||
|
m_loadExported->setEnabled(!m_running);
|
||||||
|
|
||||||
|
QString message;
|
||||||
|
if (m_running) {
|
||||||
|
if (issuesFound)
|
||||||
|
message = tr("Running - %n diagnostics", nullptr, issuesFound);
|
||||||
|
else
|
||||||
|
message = tr("Running - No diagnostics");
|
||||||
|
} else {
|
||||||
|
if (issuesFound)
|
||||||
|
message = tr("Finished - %n diagnostics", nullptr, issuesFound);
|
||||||
|
else
|
||||||
|
message = tr("Finished - No diagnostics");
|
||||||
|
}
|
||||||
|
|
||||||
|
Debugger::showPermanentStatusMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClangTool::setToolBusy(bool busy)
|
void ClangTool::setToolBusy(bool busy)
|
||||||
|
@@ -29,38 +29,56 @@
|
|||||||
#include "clangtoolsdiagnostic.h"
|
#include "clangtoolsdiagnostic.h"
|
||||||
#include "clangtoolslogfilereader.h"
|
#include "clangtoolslogfilereader.h"
|
||||||
|
|
||||||
|
#include <debugger/debuggermainwindow.h>
|
||||||
|
|
||||||
#include <projectexplorer/runconfiguration.h>
|
#include <projectexplorer/runconfiguration.h>
|
||||||
#include <cpptools/projectinfo.h>
|
#include <cpptools/projectinfo.h>
|
||||||
|
|
||||||
namespace Debugger { class DetailedErrorView; }
|
QT_BEGIN_NAMESPACE
|
||||||
namespace Utils { class FilePath; }
|
class QToolButton;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
namespace Debugger {
|
||||||
|
class DetailedErrorView;
|
||||||
|
}
|
||||||
|
namespace Utils {
|
||||||
|
class FilePath;
|
||||||
|
class FancyLineEdit;
|
||||||
|
} // namespace Utils
|
||||||
|
|
||||||
namespace ClangTools {
|
namespace ClangTools {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
class ClangToolsDiagnosticModel;
|
class ClangToolsDiagnosticModel;
|
||||||
class Diagnostic;
|
class Diagnostic;
|
||||||
|
class DiagnosticFilterModel;
|
||||||
|
|
||||||
|
const char ClangTidyClazyPerspectiveId[] = "ClangTidyClazy.Perspective";
|
||||||
|
|
||||||
class ClangTool : public QObject
|
class ClangTool : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ClangTool(const QString &name);
|
static ClangTool *instance();
|
||||||
|
|
||||||
|
ClangTool();
|
||||||
~ClangTool() override;
|
~ClangTool() override;
|
||||||
|
|
||||||
|
void selectPerspective();
|
||||||
|
|
||||||
enum class FileSelection {
|
enum class FileSelection {
|
||||||
AllFiles,
|
AllFiles,
|
||||||
CurrentFile,
|
CurrentFile,
|
||||||
AskUser,
|
AskUser,
|
||||||
};
|
};
|
||||||
virtual void startTool(FileSelection fileSelection) = 0;
|
void startTool(FileSelection fileSelection);
|
||||||
|
|
||||||
virtual Diagnostics read(OutputFileFormat outputFileFormat,
|
Diagnostics read(OutputFileFormat outputFileFormat,
|
||||||
const QString &logFilePath,
|
const QString &logFilePath,
|
||||||
const QString &mainFilePath,
|
const QString &mainFilePath,
|
||||||
const QSet<Utils::FilePath> &projectFiles,
|
const QSet<Utils::FilePath> &projectFiles,
|
||||||
QString *errorMessage) const = 0;
|
QString *errorMessage) const;
|
||||||
|
|
||||||
FileInfos collectFileInfos(ProjectExplorer::Project *project,
|
FileInfos collectFileInfos(ProjectExplorer::Project *project,
|
||||||
FileSelection fileSelection) const;
|
FileSelection fileSelection) const;
|
||||||
@@ -70,7 +88,7 @@ public:
|
|||||||
|
|
||||||
const QString &name() const;
|
const QString &name() const;
|
||||||
|
|
||||||
virtual void onNewDiagnosticsAvailable(const Diagnostics &diagnostics);
|
void onNewDiagnosticsAvailable(const Diagnostics &diagnostics);
|
||||||
|
|
||||||
QAction *startAction() const { return m_startAction; }
|
QAction *startAction() const { return m_startAction; }
|
||||||
QAction *startOnCurrentFileAction() const { return m_startOnCurrentFileAction; }
|
QAction *startOnCurrentFileAction() const { return m_startOnCurrentFileAction; }
|
||||||
@@ -78,11 +96,14 @@ public:
|
|||||||
signals:
|
signals:
|
||||||
void finished(bool success); // For testing.
|
void finished(bool success); // For testing.
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
virtual void handleStateUpdate() = 0;
|
void updateRunActions();
|
||||||
|
void handleStateUpdate();
|
||||||
|
|
||||||
void setToolBusy(bool busy);
|
void setToolBusy(bool busy);
|
||||||
|
|
||||||
void initDiagnosticView();
|
void initDiagnosticView();
|
||||||
|
void loadDiagnosticsFromFiles();
|
||||||
|
|
||||||
ClangToolsDiagnosticModel *m_diagnosticModel = nullptr;
|
ClangToolsDiagnosticModel *m_diagnosticModel = nullptr;
|
||||||
QPointer<Debugger::DetailedErrorView> m_diagnosticView;
|
QPointer<Debugger::DetailedErrorView> m_diagnosticView;
|
||||||
@@ -93,6 +114,19 @@ protected:
|
|||||||
bool m_running = false;
|
bool m_running = false;
|
||||||
bool m_toolBusy = false;
|
bool m_toolBusy = false;
|
||||||
|
|
||||||
|
DiagnosticFilterModel *m_diagnosticFilterModel = nullptr;
|
||||||
|
|
||||||
|
Utils::FancyLineEdit *m_filterLineEdit = nullptr;
|
||||||
|
QToolButton *m_applyFixitsButton = nullptr;
|
||||||
|
|
||||||
|
QAction *m_goBack = nullptr;
|
||||||
|
QAction *m_goNext = nullptr;
|
||||||
|
QAction *m_loadExported = nullptr;
|
||||||
|
QAction *m_clear = nullptr;
|
||||||
|
QAction *m_expandCollapse = nullptr;
|
||||||
|
|
||||||
|
Utils::Perspective m_perspective{ClangTidyClazyPerspectiveId, tr("Clang-Tidy and Clazy")};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const QString m_name;
|
const QString m_name;
|
||||||
};
|
};
|
||||||
|
@@ -26,7 +26,6 @@
|
|||||||
#include "clangtoolruncontrol.h"
|
#include "clangtoolruncontrol.h"
|
||||||
|
|
||||||
#include "clangtidyclazyrunner.h"
|
#include "clangtidyclazyrunner.h"
|
||||||
#include "clangtidyclazytool.h"
|
|
||||||
#include "clangtool.h"
|
#include "clangtool.h"
|
||||||
#include "clangtoolslogfilereader.h"
|
#include "clangtoolslogfilereader.h"
|
||||||
#include "clangtoolsprojectsettings.h"
|
#include "clangtoolsprojectsettings.h"
|
||||||
@@ -119,7 +118,7 @@ namespace Internal {
|
|||||||
|
|
||||||
static ClangTool *tool()
|
static ClangTool *tool()
|
||||||
{
|
{
|
||||||
return ClangTidyClazyTool::instance();
|
return ClangTool::instance();
|
||||||
}
|
}
|
||||||
|
|
||||||
class ProjectBuilder : public RunWorker
|
class ProjectBuilder : public RunWorker
|
||||||
|
@@ -21,7 +21,6 @@ SOURCES += \
|
|||||||
clangtoolsdiagnosticview.cpp \
|
clangtoolsdiagnosticview.cpp \
|
||||||
clangtoolsprojectsettingswidget.cpp \
|
clangtoolsprojectsettingswidget.cpp \
|
||||||
clangtidyclazyrunner.cpp \
|
clangtidyclazyrunner.cpp \
|
||||||
clangtidyclazytool.cpp \
|
|
||||||
clangtool.cpp \
|
clangtool.cpp \
|
||||||
clangtoolruncontrol.cpp \
|
clangtoolruncontrol.cpp \
|
||||||
clangtoolrunner.cpp \
|
clangtoolrunner.cpp \
|
||||||
@@ -42,7 +41,6 @@ HEADERS += \
|
|||||||
clangtoolsdiagnosticview.h \
|
clangtoolsdiagnosticview.h \
|
||||||
clangtoolsprojectsettingswidget.h \
|
clangtoolsprojectsettingswidget.h \
|
||||||
clangtidyclazyrunner.h \
|
clangtidyclazyrunner.h \
|
||||||
clangtidyclazytool.h \
|
|
||||||
clangtool.h \
|
clangtool.h \
|
||||||
clangtoolruncontrol.h \
|
clangtoolruncontrol.h \
|
||||||
clangtoolrunner.h \
|
clangtoolrunner.h \
|
||||||
|
@@ -39,8 +39,6 @@ QtcPlugin {
|
|||||||
"clangselectablefilesdialog.ui",
|
"clangselectablefilesdialog.ui",
|
||||||
"clangtidyclazyrunner.cpp",
|
"clangtidyclazyrunner.cpp",
|
||||||
"clangtidyclazyrunner.h",
|
"clangtidyclazyrunner.h",
|
||||||
"clangtidyclazytool.cpp",
|
|
||||||
"clangtidyclazytool.h",
|
|
||||||
"clangtool.cpp",
|
"clangtool.cpp",
|
||||||
"clangtool.h",
|
"clangtool.h",
|
||||||
"clangtoolruncontrol.cpp",
|
"clangtoolruncontrol.cpp",
|
||||||
|
@@ -25,10 +25,10 @@
|
|||||||
|
|
||||||
#include "clangtoolsplugin.h"
|
#include "clangtoolsplugin.h"
|
||||||
|
|
||||||
|
#include "clangtool.h"
|
||||||
#include "clangtoolsconstants.h"
|
#include "clangtoolsconstants.h"
|
||||||
#include "clangtoolsprojectsettingswidget.h"
|
|
||||||
#include "clangtidyclazytool.h"
|
|
||||||
#include "clangtoolsprojectsettings.h"
|
#include "clangtoolsprojectsettings.h"
|
||||||
|
#include "clangtoolsprojectsettingswidget.h"
|
||||||
#include "settingswidget.h"
|
#include "settingswidget.h"
|
||||||
|
|
||||||
#ifdef WITH_TESTS
|
#ifdef WITH_TESTS
|
||||||
@@ -98,7 +98,7 @@ private:
|
|||||||
class ClangToolsPluginPrivate
|
class ClangToolsPluginPrivate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ClangTidyClazyTool clangTidyClazyTool;
|
ClangTool clangTool;
|
||||||
ClangToolsOptionsPage optionsPage;
|
ClangToolsOptionsPage optionsPage;
|
||||||
ClangToolsProjectSettingsManager settingsManager;
|
ClangToolsProjectSettingsManager settingsManager;
|
||||||
};
|
};
|
||||||
@@ -115,9 +115,8 @@ bool ClangToolsPlugin::initialize(const QStringList &arguments, QString *errorSt
|
|||||||
|
|
||||||
d = new ClangToolsPluginPrivate;
|
d = new ClangToolsPluginPrivate;
|
||||||
|
|
||||||
ActionManager::registerAction(d->clangTidyClazyTool.startAction(),
|
ActionManager::registerAction(d->clangTool.startAction(), Constants::RUN_ON_PROJECT);
|
||||||
Constants::RUN_ON_PROJECT);
|
ActionManager::registerAction(d->clangTool.startOnCurrentFileAction(),
|
||||||
ActionManager::registerAction(d->clangTidyClazyTool.startOnCurrentFileAction(),
|
|
||||||
Constants::RUN_ON_CURRENT_FILE);
|
Constants::RUN_ON_CURRENT_FILE);
|
||||||
|
|
||||||
auto panelFactory = new ProjectPanelFactory();
|
auto panelFactory = new ProjectPanelFactory();
|
||||||
|
@@ -25,8 +25,8 @@
|
|||||||
|
|
||||||
#include "clangtoolspreconfiguredsessiontests.h"
|
#include "clangtoolspreconfiguredsessiontests.h"
|
||||||
|
|
||||||
|
#include "clangtool.h"
|
||||||
#include "clangtoolsdiagnostic.h"
|
#include "clangtoolsdiagnostic.h"
|
||||||
#include "clangtidyclazytool.h"
|
|
||||||
#include "clangtoolsutils.h"
|
#include "clangtoolsutils.h"
|
||||||
|
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
@@ -121,13 +121,13 @@ void PreconfiguredSessionTests::testPreconfiguredSession()
|
|||||||
|
|
||||||
QVERIFY(switchToProjectAndTarget(project, target));
|
QVERIFY(switchToProjectAndTarget(project, target));
|
||||||
|
|
||||||
ClangTidyClazyTool::instance()->startTool(ClangTidyClazyTool::FileSelection::AllFiles);
|
ClangTool::instance()->startTool(ClangTool::FileSelection::AllFiles);
|
||||||
QSignalSpy waitUntilAnalyzerFinished(ClangTidyClazyTool::instance(), SIGNAL(finished(bool)));
|
QSignalSpy waitUntilAnalyzerFinished(ClangTool::instance(), SIGNAL(finished(bool)));
|
||||||
QVERIFY(waitUntilAnalyzerFinished.wait(30000));
|
QVERIFY(waitUntilAnalyzerFinished.wait(30000));
|
||||||
const QList<QVariant> arguments = waitUntilAnalyzerFinished.takeFirst();
|
const QList<QVariant> arguments = waitUntilAnalyzerFinished.takeFirst();
|
||||||
const bool analyzerFinishedSuccessfully = arguments.first().toBool();
|
const bool analyzerFinishedSuccessfully = arguments.first().toBool();
|
||||||
QVERIFY(analyzerFinishedSuccessfully);
|
QVERIFY(analyzerFinishedSuccessfully);
|
||||||
QCOMPARE(ClangTidyClazyTool::instance()->diagnostics().count(), 0);
|
QCOMPARE(ClangTool::instance()->diagnostics().count(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static QList<Project *> validProjects(const QList<Project *> projectsOfSession)
|
static QList<Project *> validProjects(const QList<Project *> projectsOfSession)
|
||||||
|
@@ -26,7 +26,7 @@
|
|||||||
#include "clangtoolsprojectsettingswidget.h"
|
#include "clangtoolsprojectsettingswidget.h"
|
||||||
#include "ui_clangtoolsprojectsettingswidget.h"
|
#include "ui_clangtoolsprojectsettingswidget.h"
|
||||||
|
|
||||||
#include "clangtidyclazytool.h"
|
#include "clangtool.h"
|
||||||
#include "clangtoolsconstants.h"
|
#include "clangtoolsconstants.h"
|
||||||
#include "clangtoolsprojectsettings.h"
|
#include "clangtoolsprojectsettings.h"
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ ProjectSettingsWidget::ProjectSettingsWidget(ProjectExplorer::Project *project,
|
|||||||
});
|
});
|
||||||
|
|
||||||
connect(m_ui->gotoAnalyzerModeLabel, &QLabel::linkActivated, [](const QString &){
|
connect(m_ui->gotoAnalyzerModeLabel, &QLabel::linkActivated, [](const QString &){
|
||||||
ClangTidyClazyTool::instance()->selectPerspective();
|
ClangTool::instance()->selectPerspective();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Run options
|
// Run options
|
||||||
|
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
#include "clangtoolsunittests.h"
|
#include "clangtoolsunittests.h"
|
||||||
|
|
||||||
#include "clangtidyclazytool.h"
|
#include "clangtool.h"
|
||||||
#include "clangtoolsdiagnostic.h"
|
#include "clangtoolsdiagnostic.h"
|
||||||
#include "clangtoolssettings.h"
|
#include "clangtoolssettings.h"
|
||||||
#include "clangtoolsutils.h"
|
#include "clangtoolsutils.h"
|
||||||
@@ -109,7 +109,7 @@ void ClangToolsUnitTests::testProject()
|
|||||||
CppTools::Tests::ProjectOpenerAndCloser projectManager;
|
CppTools::Tests::ProjectOpenerAndCloser projectManager;
|
||||||
const CppTools::ProjectInfo projectInfo = projectManager.open(projectFilePath, true);
|
const CppTools::ProjectInfo projectInfo = projectManager.open(projectFilePath, true);
|
||||||
QVERIFY(projectInfo.isValid());
|
QVERIFY(projectInfo.isValid());
|
||||||
ClangTool *tool = ClangTidyClazyTool::instance();
|
ClangTool *tool = ClangTool::instance();
|
||||||
|
|
||||||
// Change configs
|
// Change configs
|
||||||
QSharedPointer<CppTools::CppCodeModelSettings> cppToolsSettings = CppTools::codeModelSettings();
|
QSharedPointer<CppTools::CppCodeModelSettings> cppToolsSettings = CppTools::codeModelSettings();
|
||||||
@@ -136,7 +136,7 @@ void ClangToolsUnitTests::testProject()
|
|||||||
clangToolsSettings->setRunSettings(runSettings);
|
clangToolsSettings->setRunSettings(runSettings);
|
||||||
clangToolsSettings->writeSettings();
|
clangToolsSettings->writeSettings();
|
||||||
|
|
||||||
tool->startTool(ClangTidyClazyTool::FileSelection::AllFiles);
|
tool->startTool(ClangTool::FileSelection::AllFiles);
|
||||||
QSignalSpy waiter(tool, SIGNAL(finished(bool)));
|
QSignalSpy waiter(tool, SIGNAL(finished(bool)));
|
||||||
QVERIFY(waiter.wait(30000));
|
QVERIFY(waiter.wait(30000));
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user