diff options
Diffstat (limited to 'src/plugins/clangtools')
-rw-r--r-- | src/plugins/clangtools/clangtidyclazyrunner.cpp | 5 | ||||
-rw-r--r-- | src/plugins/clangtools/clangtoolruncontrol.cpp | 14 | ||||
-rw-r--r-- | src/plugins/clangtools/clangtoolrunner.h | 1 | ||||
-rw-r--r-- | src/plugins/clangtools/clangtoolsconstants.h | 3 | ||||
-rw-r--r-- | src/plugins/clangtools/clangtoolssettings.cpp | 41 | ||||
-rw-r--r-- | src/plugins/clangtools/clangtoolssettings.h | 13 | ||||
-rw-r--r-- | src/plugins/clangtools/clangtoolsutils.cpp | 84 | ||||
-rw-r--r-- | src/plugins/clangtools/clangtoolsutils.h | 8 | ||||
-rw-r--r-- | src/plugins/clangtools/settingswidget.cpp | 74 | ||||
-rw-r--r-- | src/plugins/clangtools/settingswidget.ui | 37 |
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/> |