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:
Nikolai Kosjar
2019-09-25 15:07:59 +02:00
parent 4750969c2b
commit d5bae3c1eb
12 changed files with 546 additions and 680 deletions

View File

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

View File

@@ -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),
{},
&currentError);
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

View File

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

View File

@@ -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),
{},
&currentError);
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)

View File

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

View File

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

View File

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

View File

@@ -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",

View File

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

View File

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

View File

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

View File

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