From 97fc02b247284cee8f52acf0a3dcb265451ce5f6 Mon Sep 17 00:00:00 2001 From: Ivan Donchevskii Date: Wed, 2 May 2018 16:13:01 +0200 Subject: [PATCH] ClangTools: Add settings for build project dependency All Clang tools get support for running project build before themselves or skipping that step. Before this change static analyzer always ran it and ClangTidy+Clazy tool always skipped. Change-Id: Idb9fbc27f0589472abb0f9d207857eb79c0079fd Reviewed-by: Nikolai Kosjar --- .../clangstaticanalyzerruncontrol.cpp | 68 +------------- .../clangtools/clangtoolruncontrol.cpp | 91 ++++++++++++++++++- src/plugins/clangtools/clangtoolruncontrol.h | 13 +-- .../clangtools/clangtoolsconfigwidget.cpp | 6 ++ .../clangtools/clangtoolsconfigwidget.ui | 11 ++- src/plugins/clangtools/clangtoolssettings.cpp | 29 ++++++ src/plugins/clangtools/clangtoolssettings.h | 15 ++- 7 files changed, 149 insertions(+), 84 deletions(-) diff --git a/src/plugins/clangtools/clangstaticanalyzerruncontrol.cpp b/src/plugins/clangtools/clangstaticanalyzerruncontrol.cpp index e9585665337..8bacb4af88d 100644 --- a/src/plugins/clangtools/clangstaticanalyzerruncontrol.cpp +++ b/src/plugins/clangtools/clangstaticanalyzerruncontrol.cpp @@ -71,83 +71,17 @@ using namespace ProjectExplorer; namespace ClangTools { namespace Internal { -class ProjectBuilder : public RunWorker, public BaseProjectBuilder -{ -public: - ProjectBuilder(RunControl *runControl, Project *project) - : RunWorker(runControl), m_project(project) - { - setDisplayName("ProjectBuilder"); - } - - bool success() const override { return m_success; } - -private: - void start() final - { - Target *target = m_project->activeTarget(); - QTC_ASSERT(target, reportFailure(); return); - - BuildConfiguration::BuildType buildType = BuildConfiguration::Unknown; - if (const BuildConfiguration *buildConfig = target->activeBuildConfiguration()) - buildType = buildConfig->buildType(); - - if (buildType == BuildConfiguration::Release) { - const QString wrongMode = ClangStaticAnalyzerTool::tr("Release"); - const QString toolName = ClangStaticAnalyzerTool::tr("Clang Static Analyzer"); - const QString title = ClangStaticAnalyzerTool::tr("Run %1 in %2 Mode?").arg(toolName) - .arg(wrongMode); - const QString message = ClangStaticAnalyzerTool::tr( - "" - "

You are trying to run the tool \"%1\" on an application in %2 mode. The tool is " - "designed to be used in Debug mode since enabled assertions can reduce the number of " - "false positives.

" - "

Do you want to continue and run the tool in %2 mode?

" - "") - .arg(toolName).arg(wrongMode); - if (Utils::CheckableMessageBox::doNotAskAgainQuestion(Core::ICore::mainWindow(), - title, message, Core::ICore::settings(), - "ClangStaticAnalyzerCorrectModeWarning") != QDialogButtonBox::Yes) - { - reportFailure(); - return; - } - } - - connect(BuildManager::instance(), &BuildManager::buildQueueFinished, - this, &ProjectBuilder::onBuildFinished, Qt::QueuedConnection); - - ProjectExplorerPlugin::buildProject(m_project); - } - - void onBuildFinished(bool success) - { - disconnect(BuildManager::instance(), &BuildManager::buildQueueFinished, - this, &ProjectBuilder::onBuildFinished); - m_success = success; - reportDone(); - } - -private: - QPointer m_project; - bool m_success = false; -}; - ClangStaticAnalyzerRunControl::ClangStaticAnalyzerRunControl(RunControl *runControl, Target *target) : ClangToolRunControl(runControl, target) { setDisplayName("ClangStaticAnalyzerRunner"); - auto *projectBuilder = new ProjectBuilder(runControl, target->project()); - addStartDependency(projectBuilder); - m_projectBuilder = projectBuilder; - init(); } ClangToolRunner *ClangStaticAnalyzerRunControl::createRunner() { - QTC_ASSERT(!m_clangLogFileDir.isEmpty(), return 0); + QTC_ASSERT(!m_clangLogFileDir.isEmpty(), return nullptr); auto runner = new ClangStaticAnalyzerRunner(m_clangExecutable, m_clangLogFileDir, diff --git a/src/plugins/clangtools/clangtoolruncontrol.cpp b/src/plugins/clangtools/clangtoolruncontrol.cpp index d2e03f48a47..6d8e674319d 100644 --- a/src/plugins/clangtools/clangtoolruncontrol.cpp +++ b/src/plugins/clangtools/clangtoolruncontrol.cpp @@ -113,6 +113,78 @@ static QStringList extraClangToolsAppendOptions() { namespace ClangTools { namespace Internal { +class ProjectBuilder : public RunWorker +{ +public: + ProjectBuilder(RunControl *runControl, Project *project, ClangToolRunControl *parent) + : RunWorker(runControl), m_project(project), m_parent(parent) + { + setDisplayName("ProjectBuilder"); + } + + void setEnabled(bool enabled) { m_enabled = enabled; } + + bool success() const { return m_success; } + +private: + void start() final + { + if (!m_enabled) { + ProjectExplorerPlugin::saveModifiedFiles(); + onBuildFinished(true); + return; + } + + Target *target = m_project->activeTarget(); + QTC_ASSERT(target, reportFailure(); return); + + BuildConfiguration::BuildType buildType = BuildConfiguration::Unknown; + if (const BuildConfiguration *buildConfig = target->activeBuildConfiguration()) + buildType = buildConfig->buildType(); + + if (buildType == BuildConfiguration::Release) { + const QString wrongMode = ClangToolRunControl::tr("Release"); + const QString toolName = m_parent->tool()->name(); + const QString title = ClangToolRunControl::tr("Run %1 in %2 Mode?").arg(toolName) + .arg(wrongMode); + const QString message = ClangToolRunControl::tr( + "" + "

You are trying to run the tool \"%1\" on an application in %2 mode. The tool is " + "designed to be used in Debug mode since enabled assertions can reduce the number of " + "false positives.

" + "

Do you want to continue and run the tool in %2 mode?

" + "") + .arg(toolName).arg(wrongMode); + if (Utils::CheckableMessageBox::doNotAskAgainQuestion(Core::ICore::mainWindow(), + title, message, Core::ICore::settings(), + "ClangStaticAnalyzerCorrectModeWarning") != QDialogButtonBox::Yes) + { + reportFailure(); + return; + } + } + + connect(BuildManager::instance(), &BuildManager::buildQueueFinished, + this, &ProjectBuilder::onBuildFinished, Qt::QueuedConnection); + + ProjectExplorerPlugin::buildProject(m_project); + } + + void onBuildFinished(bool success) + { + disconnect(BuildManager::instance(), &BuildManager::buildQueueFinished, + this, &ProjectBuilder::onBuildFinished); + m_success = success; + reportDone(); + } + +private: + QPointer m_project; + ClangToolRunControl *m_parent; + bool m_enabled = true; + bool m_success = false; +}; + static AnalyzeUnits unitsToAnalyzeFromProjectParts(const QVector projectParts, const QString &clangVersion, const QString &clangResourceDirectory) @@ -173,9 +245,18 @@ static QDebug operator<<(QDebug debug, const AnalyzeUnits &analyzeUnits) ClangToolRunControl::ClangToolRunControl(RunControl *runControl, Target *target) : RunWorker(runControl) + , m_projectBuilder(new ProjectBuilder(runControl, target->project(), this)) , m_clangExecutable(CppTools::clangExecutable(CLANG_BINDIR)) , m_target(target) { + addStartDependency(m_projectBuilder); + + auto *settings = ClangToolsSettings::instance(); + m_projectBuilder->setEnabled(settings->savedBuildBeforeAnalysis()); + + connect(settings, &ClangToolsSettings::buildBeforeAnalysisChanged, this, [this](bool checked) { + m_projectBuilder->setEnabled(checked); + }); } void ClangToolRunControl::init() @@ -197,10 +278,12 @@ void ClangToolRunControl::init() void ClangToolRunControl::start() { - m_success = m_projectBuilder ? m_projectBuilder->success() : true; - if (!m_success) { - reportFailure(); - return; + if (ClangToolsSettings::instance()->savedBuildBeforeAnalysis()) { + QTC_ASSERT(m_projectBuilder, return;); + if (!m_projectBuilder->success()) { + reportFailure(); + return; + } } const QString &toolName = tool()->name(); diff --git a/src/plugins/clangtools/clangtoolruncontrol.h b/src/plugins/clangtools/clangtoolruncontrol.h index c8339a40bc4..0d13bf9263c 100644 --- a/src/plugins/clangtools/clangtoolruncontrol.h +++ b/src/plugins/clangtools/clangtoolruncontrol.h @@ -49,13 +49,6 @@ struct AnalyzeUnit { }; typedef QList AnalyzeUnits; -class BaseProjectBuilder -{ -public: - virtual ~BaseProjectBuilder() {} - virtual bool success() const { return true; } -}; - class ClangToolRunControl : public ProjectExplorer::RunWorker { Q_OBJECT @@ -66,11 +59,11 @@ public: bool success() const { return m_success; } // For testing. + virtual ClangTool *tool() = 0; + protected: void init(); - virtual ClangTool *tool() = 0; - virtual ClangToolRunner *createRunner() = 0; void onRunnerFinishedWithSuccess(const QString &filePath, const QString &logFilePath); @@ -91,7 +84,7 @@ private: void finalize(); protected: - BaseProjectBuilder *m_projectBuilder = nullptr; + ProjectBuilder *m_projectBuilder; Utils::Environment m_environment; QString m_clangExecutable; QString m_clangLogFileDir; diff --git a/src/plugins/clangtools/clangtoolsconfigwidget.cpp b/src/plugins/clangtools/clangtoolsconfigwidget.cpp index 16609a5bbd4..d99c81c6ac6 100644 --- a/src/plugins/clangtools/clangtoolsconfigwidget.cpp +++ b/src/plugins/clangtools/clangtoolsconfigwidget.cpp @@ -49,6 +49,12 @@ ClangToolsConfigWidget::ClangToolsConfigWidget( connect(m_ui->simultaneousProccessesSpinBox, static_cast(&QSpinBox::valueChanged), [settings](int count) { settings->setSimultaneousProcesses(count); }); + + m_ui->buildBeforeAnalysis->setCheckState(settings->savedBuildBeforeAnalysis() + ? Qt::Checked : Qt::Unchecked); + connect(m_ui->buildBeforeAnalysis, &QCheckBox::toggled, [settings](bool checked) { + settings->setBuildBeforeAnalysis(checked); + }); } ClangToolsConfigWidget::~ClangToolsConfigWidget() diff --git a/src/plugins/clangtools/clangtoolsconfigwidget.ui b/src/plugins/clangtools/clangtoolsconfigwidget.ui index 05897bfe1f0..2f7e41e5b55 100644 --- a/src/plugins/clangtools/clangtoolsconfigwidget.ui +++ b/src/plugins/clangtools/clangtoolsconfigwidget.ui @@ -20,14 +20,14 @@ General - + Simultaneous processes: - + @@ -54,6 +54,13 @@ + + + + Build the project before analysis + + + diff --git a/src/plugins/clangtools/clangtoolssettings.cpp b/src/plugins/clangtools/clangtoolssettings.cpp index 50bad3f82af..af4fa263367 100644 --- a/src/plugins/clangtools/clangtoolssettings.cpp +++ b/src/plugins/clangtools/clangtoolssettings.cpp @@ -36,6 +36,7 @@ #include static const char simultaneousProcessesKey[] = "simultaneousProcesses"; +static const char buildBeforeAnalysisKey[] = "buildBeforeAnalysis"; namespace ClangTools { namespace Internal { @@ -66,6 +67,29 @@ void ClangToolsSettings::setSimultaneousProcesses(int processes) m_simultaneousProcesses = processes; } +bool ClangToolsSettings::savedBuildBeforeAnalysis() const +{ + return m_savedBuildBeforeAnalysis; +} + +int ClangToolsSettings::buildBeforeAnalysis() const +{ + return m_buildBeforeAnalysis; +} + +void ClangToolsSettings::setBuildBeforeAnalysis(bool build) +{ + m_buildBeforeAnalysis = build; +} + +void ClangToolsSettings::updateSavedBuildBeforeAnalysiIfRequired() +{ + if (m_savedBuildBeforeAnalysis == m_buildBeforeAnalysis) + return; + m_savedBuildBeforeAnalysis = m_buildBeforeAnalysis; + emit buildBeforeAnalysisChanged(m_savedBuildBeforeAnalysis); +} + void ClangToolsSettings::readSettings() { QSettings *settings = Core::ICore::settings(); @@ -76,6 +100,9 @@ void ClangToolsSettings::readSettings() = settings->value(QString(simultaneousProcessesKey), defaultSimultaneousProcesses).toInt(); + m_buildBeforeAnalysis = settings->value(QString(buildBeforeAnalysisKey), true).toBool(); + updateSavedBuildBeforeAnalysiIfRequired(); + settings->endGroup(); } @@ -84,8 +111,10 @@ void ClangToolsSettings::writeSettings() QSettings *settings = Core::ICore::settings(); settings->beginGroup(QString(Constants::SETTINGS_ID)); settings->setValue(QString(simultaneousProcessesKey), m_simultaneousProcesses); + settings->setValue(QString(buildBeforeAnalysisKey), m_buildBeforeAnalysis); m_savedSimultaneousProcesses = m_simultaneousProcesses; + updateSavedBuildBeforeAnalysiIfRequired(); settings->endGroup(); } diff --git a/src/plugins/clangtools/clangtoolssettings.h b/src/plugins/clangtools/clangtoolssettings.h index 528407fe50b..1bc72c968e9 100644 --- a/src/plugins/clangtools/clangtoolssettings.h +++ b/src/plugins/clangtools/clangtoolssettings.h @@ -25,29 +25,42 @@ #pragma once +#include #include namespace ClangTools { namespace Internal { -class ClangToolsSettings +class ClangToolsSettings : public QObject { + Q_OBJECT public: static ClangToolsSettings *instance(); void writeSettings(); int savedSimultaneousProcesses() const; + bool savedBuildBeforeAnalysis() const; int simultaneousProcesses() const; void setSimultaneousProcesses(int processes); + int buildBeforeAnalysis() const; + void setBuildBeforeAnalysis(bool build); + +signals: + void buildBeforeAnalysisChanged(bool checked) const; + private: ClangToolsSettings(); void readSettings(); + void updateSavedBuildBeforeAnalysiIfRequired(); + int m_simultaneousProcesses = -1; int m_savedSimultaneousProcesses = -1; + bool m_buildBeforeAnalysis = false; + bool m_savedBuildBeforeAnalysis= false; }; } // namespace Internal