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