CppEditor: Do not use clangd < 13

We will shortly need to use a command-line option that is new in clangd
13. Rather than starting to add checks for versions that won't work as
expected anyway, we simply refuse to use clangd < 13 now.

Change-Id: I42ec679e0f58449a2593cf92b4be7ed3101fa787
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io>
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
Christian Kandeler
2021-11-01 12:06:38 +01:00
parent a2cb1edb69
commit 4dfdbf91f6
3 changed files with 47 additions and 20 deletions

View File

@@ -34,6 +34,7 @@
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
#include <QSettings> #include <QSettings>
@@ -312,6 +313,11 @@ ClangdSettings &ClangdSettings::instance()
return settings; return settings;
} }
bool ClangdSettings::useClangd() const
{
return m_data.useClangd && clangdVersion(clangdFilePath()) >= QVersionNumber(13);
}
void ClangdSettings::setDefaultClangdPath(const FilePath &filePath) void ClangdSettings::setDefaultClangdPath(const FilePath &filePath)
{ {
g_defaultClangdFilePath = filePath; g_defaultClangdFilePath = filePath;
@@ -333,6 +339,37 @@ void ClangdSettings::setData(const Data &data)
} }
} }
static QVersionNumber getClangdVersion(const FilePath &clangdFilePath)
{
Utils::QtcProcess clangdProc;
clangdProc.setCommand({clangdFilePath, {"--version"}});
clangdProc.start();
if (!clangdProc.waitForStarted() || !clangdProc.waitForFinished())
return{};
const QString output = clangdProc.allOutput();
static const QString versionPrefix = "clangd version ";
const int prefixOffset = output.indexOf(versionPrefix);
if (prefixOffset == -1)
return {};
return QVersionNumber::fromString(output.mid(prefixOffset + versionPrefix.length()));
}
QVersionNumber ClangdSettings::clangdVersion(const FilePath &clangdFilePath)
{
const QDateTime timeStamp = clangdFilePath.lastModified();
const auto it = m_versionCache.find(clangdFilePath);
if (it == m_versionCache.end()) {
const QVersionNumber version = getClangdVersion(clangdFilePath);
m_versionCache.insert(clangdFilePath, qMakePair(timeStamp, version));
return version;
}
if (it->first != timeStamp) {
it->first = timeStamp;
it->second = getClangdVersion(clangdFilePath);
}
return it->second;
}
void ClangdSettings::loadSettings() void ClangdSettings::loadSettings()
{ {
m_data.fromMap(Core::ICore::settings()->value(clangdSettingsKey()).toMap()); m_data.fromMap(Core::ICore::settings()->value(clangdSettingsKey()).toMap());

View File

@@ -29,8 +29,12 @@
#include <utils/fileutils.h> #include <utils/fileutils.h>
#include <QDateTime>
#include <QHash>
#include <QObject> #include <QObject>
#include <QPair>
#include <QStringList> #include <QStringList>
#include <QVersionNumber>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QSettings; class QSettings;
@@ -117,7 +121,7 @@ public:
ClangdSettings(const Data &data) : m_data(data) {} ClangdSettings(const Data &data) : m_data(data) {}
static ClangdSettings &instance(); static ClangdSettings &instance();
bool useClangd() const { return m_data.useClangd; } bool useClangd() const;
static void setDefaultClangdPath(const Utils::FilePath &filePath); static void setDefaultClangdPath(const Utils::FilePath &filePath);
Utils::FilePath clangdFilePath() const; Utils::FilePath clangdFilePath() const;
@@ -129,6 +133,8 @@ public:
void setData(const Data &data); void setData(const Data &data);
Data data() const { return m_data; } Data data() const { return m_data; }
static QVersionNumber clangdVersion(const Utils::FilePath &clangdFilePath);
#ifdef WITH_TESTS #ifdef WITH_TESTS
static void setUseClangd(bool use); static void setUseClangd(bool use);
static void setClangdFilePath(const Utils::FilePath &filePath); static void setClangdFilePath(const Utils::FilePath &filePath);
@@ -144,6 +150,7 @@ private:
void saveSettings(); void saveSettings();
Data m_data; Data m_data;
static inline QHash<Utils::FilePath, QPair<QDateTime, QVersionNumber>> m_versionCache;
}; };
inline bool operator==(const ClangdSettings::Data &s1, const ClangdSettings::Data &s2) inline bool operator==(const ClangdSettings::Data &s1, const ClangdSettings::Data &s2)

View File

@@ -35,7 +35,6 @@
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/infolabel.h> #include <utils/infolabel.h>
#include <utils/pathchooser.h> #include <utils/pathchooser.h>
#include <utils/qtcprocess.h>
#include <QFormLayout> #include <QFormLayout>
#include <QSpinBox> #include <QSpinBox>
@@ -285,30 +284,14 @@ ClangdSettingsWidget::ClangdSettingsWidget(const ClangdSettings::Data &settingsD
if (!d->clangdChooser.isValid()) if (!d->clangdChooser.isValid())
return; return;
const Utils::FilePath clangdPath = d->clangdChooser.filePath(); const Utils::FilePath clangdPath = d->clangdChooser.filePath();
Utils::QtcProcess clangdProc; const QVersionNumber clangdVersion = ClangdSettings::clangdVersion(clangdPath);
clangdProc.setCommand({clangdPath, {"--version"}});
clangdProc.start();
if (!clangdProc.waitForStarted() || !clangdProc.waitForFinished()) {
labelSetter.setWarning(tr("Failed to retrieve clangd version: %1")
.arg(clangdProc.exitMessage()));
return;
}
const QString output = clangdProc.allOutput();
static const QString versionPrefix = "clangd version ";
const int prefixOffset = output.indexOf(versionPrefix);
QVersionNumber clangdVersion;
if (prefixOffset != -1) {
clangdVersion = QVersionNumber::fromString(output.mid(prefixOffset
+ versionPrefix.length()));
}
if (clangdVersion.isNull()) { if (clangdVersion.isNull()) {
labelSetter.setWarning(tr("Failed to retrieve clangd version: " labelSetter.setWarning(tr("Failed to retrieve clangd version: "
"Unexpected clangd output.")); "Unexpected clangd output."));
return; return;
} }
if (clangdVersion < QVersionNumber(13)) { if (clangdVersion < QVersionNumber(13)) {
labelSetter.setWarning(tr("The clangd version is %1, but %2 or greater is " labelSetter.setWarning(tr("The clangd version is %1, but %2 or greater is required.")
"recommended for full functionality.")
.arg(clangdVersion.toString()).arg(13)); .arg(clangdVersion.toString()).arg(13));
return; return;
} }