ClangTools: Allow selecting diagnostic config for project

When starting the Clazy/Tidy tool, allow to select the diagnostic
configuration for the run.

As a side effect, fix a race condition where the runner could end up
with no diagnostic config (removed during run) - copy the diagnostic
config instead of referencing/querying it by the id.

Change-Id: Iedafa8f31a3bbd233d65818fe8de16add1e4d443
Reviewed-by: Ivan Donchevskii <ivan.donchevskii@qt.io>
This commit is contained in:
Nikolai Kosjar
2018-05-14 11:40:40 +02:00
parent 2522275b69
commit 9b74948a61
12 changed files with 206 additions and 25 deletions

View File

@@ -27,6 +27,7 @@
#include "ui_clangselectablefilesdialog.h"
#include "clangtoolsprojectsettings.h"
#include "clangtoolssettings.h"
#include "clangtoolsutils.h"
#include <cpptools/compileroptionsbuilder.h>
@@ -262,6 +263,8 @@ private:
}
};
enum { GlobalSettings , CustomSettings };
SelectableFilesDialog::SelectableFilesDialog(const ProjectInfo &projectInfo,
const FileInfos &allFileInfos)
: QDialog(nullptr)
@@ -278,8 +281,42 @@ SelectableFilesDialog::SelectableFilesDialog(const ProjectInfo &projectInfo,
m_ui->buttons->setStandardButtons(QDialogButtonBox::Cancel);
m_ui->buttons->addButton(m_analyzeButton, QDialogButtonBox::AcceptRole);
// Restore selection
m_ui->diagnosticConfigsSelectionWidget->showLabel(false);
ClangToolsProjectSettings *settings = ClangToolsProjectSettingsManager::getSettings(m_project);
Core::Id diagnosticConfig;
if (settings->useGlobalSettings()) {
m_ui->globalOrCustom->setCurrentIndex(GlobalSettings);
m_ui->diagnosticConfigsSelectionWidget->setEnabled(false);
diagnosticConfig = ClangToolsSettings::instance()->savedDiagnosticConfigId();
} else {
m_ui->globalOrCustom->setCurrentIndex(CustomSettings);
m_ui->diagnosticConfigsSelectionWidget->setEnabled(true);
diagnosticConfig = settings->diagnosticConfig();
}
m_customDiagnosticConfig = diagnosticConfig;
m_ui->diagnosticConfigsSelectionWidget->refresh(diagnosticConfig);
connect(m_ui->globalOrCustom,
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
[this](int index){
m_ui->diagnosticConfigsSelectionWidget->setEnabled(index == CustomSettings);
if (index == CustomSettings) {
m_ui->diagnosticConfigsSelectionWidget->refresh(m_customDiagnosticConfig);
} else {
m_ui->diagnosticConfigsSelectionWidget->refresh(
ClangToolsSettings::instance()->savedDiagnosticConfigId());
}
});
connect(m_ui->diagnosticConfigsSelectionWidget,
&ClangDiagnosticConfigsSelectionWidget::currentConfigChanged,
[this](const Core::Id &currentConfigId) {
if (m_ui->globalOrCustom->currentIndex() == CustomSettings)
m_customDiagnosticConfig = currentConfigId;
});
// Restore selection
if (settings->selectedDirs().isEmpty() && settings->selectedFiles().isEmpty())
m_filesModel->selectAllFiles(); // Initially, all files are selected
else // Restore selection
@@ -300,11 +337,16 @@ FileInfos SelectableFilesDialog::filteredFileInfos() const
void SelectableFilesDialog::accept()
{
ClangToolsProjectSettings *settings = ClangToolsProjectSettingsManager::getSettings(m_project);
// Save diagnostic configuration
settings->setUseGlobalSettings(m_ui->globalOrCustom->currentIndex() == GlobalSettings);
settings->setDiagnosticConfig(m_customDiagnosticConfig);
// Save selection
QSet<FileName> checkedDirs;
QSet<FileName> checkedFiles;
m_filesModel->minimalSelection(checkedDirs, checkedFiles);
ClangToolsProjectSettings *settings = ClangToolsProjectSettingsManager::getSettings(m_project);
settings->setSelectedDirs(checkedDirs);
settings->setSelectedFiles(checkedFiles);

View File

@@ -27,6 +27,8 @@
#include "clangfileinfo.h"
#include <coreplugin/id.h>
#include <QDialog>
#include <memory>
@@ -60,6 +62,7 @@ private:
std::unique_ptr<Ui::SelectableFilesDialog> m_ui;
std::unique_ptr<SelectableFilesModel> m_filesModel;
Core::Id m_customDiagnosticConfig;
ProjectExplorer::Project *m_project;
QPushButton *m_analyzeButton = nullptr;
};

View File

@@ -11,9 +11,47 @@
</rect>
</property>
<property name="windowTitle">
<string>Select the Files to Analyze</string>
<string>Analyzer Configuration</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Diagnostic Configuration</string>
</property>
<property name="checkable">
<bool>false</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QComboBox" name="globalOrCustom">
<item>
<property name="text">
<string>Global</string>
</property>
</item>
<item>
<property name="text">
<string>Custom</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="CppTools::ClangDiagnosticConfigsSelectionWidget" name="diagnosticConfigsSelectionWidget" native="true"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Files to Analyze</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QTreeView" name="filesView">
<property name="headerHidden">
@@ -21,6 +59,9 @@
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttons">
<property name="orientation">
@@ -33,6 +74,13 @@
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>CppTools::ClangDiagnosticConfigsSelectionWidget</class>
<extends>QWidget</extends>
<header>cpptools/clangdiagnosticconfigsselectionwidget.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>

View File

@@ -33,10 +33,13 @@ using namespace ProjectExplorer;
namespace ClangTools {
namespace Internal {
ClangTidyClazyRunControl::ClangTidyClazyRunControl(RunControl *runControl,
ClangTidyClazyRunControl::ClangTidyClazyRunControl(
RunControl *runControl,
Target *target,
const CppTools::ClangDiagnosticConfig &diagnosticConfig,
const FileInfos &fileInfos)
: ClangToolRunControl(runControl, target, fileInfos)
, m_diagnosticConfig(diagnosticConfig)
{
setDisplayName("ClangTidyClazyRunner");
init();
@@ -47,7 +50,8 @@ ClangToolRunner *ClangTidyClazyRunControl::createRunner()
QTC_ASSERT(!m_clangExecutable.isEmpty(), return 0);
QTC_ASSERT(!m_clangLogFileDir.isEmpty(), return 0);
auto runner = new ClangTidyClazyRunner(m_clangExecutable,
auto runner = new ClangTidyClazyRunner(m_diagnosticConfig,
m_clangExecutable,
m_clangLogFileDir,
m_environment,
this);

View File

@@ -27,6 +27,8 @@
#include "clangtoolruncontrol.h"
#include <cpptools/clangdiagnosticconfig.h>
namespace ClangTools {
namespace Internal {
@@ -37,11 +39,15 @@ class ClangTidyClazyRunControl final : public ClangToolRunControl
public:
ClangTidyClazyRunControl(ProjectExplorer::RunControl *runControl,
ProjectExplorer::Target *target,
const CppTools::ClangDiagnosticConfig &diagnosticConfig,
const FileInfos &fileInfos);
protected:
ClangToolRunner *createRunner() final;
ClangTool *tool() final;
private:
CppTools::ClangDiagnosticConfig m_diagnosticConfig;
};
} // namespace Internal

View File

@@ -42,7 +42,8 @@ static Q_LOGGING_CATEGORY(LOG, "qtc.clangtools.runner")
namespace ClangTools {
namespace Internal {
ClangTidyClazyRunner::ClangTidyClazyRunner(const QString &clangExecutable,
ClangTidyClazyRunner::ClangTidyClazyRunner(const CppTools::ClangDiagnosticConfig &diagnosticConfig,
const QString &clangExecutable,
const QString &clangLogFileDir,
const Utils::Environment &environment,
QObject *parent)
@@ -51,6 +52,7 @@ ClangTidyClazyRunner::ClangTidyClazyRunner(const QString &clangExecutable,
environment,
tr("Clang-Tidy and Clazy"),
parent)
, m_diagnosticConfig(diagnosticConfig)
{
}
@@ -78,28 +80,21 @@ QStringList ClangTidyClazyRunner::constructCommandLineArguments(const QStringLis
<< QString("-serialize-diagnostics")
<< QString(m_logFile);
const ClangDiagnosticConfigsModel configsModel(
CppTools::codeModelSettings()->clangCustomDiagnosticConfigs());
const Core::Id configId = ClangToolsSettings::instance()->savedDiagnosticConfigId();
QTC_ASSERT(configsModel.hasConfigWithId(configId), return arguments;);
const ClangDiagnosticConfig &config = configsModel.configWithId(configId);
const ClangDiagnosticConfig::TidyMode tidyMode = config.clangTidyMode();
const ClangDiagnosticConfig::TidyMode tidyMode = m_diagnosticConfig.clangTidyMode();
if (tidyMode != ClangDiagnosticConfig::TidyMode::Disabled) {
addXclangArg(arguments, QString("-add-plugin"), QString("clang-tidy"));
if (tidyMode != ClangDiagnosticConfig::TidyMode::File) {
const QString tidyChecks = config.clangTidyChecks();
const QString tidyChecks = m_diagnosticConfig.clangTidyChecks();
addXclangArg(arguments, QString("-plugin-arg-clang-tidy"), "-checks=" + tidyChecks);
}
}
const QString clazyChecks = config.clazyChecks();
const QString clazyChecks = m_diagnosticConfig.clazyChecks();
if (!clazyChecks.isEmpty()) {
addXclangArg(arguments, QString("-add-plugin"), QString("clang-lazy"));
addXclangArg(arguments, QString("-plugin-arg-clang-lazy"), QString("enable-all-fixits"));
addXclangArg(arguments, QString("-plugin-arg-clang-lazy"), QString("no-autowrite-fixits"));
addXclangArg(arguments, QString("-plugin-arg-clang-lazy"), config.clazyChecks());
addXclangArg(arguments, QString("-plugin-arg-clang-lazy"), m_diagnosticConfig.clazyChecks());
}
arguments += options;

View File

@@ -25,6 +25,8 @@
#pragma once
#include <cpptools/clangdiagnosticconfig.h>
#include "clangtoolrunner.h"
namespace ClangTools {
@@ -35,12 +37,17 @@ class ClangTidyClazyRunner final : public ClangToolRunner
Q_OBJECT
public:
ClangTidyClazyRunner(const QString &clangExecutable,
ClangTidyClazyRunner(const CppTools::ClangDiagnosticConfig &diagnosticConfig,
const QString &clangExecutable,
const QString &clangLogFileDir,
const Utils::Environment &environment,
QObject *parent = nullptr);
protected:
QStringList constructCommandLineArguments(const QStringList &options) final;
private:
const CppTools::ClangDiagnosticConfig m_diagnosticConfig;
};
} // namespace Internal

View File

@@ -31,11 +31,16 @@
#include "clangtoolslogfilereader.h"
#include "clangtidyclazyruncontrol.h"
#include "clangtoolsdiagnosticview.h"
#include "clangtoolsprojectsettings.h"
#include "clangtoolssettings.h"
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <cpptools/clangdiagnosticconfigsmodel.h>
#include <cpptools/cppcodemodelsettings.h>
#include <cpptools/cppmodelmanager.h>
#include <cpptools/cpptoolsreuse.h>
#include <debugger/analyzer/analyzermanager.h>
@@ -50,6 +55,7 @@
#include <QAction>
using namespace Core;
using namespace CppTools;
using namespace Debugger;
using namespace ProjectExplorer;
using namespace Utils;
@@ -140,6 +146,24 @@ ClangTidyClazyTool *ClangTidyClazyTool::instance()
return s_instance;
}
static ClangDiagnosticConfig getDiagnosticConfig(Project *project)
{
ClangToolsProjectSettings *projectSettings = ClangToolsProjectSettingsManager::getSettings(
project);
Core::Id diagnosticConfigId;
if (projectSettings->useGlobalSettings())
diagnosticConfigId = ClangToolsSettings::instance()->savedDiagnosticConfigId();
else
diagnosticConfigId = projectSettings->diagnosticConfig();
const ClangDiagnosticConfigsModel configsModel(
CppTools::codeModelSettings()->clangCustomDiagnosticConfigs());
QTC_ASSERT(configsModel.hasConfigWithId(diagnosticConfigId), return ClangDiagnosticConfig());
return configsModel.configWithId(diagnosticConfigId);
}
void ClangTidyClazyTool::startTool(bool askUserForFileSelection)
{
auto runControl = new RunControl(nullptr, Constants::CLANGTIDYCLAZY_RUN_MODE);
@@ -153,7 +177,10 @@ void ClangTidyClazyTool::startTool(bool askUserForFileSelection)
if (fileInfos.isEmpty())
return;
auto clangTool = new ClangTidyClazyRunControl(runControl, project->activeTarget(), fileInfos);
auto clangTool = new ClangTidyClazyRunControl(runControl,
project->activeTarget(),
getDiagnosticConfig(project),
fileInfos);
m_stopAction->disconnect();
connect(m_stopAction, &QAction::triggered, runControl, [runControl] {

View File

@@ -34,6 +34,8 @@
namespace ClangTools {
namespace Internal {
static const char SETTINGS_KEY_USE_GLOBAL_SETTINGS[] = "ClangTools.UseGlobalSettings";
static const char SETTINGS_KEY_DIAGNOSTIC_CONFIG[] = "ClangTools.DiagnosticConfig";
static const char SETTINGS_KEY_SELECTED_DIRS[] = "ClangTools.SelectedDirs";
static const char SETTINGS_KEY_SELECTED_FILES[] = "ClangTools.SelectedFiles";
static const char SETTINGS_KEY_SUPPRESSED_DIAGS[] = "ClangTools.SuppressedDiagnostics";
@@ -80,6 +82,11 @@ void ClangToolsProjectSettings::removeAllSuppressedDiagnostics()
void ClangToolsProjectSettings::load()
{
const QVariant useGlobalVariant = m_project->namedSettings(SETTINGS_KEY_USE_GLOBAL_SETTINGS);
m_useGlobalSettings = useGlobalVariant.isValid() ? useGlobalVariant.toBool() : true;
m_diagnosticConfig = Core::Id::fromSetting(
m_project->namedSettings(SETTINGS_KEY_DIAGNOSTIC_CONFIG));
auto toFileName = [](const QString &s) { return Utils::FileName::fromString(s); };
const QStringList dirs = m_project->namedSettings(SETTINGS_KEY_SELECTED_DIRS).toStringList();
@@ -115,6 +122,9 @@ void ClangToolsProjectSettings::load()
void ClangToolsProjectSettings::store()
{
m_project->setNamedSettings(SETTINGS_KEY_USE_GLOBAL_SETTINGS, m_useGlobalSettings);
m_project->setNamedSettings(SETTINGS_KEY_DIAGNOSTIC_CONFIG, m_diagnosticConfig.toSetting());
const QStringList dirs = Utils::transform(m_selectedDirs.toList(), &Utils::FileName::toString);
m_project->setNamedSettings(SETTINGS_KEY_SELECTED_DIRS, dirs);
@@ -134,6 +144,26 @@ void ClangToolsProjectSettings::store()
m_project->setNamedSettings(SETTINGS_KEY_SUPPRESSED_DIAGS, list);
}
bool ClangToolsProjectSettings::useGlobalSettings() const
{
return m_useGlobalSettings;
}
void ClangToolsProjectSettings::setUseGlobalSettings(bool useGlobalSettings)
{
m_useGlobalSettings = useGlobalSettings;
}
Core::Id ClangToolsProjectSettings::diagnosticConfig() const
{
return m_diagnosticConfig;
}
void ClangToolsProjectSettings::setDiagnosticConfig(const Core::Id &diagnosticConfig)
{
m_diagnosticConfig = diagnosticConfig;
}
ClangToolsProjectSettingsManager::ClangToolsProjectSettingsManager()
{
QObject::connect(ProjectExplorer::SessionManager::instance(),

View File

@@ -27,6 +27,7 @@
#include <QObject>
#include <coreplugin/id.h>
#include <projectexplorer/project.h>
#include <utils/fileutils.h>
@@ -74,6 +75,12 @@ public:
ClangToolsProjectSettings(ProjectExplorer::Project *project);
~ClangToolsProjectSettings() override;
bool useGlobalSettings() const;
void setUseGlobalSettings(bool useGlobalSettings);
Core::Id diagnosticConfig() const;
void setDiagnosticConfig(const Core::Id &diagnosticConfig);
QSet<Utils::FileName> selectedDirs() const { return m_selectedDirs; }
void setSelectedDirs(const QSet<Utils::FileName> &value) { m_selectedDirs = value; }
@@ -93,6 +100,8 @@ private:
void store();
ProjectExplorer::Project *m_project;
bool m_useGlobalSettings = true;
Core::Id m_diagnosticConfig;
QSet<Utils::FileName> m_selectedDirs;
QSet<Utils::FileName> m_selectedFiles;
SuppressedDiagnosticsList m_suppressedDiagnostics;

View File

@@ -69,12 +69,13 @@ static void connectToClangDiagnosticConfigsDialog(QPushButton *button)
ClangDiagnosticConfigsSelectionWidget::ClangDiagnosticConfigsSelectionWidget(QWidget *parent)
: QWidget(parent)
, m_label(new QLabel(tr("Diagnostic Configuration:"), this))
, m_selectionComboBox(new QComboBox(this))
{
auto *layout = new QHBoxLayout(this);
layout->setMargin(0);
setLayout(layout);
layout->addWidget(new QLabel(tr("Diagnostic Configuration:"), this));
layout->addWidget(m_label);
layout->addWidget(m_selectionComboBox);
auto *manageButton = new QPushButton(tr("Manage..."), this);
layout->addWidget(manageButton);
@@ -133,4 +134,9 @@ void ClangDiagnosticConfigsSelectionWidget::refresh(Core::Id id)
connectToCurrentIndexChanged();
}
void ClangDiagnosticConfigsSelectionWidget::showLabel(bool show)
{
m_label->setVisible(show);
}
} // CppTools namespace

View File

@@ -33,6 +33,7 @@
QT_BEGIN_NAMESPACE
class QComboBox;
class QLabel;
QT_END_NAMESPACE
namespace CppTools {
@@ -48,6 +49,8 @@ public:
void refresh(Core::Id id);
void showLabel(bool show);
signals:
void currentConfigChanged(const Core::Id &currentConfigId);
@@ -58,6 +61,7 @@ private:
QMetaObject::Connection m_currentIndexChangedConnection;
ClangDiagnosticConfigsModel m_diagnosticConfigsModel;
QLabel *m_label = nullptr;
QComboBox *m_selectionComboBox = nullptr;
};