diff --git a/src/libs/utils/hostosinfo.cpp b/src/libs/utils/hostosinfo.cpp index 657bf08470a..79f042e0f05 100644 --- a/src/libs/utils/hostosinfo.cpp +++ b/src/libs/utils/hostosinfo.cpp @@ -31,6 +31,10 @@ #include #endif +#ifdef Q_OS_LINUX +#include +#endif + #ifdef Q_OS_WIN #include #endif @@ -111,3 +115,27 @@ bool HostOsInfo::canCreateOpenGLContext(QString *errorMessage) return canCreate; #endif } + +optional HostOsInfo::totalMemoryInstalledInBytes() +{ +#ifdef Q_OS_LINUX + struct sysinfo info; + if (sysinfo(&info) == -1) + return {}; + return info.totalram; +#elif defined(Q_OS_WIN) + MEMORYSTATUSEX statex; + statex.dwLength = sizeof statex; + if (!GlobalMemoryStatusEx(&statex)) + return {}; + return statex.ullTotalPhys; +#elif defined(Q_OS_MACOS) + int mib[] = {CTL_HW, HW_MEMSIZE}; + int64_t ram; + size_t length = sizeof(int64_t); + if (sysctl(mib, 2, &ram, &length, nullptr, 0) == -1) + return {}; + return ram; +#endif + return {}; +} diff --git a/src/libs/utils/hostosinfo.h b/src/libs/utils/hostosinfo.h index 9fa6689d4b6..9823c7e6f23 100644 --- a/src/libs/utils/hostosinfo.h +++ b/src/libs/utils/hostosinfo.h @@ -27,6 +27,7 @@ #include "utils_global.h" +#include "optional.h" #include "osspecificaspects.h" QT_BEGIN_NAMESPACE @@ -104,6 +105,8 @@ public: static bool canCreateOpenGLContext(QString *errorMessage); + static optional totalMemoryInstalledInBytes(); + private: static Qt::CaseSensitivity m_overrideFileNameCaseSensitivity; static bool m_useOverrideFileNameCaseSensitivity; diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp index a33d2863563..1437aff83f6 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp @@ -62,10 +62,12 @@ #include #include +#include #include #include #include +#include #include #include #include @@ -124,6 +126,40 @@ static Client *clientForGeneratedFile(const Utils::FilePath &filePath) return nullptr; } +static void checkSystemForClangdSuitability() +{ + if (ClangdSettings::haveCheckedHardwareRequirements()) + return; + if (ClangdSettings::hardwareFulfillsRequirements()) + return; + + ClangdSettings::setUseClangd(false); + const QString warnStr = ClangModelManagerSupport::tr("The use of clangd for the C/C++ " + "code model was disabled, because it is likely that its memory requirements " + "would be higher than what your system can handle."); + const Utils::Id clangdWarningSetting("WarnAboutClangd"); + Utils::InfoBarEntry info(clangdWarningSetting, warnStr); + info.setDetailsWidgetCreator([] { + const auto label = new QLabel(ClangModelManagerSupport::tr( + "With clangd enabled, Qt Creator fully supports modern C++ " + "when highlighting code, completing symbols and so on.
" + "This comes at a higher cost in terms of CPU load and memory usage compared " + "to the built-in code model, which therefore might be the better choice " + "on older machines and/or with legacy code.
" + "You can enable/disable and fine-tune clangd here.")); + label->setWordWrap(true); + QObject::connect(label, &QLabel::linkActivated, [] { + Core::ICore::showOptionsDialog(CppEditor::Constants::CPP_CLANGD_SETTINGS_ID); + }); + return label; + }); + info.addCustomButton(ClangModelManagerSupport::tr("Enable Anyway"), [clangdWarningSetting] { + ClangdSettings::setUseClangd(true); + Core::ICore::infoBar()->removeInfo(clangdWarningSetting); + }); + Core::ICore::infoBar()->addInfo(info); +} + ClangModelManagerSupport::ClangModelManagerSupport() { QTC_CHECK(!m_instance); @@ -132,6 +168,7 @@ ClangModelManagerSupport::ClangModelManagerSupport() watchForExternalChanges(); watchForInternalChanges(); setupClangdConfigFile(); + checkSystemForClangdSuitability(); cppModelManager()->setCurrentDocumentFilter(std::make_unique()); cppModelManager()->setLocatorFilter(std::make_unique()); cppModelManager()->setClassesFilter(std::make_unique()); diff --git a/src/plugins/cppeditor/cppcodemodelsettings.cpp b/src/plugins/cppeditor/cppcodemodelsettings.cpp index 0c59d923c25..69f61e2e549 100644 --- a/src/plugins/cppeditor/cppcodemodelsettings.cpp +++ b/src/plugins/cppeditor/cppcodemodelsettings.cpp @@ -34,6 +34,7 @@ #include #include +#include #include #include #include @@ -81,6 +82,7 @@ static QString clangdSizeThresholdKey() { return QLatin1String("ClangdSizeThresh static QString clangdUseGlobalSettingsKey() { return QLatin1String("useGlobalSettings"); } static QString sessionsWithOneClangdKey() { return QLatin1String("SessionsWithOneClangd"); } static QString diagnosticConfigIdKey() { return QLatin1String("diagnosticConfigId"); } +static QString checkedHardwareKey() { return QLatin1String("checkedHardware"); } static FilePath g_defaultClangdFilePath; static FilePath fallbackClangdFilePath() @@ -206,6 +208,22 @@ bool ClangdSettings::useClangd() const return m_data.useClangd && clangdVersion() >= QVersionNumber(14); } +void ClangdSettings::setUseClangd(bool use) { instance().m_data.useClangd = use; } + +bool ClangdSettings::hardwareFulfillsRequirements() +{ + instance().m_data.haveCheckedHardwareReqirements = true; + instance().saveSettings(); + const quint64 minRam = quint64(12) * 1024 * 1024 * 1024; + const Utils::optional totalRam = Utils::HostOsInfo::totalMemoryInstalledInBytes(); + return !totalRam || *totalRam >= minRam; +} + +bool ClangdSettings::haveCheckedHardwareRequirements() +{ + return instance().data().haveCheckedHardwareReqirements; +} + void ClangdSettings::setDefaultClangdPath(const FilePath &filePath) { g_defaultClangdFilePath = filePath; @@ -350,8 +368,6 @@ void ClangdSettings::saveSettings() } #ifdef WITH_TESTS -void ClangdSettings::setUseClangd(bool use) { instance().m_data.useClangd = use; } - void ClangdSettings::setClangdFilePath(const FilePath &filePath) { instance().m_data.executableFilePath = filePath; @@ -435,6 +451,7 @@ QVariantMap ClangdSettings::Data::toMap() const map.insert(clangdSizeThresholdKey(), sizeThresholdInKb); map.insert(sessionsWithOneClangdKey(), sessionsWithOneClangd); map.insert(diagnosticConfigIdKey(), diagnosticConfigId.toSetting()); + map.insert(checkedHardwareKey(), true); return map; } @@ -451,6 +468,7 @@ void ClangdSettings::Data::fromMap(const QVariantMap &map) sessionsWithOneClangd = map.value(sessionsWithOneClangdKey()).toStringList(); diagnosticConfigId = Id::fromSetting(map.value(diagnosticConfigIdKey(), initialClangDiagnosticConfigId().toSetting())); + haveCheckedHardwareReqirements = map.value(checkedHardwareKey(), false).toBool(); } } // namespace CppEditor diff --git a/src/plugins/cppeditor/cppcodemodelsettings.h b/src/plugins/cppeditor/cppcodemodelsettings.h index 1bf5b46616a..8cf0bac463c 100644 --- a/src/plugins/cppeditor/cppcodemodelsettings.h +++ b/src/plugins/cppeditor/cppcodemodelsettings.h @@ -111,7 +111,8 @@ public: && s1.autoIncludeHeaders == s2.autoIncludeHeaders && s1.documentUpdateThreshold == s2.documentUpdateThreshold && s1.sizeThresholdEnabled == s2.sizeThresholdEnabled - && s1.sizeThresholdInKb == s2.sizeThresholdInKb; + && s1.sizeThresholdInKb == s2.sizeThresholdInKb + && s1.haveCheckedHardwareReqirements == s2.haveCheckedHardwareReqirements; } friend bool operator!=(const Data &s1, const Data &s2) { return !(s1 == s2); } @@ -126,12 +127,17 @@ public: bool enableIndexing = true; bool autoIncludeHeaders = false; bool sizeThresholdEnabled = false; + bool haveCheckedHardwareReqirements = false; }; ClangdSettings(const Data &data) : m_data(data) {} static ClangdSettings &instance(); bool useClangd() const; + static void setUseClangd(bool use); + + static bool hardwareFulfillsRequirements(); + static bool haveCheckedHardwareRequirements(); static void setDefaultClangdPath(const Utils::FilePath &filePath); static void setCustomDiagnosticConfigs(const ClangDiagnosticConfigs &configs); @@ -159,7 +165,6 @@ public: static Utils::FilePath clangdUserConfigFilePath(); #ifdef WITH_TESTS - static void setUseClangd(bool use); static void setClangdFilePath(const Utils::FilePath &filePath); #endif