forked from qt-creator/qt-creator
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 <nikolai.kosjar@qt.io>
This commit is contained in:
@@ -71,83 +71,17 @@ using namespace ProjectExplorer;
|
|||||||
namespace ClangTools {
|
namespace ClangTools {
|
||||||
namespace Internal {
|
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(
|
|
||||||
"<html><head/><body>"
|
|
||||||
"<p>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.</p>"
|
|
||||||
"<p>Do you want to continue and run the tool in %2 mode?</p>"
|
|
||||||
"</body></html>")
|
|
||||||
.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<Project> m_project;
|
|
||||||
bool m_success = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
ClangStaticAnalyzerRunControl::ClangStaticAnalyzerRunControl(RunControl *runControl, Target *target)
|
ClangStaticAnalyzerRunControl::ClangStaticAnalyzerRunControl(RunControl *runControl, Target *target)
|
||||||
: ClangToolRunControl(runControl, target)
|
: ClangToolRunControl(runControl, target)
|
||||||
{
|
{
|
||||||
setDisplayName("ClangStaticAnalyzerRunner");
|
setDisplayName("ClangStaticAnalyzerRunner");
|
||||||
|
|
||||||
auto *projectBuilder = new ProjectBuilder(runControl, target->project());
|
|
||||||
addStartDependency(projectBuilder);
|
|
||||||
m_projectBuilder = projectBuilder;
|
|
||||||
|
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
ClangToolRunner *ClangStaticAnalyzerRunControl::createRunner()
|
ClangToolRunner *ClangStaticAnalyzerRunControl::createRunner()
|
||||||
{
|
{
|
||||||
QTC_ASSERT(!m_clangLogFileDir.isEmpty(), return 0);
|
QTC_ASSERT(!m_clangLogFileDir.isEmpty(), return nullptr);
|
||||||
|
|
||||||
auto runner = new ClangStaticAnalyzerRunner(m_clangExecutable,
|
auto runner = new ClangStaticAnalyzerRunner(m_clangExecutable,
|
||||||
m_clangLogFileDir,
|
m_clangLogFileDir,
|
||||||
|
|||||||
@@ -113,6 +113,78 @@ static QStringList extraClangToolsAppendOptions() {
|
|||||||
namespace ClangTools {
|
namespace ClangTools {
|
||||||
namespace Internal {
|
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(
|
||||||
|
"<html><head/><body>"
|
||||||
|
"<p>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.</p>"
|
||||||
|
"<p>Do you want to continue and run the tool in %2 mode?</p>"
|
||||||
|
"</body></html>")
|
||||||
|
.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<Project> m_project;
|
||||||
|
ClangToolRunControl *m_parent;
|
||||||
|
bool m_enabled = true;
|
||||||
|
bool m_success = false;
|
||||||
|
};
|
||||||
|
|
||||||
static AnalyzeUnits unitsToAnalyzeFromProjectParts(const QVector<ProjectPart::Ptr> projectParts,
|
static AnalyzeUnits unitsToAnalyzeFromProjectParts(const QVector<ProjectPart::Ptr> projectParts,
|
||||||
const QString &clangVersion,
|
const QString &clangVersion,
|
||||||
const QString &clangResourceDirectory)
|
const QString &clangResourceDirectory)
|
||||||
@@ -173,9 +245,18 @@ static QDebug operator<<(QDebug debug, const AnalyzeUnits &analyzeUnits)
|
|||||||
|
|
||||||
ClangToolRunControl::ClangToolRunControl(RunControl *runControl, Target *target)
|
ClangToolRunControl::ClangToolRunControl(RunControl *runControl, Target *target)
|
||||||
: RunWorker(runControl)
|
: RunWorker(runControl)
|
||||||
|
, m_projectBuilder(new ProjectBuilder(runControl, target->project(), this))
|
||||||
, m_clangExecutable(CppTools::clangExecutable(CLANG_BINDIR))
|
, m_clangExecutable(CppTools::clangExecutable(CLANG_BINDIR))
|
||||||
, m_target(target)
|
, 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()
|
void ClangToolRunControl::init()
|
||||||
@@ -197,11 +278,13 @@ void ClangToolRunControl::init()
|
|||||||
|
|
||||||
void ClangToolRunControl::start()
|
void ClangToolRunControl::start()
|
||||||
{
|
{
|
||||||
m_success = m_projectBuilder ? m_projectBuilder->success() : true;
|
if (ClangToolsSettings::instance()->savedBuildBeforeAnalysis()) {
|
||||||
if (!m_success) {
|
QTC_ASSERT(m_projectBuilder, return;);
|
||||||
|
if (!m_projectBuilder->success()) {
|
||||||
reportFailure();
|
reportFailure();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const QString &toolName = tool()->name();
|
const QString &toolName = tool()->name();
|
||||||
if (m_clangExecutable.isEmpty()) {
|
if (m_clangExecutable.isEmpty()) {
|
||||||
|
|||||||
@@ -49,13 +49,6 @@ struct AnalyzeUnit {
|
|||||||
};
|
};
|
||||||
typedef QList<AnalyzeUnit> AnalyzeUnits;
|
typedef QList<AnalyzeUnit> AnalyzeUnits;
|
||||||
|
|
||||||
class BaseProjectBuilder
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~BaseProjectBuilder() {}
|
|
||||||
virtual bool success() const { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class ClangToolRunControl : public ProjectExplorer::RunWorker
|
class ClangToolRunControl : public ProjectExplorer::RunWorker
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -66,11 +59,11 @@ public:
|
|||||||
|
|
||||||
bool success() const { return m_success; } // For testing.
|
bool success() const { return m_success; } // For testing.
|
||||||
|
|
||||||
|
virtual ClangTool *tool() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
virtual ClangTool *tool() = 0;
|
|
||||||
|
|
||||||
virtual ClangToolRunner *createRunner() = 0;
|
virtual ClangToolRunner *createRunner() = 0;
|
||||||
|
|
||||||
void onRunnerFinishedWithSuccess(const QString &filePath, const QString &logFilePath);
|
void onRunnerFinishedWithSuccess(const QString &filePath, const QString &logFilePath);
|
||||||
@@ -91,7 +84,7 @@ private:
|
|||||||
void finalize();
|
void finalize();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
BaseProjectBuilder *m_projectBuilder = nullptr;
|
ProjectBuilder *m_projectBuilder;
|
||||||
Utils::Environment m_environment;
|
Utils::Environment m_environment;
|
||||||
QString m_clangExecutable;
|
QString m_clangExecutable;
|
||||||
QString m_clangLogFileDir;
|
QString m_clangLogFileDir;
|
||||||
|
|||||||
@@ -49,6 +49,12 @@ ClangToolsConfigWidget::ClangToolsConfigWidget(
|
|||||||
connect(m_ui->simultaneousProccessesSpinBox,
|
connect(m_ui->simultaneousProccessesSpinBox,
|
||||||
static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
|
static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
|
||||||
[settings](int count) { settings->setSimultaneousProcesses(count); });
|
[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()
|
ClangToolsConfigWidget::~ClangToolsConfigWidget()
|
||||||
|
|||||||
@@ -20,14 +20,14 @@
|
|||||||
<string>General</string>
|
<string>General</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QFormLayout" name="formLayout">
|
<layout class="QFormLayout" name="formLayout">
|
||||||
<item row="0" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="label_2">
|
<widget class="QLabel" name="label_2">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Simultaneous processes:</string>
|
<string>Simultaneous processes:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item row="1" column="1">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QSpinBox" name="simultaneousProccessesSpinBox">
|
<widget class="QSpinBox" name="simultaneousProccessesSpinBox">
|
||||||
@@ -54,6 +54,13 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QCheckBox" name="buildBeforeAnalysis">
|
||||||
|
<property name="text">
|
||||||
|
<string>Build the project before analysis</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
|
||||||
static const char simultaneousProcessesKey[] = "simultaneousProcesses";
|
static const char simultaneousProcessesKey[] = "simultaneousProcesses";
|
||||||
|
static const char buildBeforeAnalysisKey[] = "buildBeforeAnalysis";
|
||||||
|
|
||||||
namespace ClangTools {
|
namespace ClangTools {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
@@ -66,6 +67,29 @@ void ClangToolsSettings::setSimultaneousProcesses(int processes)
|
|||||||
m_simultaneousProcesses = 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()
|
void ClangToolsSettings::readSettings()
|
||||||
{
|
{
|
||||||
QSettings *settings = Core::ICore::settings();
|
QSettings *settings = Core::ICore::settings();
|
||||||
@@ -76,6 +100,9 @@ void ClangToolsSettings::readSettings()
|
|||||||
= settings->value(QString(simultaneousProcessesKey),
|
= settings->value(QString(simultaneousProcessesKey),
|
||||||
defaultSimultaneousProcesses).toInt();
|
defaultSimultaneousProcesses).toInt();
|
||||||
|
|
||||||
|
m_buildBeforeAnalysis = settings->value(QString(buildBeforeAnalysisKey), true).toBool();
|
||||||
|
updateSavedBuildBeforeAnalysiIfRequired();
|
||||||
|
|
||||||
settings->endGroup();
|
settings->endGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,8 +111,10 @@ void ClangToolsSettings::writeSettings()
|
|||||||
QSettings *settings = Core::ICore::settings();
|
QSettings *settings = Core::ICore::settings();
|
||||||
settings->beginGroup(QString(Constants::SETTINGS_ID));
|
settings->beginGroup(QString(Constants::SETTINGS_ID));
|
||||||
settings->setValue(QString(simultaneousProcessesKey), m_simultaneousProcesses);
|
settings->setValue(QString(simultaneousProcessesKey), m_simultaneousProcesses);
|
||||||
|
settings->setValue(QString(buildBeforeAnalysisKey), m_buildBeforeAnalysis);
|
||||||
|
|
||||||
m_savedSimultaneousProcesses = m_simultaneousProcesses;
|
m_savedSimultaneousProcesses = m_simultaneousProcesses;
|
||||||
|
updateSavedBuildBeforeAnalysiIfRequired();
|
||||||
|
|
||||||
settings->endGroup();
|
settings->endGroup();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,29 +25,42 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
namespace ClangTools {
|
namespace ClangTools {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
class ClangToolsSettings
|
class ClangToolsSettings : public QObject
|
||||||
{
|
{
|
||||||
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
static ClangToolsSettings *instance();
|
static ClangToolsSettings *instance();
|
||||||
|
|
||||||
void writeSettings();
|
void writeSettings();
|
||||||
|
|
||||||
int savedSimultaneousProcesses() const;
|
int savedSimultaneousProcesses() const;
|
||||||
|
bool savedBuildBeforeAnalysis() const;
|
||||||
|
|
||||||
int simultaneousProcesses() const;
|
int simultaneousProcesses() const;
|
||||||
void setSimultaneousProcesses(int processes);
|
void setSimultaneousProcesses(int processes);
|
||||||
|
|
||||||
|
int buildBeforeAnalysis() const;
|
||||||
|
void setBuildBeforeAnalysis(bool build);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void buildBeforeAnalysisChanged(bool checked) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ClangToolsSettings();
|
ClangToolsSettings();
|
||||||
void readSettings();
|
void readSettings();
|
||||||
|
|
||||||
|
void updateSavedBuildBeforeAnalysiIfRequired();
|
||||||
|
|
||||||
int m_simultaneousProcesses = -1;
|
int m_simultaneousProcesses = -1;
|
||||||
int m_savedSimultaneousProcesses = -1;
|
int m_savedSimultaneousProcesses = -1;
|
||||||
|
bool m_buildBeforeAnalysis = false;
|
||||||
|
bool m_savedBuildBeforeAnalysis= false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|||||||
Reference in New Issue
Block a user