summaryrefslogtreecommitdiff
path: root/src/plugins/clangtools
diff options
context:
space:
mode:
authorNikolai Kosjar <nikolai.kosjar@qt.io>2019-08-28 08:56:22 +0200
committerNikolai Kosjar <nikolai.kosjar@qt.io>2019-09-12 13:35:01 +0000
commitfc37ea4276c9728a6fa4e3dfab8ce8df98b81d7d (patch)
treed746044f21d96bb82a5552d4120349317a16020e /src/plugins/clangtools
parent8890a7412c154d48fc160a366fdbe28021ca0138 (diff)
downloadqt-creator-fc37ea4276c9728a6fa4e3dfab8ce8df98b81d7d.tar.gz
ClangTools: Add UI for specifying executables
Add a new group box "Executables" for this. Hide the UI for clazy-standalone unless QTC_USE_CLAZY_STANDALONE_PATH is set as there is no released version with the needed -export-fixes option. Rename the previous group box from "General" to "Run Options". Change-Id: Ia9daf66c40d3a7eea98b31d9c086886d29466490 Reviewed-by: Cristian Adam <cristian.adam@qt.io> Reviewed-by: Nikolai Kosjar <nikolai.kosjar@qt.io>
Diffstat (limited to 'src/plugins/clangtools')
-rw-r--r--src/plugins/clangtools/clangtidyclazyrunner.cpp5
-rw-r--r--src/plugins/clangtools/clangtoolruncontrol.cpp14
-rw-r--r--src/plugins/clangtools/clangtoolrunner.h1
-rw-r--r--src/plugins/clangtools/clangtoolsconstants.h3
-rw-r--r--src/plugins/clangtools/clangtoolssettings.cpp41
-rw-r--r--src/plugins/clangtools/clangtoolssettings.h13
-rw-r--r--src/plugins/clangtools/clangtoolsutils.cpp84
-rw-r--r--src/plugins/clangtools/clangtoolsutils.h8
-rw-r--r--src/plugins/clangtools/settingswidget.cpp74
-rw-r--r--src/plugins/clangtools/settingswidget.ui37
10 files changed, 273 insertions, 7 deletions
diff --git a/src/plugins/clangtools/clangtidyclazyrunner.cpp b/src/plugins/clangtools/clangtidyclazyrunner.cpp
index 1a3a0cea47..59a2f5d216 100644
--- a/src/plugins/clangtools/clangtidyclazyrunner.cpp
+++ b/src/plugins/clangtools/clangtidyclazyrunner.cpp
@@ -26,6 +26,7 @@
#include "clangtidyclazyrunner.h"
#include "clangtoolssettings.h"
+#include "clangtoolsutils.h"
#include <coreplugin/icore.h>
@@ -121,7 +122,7 @@ ClangTidyRunner::ClangTidyRunner(const ClangDiagnosticConfig &config, QObject *p
{
setName(tr("Clang-Tidy"));
setOutputFileFormat(OutputFileFormat::Yaml);
- setExecutable(Core::ICore::clangTidyExecutable(CLANG_BINDIR));
+ setExecutable(clangTidyExecutable());
setArgsCreator([this, config](const QStringList &baseOptions) {
return QStringList()
<< tidyChecksArguments(config)
@@ -136,7 +137,7 @@ ClazyStandaloneRunner::ClazyStandaloneRunner(const ClangDiagnosticConfig &config
{
setName(tr("Clazy"));
setOutputFileFormat(OutputFileFormat::Yaml);
- setExecutable(qEnvironmentVariable("QTC_USE_CLAZY_STANDALONE_PATH"));
+ setExecutable(clazyStandaloneExecutable());
setArgsCreator([this, config](const QStringList &baseOptions) {
return QStringList()
<< clazyChecksArguments(config)
diff --git a/src/plugins/clangtools/clangtoolruncontrol.cpp b/src/plugins/clangtools/clangtoolruncontrol.cpp
index 578839bbbb..eed06d5841 100644
--- a/src/plugins/clangtools/clangtoolruncontrol.cpp
+++ b/src/plugins/clangtools/clangtoolruncontrol.cpp
@@ -310,7 +310,7 @@ void ClangToolRunWorker::start()
m_queue.clear();
for (const AnalyzeUnit &unit : unitsToProcess) {
- for (auto creator : runnerCreators())
+ for (const RunnerCreator &creator : runnerCreators())
m_queue << QueueItem{unit, creator};
}
m_initialQueueSize = m_queue.count();
@@ -378,6 +378,18 @@ void ClangToolRunWorker::analyzeNextFile()
ClangToolRunner *runner = queueItem.runnerCreator();
m_runners.insert(runner);
+
+ const QString executable = runner->executable();
+ if (!isFileExecutable(executable)) {
+ const QString errorMessage = tr("%1: Invalid executable \"%2\", stop.")
+ .arg(runner->name(), executable);
+ TaskHub::addTask(Task::Error, errorMessage, Debugger::Constants::ANALYZERTASK_ID);
+ TaskHub::requestPopup();
+ reportFailure(errorMessage);
+ stop();
+ return;
+ }
+
QTC_ASSERT(runner->run(unit.file, unit.arguments), return);
appendMessage(tr("Analyzing \"%1\" [%2].")
diff --git a/src/plugins/clangtools/clangtoolrunner.h b/src/plugins/clangtools/clangtoolrunner.h
index e38b5bcc4a..493722ca64 100644
--- a/src/plugins/clangtools/clangtoolrunner.h
+++ b/src/plugins/clangtools/clangtoolrunner.h
@@ -62,6 +62,7 @@ public:
QString name() const { return m_name; }
OutputFileFormat outputFileFormat() const { return m_outputFileFormat; }
+ QString executable() const { return m_executable; }
QString filePath() const { return m_filePath; }
QString logFilePath() const { return m_logFile; }
diff --git a/src/plugins/clangtools/clangtoolsconstants.h b/src/plugins/clangtools/clangtoolsconstants.h
index 6bfe64ca87..0b711162c9 100644
--- a/src/plugins/clangtools/clangtoolsconstants.h
+++ b/src/plugins/clangtools/clangtoolsconstants.h
@@ -32,5 +32,8 @@ const char SETTINGS_PAGE_ID[] = "Analyzer.ClangTools.Settings";
const char SETTINGS_ID[] = "ClangTools";
const char CLANGTIDYCLAZY_RUN_MODE[] = "ClangTidyClazy.RunMode";
+const char CLANG_TIDY_EXECUTABLE_NAME[] = "clang-tidy";
+const char CLAZY_STANDALONE_EXECUTABLE_NAME[] = "clazy-standalone";
+
} // Constants
} // ClangTools
diff --git a/src/plugins/clangtools/clangtoolssettings.cpp b/src/plugins/clangtools/clangtoolssettings.cpp
index 059f15ecbf..86f152f660 100644
--- a/src/plugins/clangtools/clangtoolssettings.cpp
+++ b/src/plugins/clangtools/clangtoolssettings.cpp
@@ -38,6 +38,8 @@
static const char simultaneousProcessesKey[] = "simultaneousProcesses";
static const char buildBeforeAnalysisKey[] = "buildBeforeAnalysis";
static const char diagnosticConfigIdKey[] = "diagnosticConfigId";
+static const char clangTidyExecutableKey[] = "clangTidyExecutable";
+static const char clazyStandaloneExecutableKey[] = "clazyStandaloneExecutable";
namespace ClangTools {
namespace Internal {
@@ -106,6 +108,36 @@ void ClangToolsSettings::updateSavedBuildBeforeAnalysiIfRequired()
emit buildBeforeAnalysisChanged(m_savedBuildBeforeAnalysis);
}
+QString ClangToolsSettings::savedClazyStandaloneExecutable() const
+{
+ return m_savedClazyStandaloneExecutable;
+}
+
+QString ClangToolsSettings::savedClangTidyExecutable() const
+{
+ return m_savedClangTidyExecutable;
+}
+
+QString ClangToolsSettings::clazyStandaloneExecutable() const
+{
+ return m_clazyStandaloneExecutable;
+}
+
+void ClangToolsSettings::setClazyStandaloneExecutable(const QString &path)
+{
+ m_clazyStandaloneExecutable = path;
+}
+
+QString ClangToolsSettings::clangTidyExecutable() const
+{
+ return m_clangTidyExecutable;
+}
+
+void ClangToolsSettings::setClangTidyExecutable(const QString &path)
+{
+ m_clangTidyExecutable = path;
+}
+
void ClangToolsSettings::readSettings()
{
QSettings *settings = Core::ICore::settings();
@@ -118,6 +150,11 @@ void ClangToolsSettings::readSettings()
m_buildBeforeAnalysis = settings->value(QString(buildBeforeAnalysisKey), true).toBool();
+ m_savedClangTidyExecutable = m_clangTidyExecutable
+ = settings->value(QLatin1String(clangTidyExecutableKey)).toString();
+ m_savedClazyStandaloneExecutable = m_clazyStandaloneExecutable
+ = settings->value(QLatin1String(clazyStandaloneExecutableKey)).toString();
+
m_diagnosticConfigId = Core::Id::fromSetting(settings->value(QString(diagnosticConfigIdKey)));
if (!m_diagnosticConfigId.isValid())
m_diagnosticConfigId = "Builtin.TidyAndClazy";
@@ -135,10 +172,14 @@ void ClangToolsSettings::writeSettings()
settings->beginGroup(QString(Constants::SETTINGS_ID));
settings->setValue(QString(simultaneousProcessesKey), m_simultaneousProcesses);
settings->setValue(QString(buildBeforeAnalysisKey), m_buildBeforeAnalysis);
+ settings->setValue(QString(clangTidyExecutableKey), m_clangTidyExecutable);
+ settings->setValue(QString(clazyStandaloneExecutableKey), m_clazyStandaloneExecutable);
settings->setValue(QString(diagnosticConfigIdKey), m_diagnosticConfigId.toSetting());
m_savedSimultaneousProcesses = m_simultaneousProcesses;
m_savedDiagnosticConfigId = m_diagnosticConfigId;
+ m_savedClangTidyExecutable = m_clangTidyExecutable;
+ m_savedClazyStandaloneExecutable = m_clazyStandaloneExecutable;
updateSavedBuildBeforeAnalysiIfRequired();
settings->endGroup();
diff --git a/src/plugins/clangtools/clangtoolssettings.h b/src/plugins/clangtools/clangtoolssettings.h
index 07f5bc7f47..402845d20f 100644
--- a/src/plugins/clangtools/clangtoolssettings.h
+++ b/src/plugins/clangtools/clangtoolssettings.h
@@ -33,6 +33,7 @@
namespace ClangTools {
namespace Internal {
+// TODO: Remove need for "saved* members
class ClangToolsSettings : public QObject
{
Q_OBJECT
@@ -44,6 +45,8 @@ public:
int savedSimultaneousProcesses() const;
bool savedBuildBeforeAnalysis() const;
Core::Id savedDiagnosticConfigId() const;
+ QString savedClangTidyExecutable() const;
+ QString savedClazyStandaloneExecutable() const;
int simultaneousProcesses() const;
void setSimultaneousProcesses(int processes);
@@ -54,6 +57,12 @@ public:
Core::Id diagnosticConfigId() const;
void setDiagnosticConfigId(Core::Id id);
+ QString clangTidyExecutable() const;
+ void setClangTidyExecutable(const QString &path);
+
+ QString clazyStandaloneExecutable() const;
+ void setClazyStandaloneExecutable(const QString &path);
+
signals:
void buildBeforeAnalysisChanged(bool checked) const;
@@ -67,6 +76,10 @@ private:
int m_savedSimultaneousProcesses = -1;
bool m_buildBeforeAnalysis = false;
bool m_savedBuildBeforeAnalysis= false;
+ QString m_clangTidyExecutable;
+ QString m_savedClangTidyExecutable;
+ QString m_clazyStandaloneExecutable;
+ QString m_savedClazyStandaloneExecutable;
Core::Id m_diagnosticConfigId;
Core::Id m_savedDiagnosticConfigId;
};
diff --git a/src/plugins/clangtools/clangtoolsutils.cpp b/src/plugins/clangtools/clangtoolsutils.cpp
index 173d97e31d..acb87f5ec1 100644
--- a/src/plugins/clangtools/clangtoolsutils.cpp
+++ b/src/plugins/clangtools/clangtoolsutils.cpp
@@ -26,6 +26,7 @@
#include "clangtoolsutils.h"
#include "clangtool.h"
+#include "clangtoolsconstants.h"
#include "clangtoolsdiagnostic.h"
#include "clangtoolssettings.h"
@@ -70,5 +71,88 @@ void showHintAboutBuildBeforeAnalysis()
"ClangToolsDisablingBuildBeforeAnalysisHint");
}
+bool isFileExecutable(const QString &filePath)
+{
+ if (filePath.isEmpty())
+ return false;
+
+ const QFileInfo fileInfo(filePath);
+ return fileInfo.isFile() && fileInfo.isExecutable();
+}
+
+QString shippedClangTidyExecutable()
+{
+ const QString shippedExecutable = Core::ICore::clangTidyExecutable(CLANG_BINDIR);
+ if (isFileExecutable(shippedExecutable))
+ return shippedExecutable;
+ return {};
+}
+
+QString shippedClazyStandaloneExecutable()
+{
+ const QString shippedExecutable = Core::ICore::clazyStandaloneExecutable(CLANG_BINDIR);
+ if (isFileExecutable(shippedExecutable))
+ return shippedExecutable;
+ return {};
+}
+
+static QString fullPath(const QString &executable)
+{
+ const QString hostExeSuffix = QLatin1String(QTC_HOST_EXE_SUFFIX);
+ const Qt::CaseSensitivity caseSensitivity = Utils::HostOsInfo::fileNameCaseSensitivity();
+
+ QString candidate = executable;
+ const bool hasSuffix = candidate.endsWith(hostExeSuffix, caseSensitivity);
+
+ const QFileInfo fileInfo = QFileInfo(candidate);
+ if (fileInfo.isAbsolute()) {
+ if (!hasSuffix)
+ candidate.append(hostExeSuffix);
+ } else {
+ const Utils::Environment environment = Utils::Environment::systemEnvironment();
+ const QString expandedPath = environment.searchInPath(candidate).toString();
+ if (!expandedPath.isEmpty())
+ candidate = expandedPath;
+ }
+
+ return candidate;
+}
+
+static QString findValidExecutable(const QStringList &candidates)
+{
+ for (QString candidate : candidates) {
+ const QString expandedPath = fullPath(candidate);
+ if (isFileExecutable(expandedPath))
+ return expandedPath;
+ }
+
+ return {};
+}
+
+QString clangTidyExecutable()
+{
+ const QString fromSettings = ClangToolsSettings::instance()->clangTidyExecutable();
+ if (!fromSettings.isEmpty())
+ return fullPath(fromSettings);
+
+ return findValidExecutable({
+ shippedClangTidyExecutable(),
+ Constants::CLANG_TIDY_EXECUTABLE_NAME,
+ });
+}
+
+QString clazyStandaloneExecutable()
+{
+ const QString fromSettings = ClangToolsSettings::instance()->clazyStandaloneExecutable();
+ if (!fromSettings.isEmpty())
+ return fullPath(fromSettings);
+
+ return findValidExecutable({
+ shippedClazyStandaloneExecutable(),
+ qEnvironmentVariable("QTC_USE_CLAZY_STANDALONE_PATH"),
+ Constants::CLAZY_STANDALONE_EXECUTABLE_NAME,
+ });
+}
+
} // namespace Internal
} // namespace ClangTools
diff --git a/src/plugins/clangtools/clangtoolsutils.h b/src/plugins/clangtools/clangtoolsutils.h
index 05acb953c5..a7ae9620de 100644
--- a/src/plugins/clangtools/clangtoolsutils.h
+++ b/src/plugins/clangtools/clangtoolsutils.h
@@ -44,5 +44,13 @@ QString createFullLocationString(const Debugger::DiagnosticLocation &location);
QString hintAboutBuildBeforeAnalysis();
void showHintAboutBuildBeforeAnalysis();
+bool isFileExecutable(const QString &filePath);
+
+QString shippedClazyStandaloneExecutable();
+QString clazyStandaloneExecutable();
+
+QString shippedClangTidyExecutable();
+QString clangTidyExecutable();
+
} // namespace Internal
} // namespace ClangTools
diff --git a/src/plugins/clangtools/settingswidget.cpp b/src/plugins/clangtools/settingswidget.cpp
index 08bd297897..5c570a7e97 100644
--- a/src/plugins/clangtools/settingswidget.cpp
+++ b/src/plugins/clangtools/settingswidget.cpp
@@ -28,8 +28,11 @@
#include "ui_basicsettingswidget.h"
#include "ui_settingswidget.h"
+#include "clangtoolsconstants.h"
#include "clangtoolsutils.h"
+#include <coreplugin/icore.h>
+
#include <cpptools/clangdiagnosticconfigswidget.h>
#include <cpptools/cppcodemodelsettings.h>
#include <cpptools/cpptoolsreuse.h>
@@ -37,18 +40,83 @@
#include <QDir>
#include <QThread>
+#include <memory>
+
namespace ClangTools {
namespace Internal {
-SettingsWidget::SettingsWidget(
- ClangToolsSettings *settings,
- QWidget *parent)
+static void setupPathChooser(Utils::PathChooser *const chooser,
+ const QString &promptDiaglogTitle,
+ const QString &placeHolderText,
+ const QString &pathFromSettings,
+ const QString &historyCompleterId,
+ std::function<void(const QString &path)> savePath)
+{
+ chooser->setPromptDialogTitle(promptDiaglogTitle);
+ chooser->lineEdit()->setPlaceholderText(placeHolderText);
+ chooser->setPath(pathFromSettings);
+ chooser->setExpectedKind(Utils::PathChooser::ExistingCommand);
+ chooser->setHistoryCompleter(historyCompleterId);
+ QObject::connect(chooser, &Utils::PathChooser::rawPathChanged, savePath),
+ chooser->setValidationFunction([chooser](Utils::FancyLineEdit *edit, QString *errorMessage) {
+ const QString currentFilePath = chooser->fileName().toString();
+ Utils::PathChooser pc;
+ Utils::PathChooser *helperPathChooser;
+ if (currentFilePath.isEmpty()) {
+ pc.setExpectedKind(chooser->expectedKind());
+ pc.setPath(edit->placeholderText());
+ helperPathChooser = &pc;
+ } else {
+ helperPathChooser = chooser;
+ }
+
+ return chooser->defaultValidationFunction()(helperPathChooser->lineEdit(), errorMessage);
+ });
+}
+
+SettingsWidget::SettingsWidget(ClangToolsSettings *settings, QWidget *parent)
: QWidget(parent)
, m_ui(new Ui::SettingsWidget)
, m_settings(settings)
{
m_ui->setupUi(this);
+ //
+ // Group box "Executables"
+ //
+
+ QString placeHolderText = shippedClangTidyExecutable();
+ QString path = settings->clangTidyExecutable();
+ if (path.isEmpty() && placeHolderText.isEmpty())
+ path = Constants::CLANG_TIDY_EXECUTABLE_NAME;
+ setupPathChooser(m_ui->clangTidyPathChooser,
+ tr("Clang-Tidy Executable"),
+ placeHolderText,
+ path,
+ "ClangTools.ClangTidyExecutable.History",
+ [settings](const QString &path) { settings->setClangTidyExecutable(path); });
+
+ if (qEnvironmentVariable("QTC_USE_CLAZY_STANDALONE_PATH").isEmpty()) {
+ m_ui->clazyStandalonePathChooser->setVisible(false);
+ m_ui->clazyStandaloneLabel->setVisible(false);
+ } else {
+ placeHolderText = shippedClazyStandaloneExecutable();
+ path = settings->clazyStandaloneExecutable();
+ if (path.isEmpty() && placeHolderText.isEmpty())
+ path = Constants::CLAZY_STANDALONE_EXECUTABLE_NAME;
+ setupPathChooser(m_ui->clazyStandalonePathChooser,
+ tr("Clazy Executable"),
+ placeHolderText,
+ path,
+ "ClangTools.ClazyStandaloneExecutable.History",
+ [settings](const QString &path) {
+ settings->setClazyStandaloneExecutable(path);
+ });
+ }
+
+ //
+ // Group box "Run Options"
+ //
m_ui->simultaneousProccessesSpinBox->setValue(settings->savedSimultaneousProcesses());
m_ui->simultaneousProccessesSpinBox->setMinimum(1);
m_ui->simultaneousProccessesSpinBox->setMaximum(QThread::idealThreadCount());
diff --git a/src/plugins/clangtools/settingswidget.ui b/src/plugins/clangtools/settingswidget.ui
index b6b990aec8..e34079df35 100644
--- a/src/plugins/clangtools/settingswidget.ui
+++ b/src/plugins/clangtools/settingswidget.ui
@@ -15,9 +15,38 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="title">
+ <string>Executables</string>
+ </property>
+ <layout class="QFormLayout" name="formLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Clang-Tidy:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="Utils::PathChooser" name="clangTidyPathChooser" native="true"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="clazyStandaloneLabel">
+ <property name="text">
+ <string>Clazy-Standalone:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="Utils::PathChooser" name="clazyStandalonePathChooser" native="true"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
- <string>General</string>
+ <string>Run Options</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
@@ -81,6 +110,12 @@
<extends>QWidget</extends>
<header>clangtools/basicsettingswidget.h</header>
</customwidget>
+ <customwidget>
+ <class>Utils::PathChooser</class>
+ <extends>QWidget</extends>
+ <header location="global">utils/pathchooser.h</header>
+ <container>1</container>
+ </customwidget>
</customwidgets>
<resources/>
<connections/>