diff options
author | Christian Kandeler <christian.kandeler@qt.io> | 2024-03-15 16:02:50 +0100 |
---|---|---|
committer | Christian Kandeler <christian.kandeler@qt.io> | 2024-03-28 19:06:08 +0000 |
commit | 3ca0deef536d33163256fee9a50895f1ee5e4a75 (patch) | |
tree | 0a24461264862ae66ac3c07ef39ee40bc05d541c /src/plugins/cppeditor | |
parent | fc8f1bc47df91e829c569cb5977677b835b86f88 (diff) |
CppEditor: Move ClangdSettings into a dedicated set of files
They were originally put alongside the CppCodeModelSettings for
simplicity, but there is no coupling (anymore?) between these two
classes.
Change-Id: Ic24df109b74a5b5c39de073c938c6de12f4aa319
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: David Schulz <david.schulz@qt.io>
Diffstat (limited to 'src/plugins/cppeditor')
-rw-r--r-- | src/plugins/cppeditor/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/plugins/cppeditor/clangdsettings.cpp | 491 | ||||
-rw-r--r-- | src/plugins/cppeditor/clangdsettings.h | 162 | ||||
-rw-r--r-- | src/plugins/cppeditor/cppcodemodelsettings.cpp | 470 | ||||
-rw-r--r-- | src/plugins/cppeditor/cppcodemodelsettings.h | 150 | ||||
-rw-r--r-- | src/plugins/cppeditor/cppcodemodelsettingspage.cpp | 2 | ||||
-rw-r--r-- | src/plugins/cppeditor/cppeditor.qbs | 2 | ||||
-rw-r--r-- | src/plugins/cppeditor/cpptoolsreuse.cpp | 1 | ||||
-rw-r--r-- | src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp | 1 |
9 files changed, 660 insertions, 620 deletions
diff --git a/src/plugins/cppeditor/CMakeLists.txt b/src/plugins/cppeditor/CMakeLists.txt index ec5ad89cea..93c37beaca 100644 --- a/src/plugins/cppeditor/CMakeLists.txt +++ b/src/plugins/cppeditor/CMakeLists.txt @@ -93,6 +93,7 @@ add_qtc_plugin(CppEditor cppvirtualfunctionassistprovider.cpp cppvirtualfunctionassistprovider.h cppvirtualfunctionproposalitem.cpp cppvirtualfunctionproposalitem.h cppworkingcopy.cpp cppworkingcopy.h + clangdsettings.cpp clangdsettings.h cursorineditor.h doxygengenerator.cpp doxygengenerator.h editordocumenthandle.cpp editordocumenthandle.h diff --git a/src/plugins/cppeditor/clangdsettings.cpp b/src/plugins/cppeditor/clangdsettings.cpp new file mode 100644 index 0000000000..b5352af6d8 --- /dev/null +++ b/src/plugins/cppeditor/clangdsettings.cpp @@ -0,0 +1,491 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include "clangdsettings.h" + +#include "clangdiagnosticconfigsmodel.h" +#include "cppeditorconstants.h" +#include "cppeditortr.h" +#include "cpptoolsreuse.h" + +#include <coreplugin/icore.h> +#include <coreplugin/session.h> +#include <projectexplorer/project.h> +#include <utils/clangutils.h> +#include <utils/qtcprocess.h> + +#include <QStandardPaths> +#include <QVersionNumber> + +using namespace Utils; + +namespace CppEditor { + +static FilePath g_defaultClangdFilePath; +static FilePath fallbackClangdFilePath() +{ + if (g_defaultClangdFilePath.exists()) + return g_defaultClangdFilePath; + return Environment::systemEnvironment().searchInPath("clangd"); +} + +static Id initialClangDiagnosticConfigId() { return Constants::CPP_CLANG_DIAG_CONFIG_BUILDSYSTEM; } + +static Key clangdSettingsKey() { return "ClangdSettings"; } +static Key useClangdKey() { return "UseClangdV7"; } +static Key clangdPathKey() { return "ClangdPath"; } +static Key clangdIndexingKey() { return "ClangdIndexing"; } +static Key clangdProjectIndexPathKey() { return "ClangdProjectIndexPath"; } +static Key clangdSessionIndexPathKey() { return "ClangdSessionIndexPath"; } +static Key clangdIndexingPriorityKey() { return "ClangdIndexingPriority"; } +static Key clangdHeaderSourceSwitchModeKey() { return "ClangdHeaderSourceSwitchMode"; } +static Key clangdCompletionRankingModelKey() { return "ClangdCompletionRankingModel"; } +static Key clangdHeaderInsertionKey() { return "ClangdHeaderInsertion"; } +static Key clangdThreadLimitKey() { return "ClangdThreadLimit"; } +static Key clangdDocumentThresholdKey() { return "ClangdDocumentThreshold"; } +static Key clangdSizeThresholdEnabledKey() { return "ClangdSizeThresholdEnabled"; } +static Key clangdSizeThresholdKey() { return "ClangdSizeThreshold"; } +static Key useGlobalSettingsKey() { return "useGlobalSettings"; } +static Key clangdblockIndexingSettingsKey() { return "blockIndexing"; } +static Key sessionsWithOneClangdKey() { return "SessionsWithOneClangd"; } +static Key diagnosticConfigIdKey() { return "diagnosticConfigId"; } +static Key checkedHardwareKey() { return "checkedHardware"; } +static Key completionResultsKey() { return "completionResults"; } + +QString ClangdSettings::priorityToString(const IndexingPriority &priority) +{ + switch (priority) { + case IndexingPriority::Background: return "background"; + case IndexingPriority::Normal: return "normal"; + case IndexingPriority::Low: return "low"; + case IndexingPriority::Off: return {}; + } + return {}; +} + +QString ClangdSettings::priorityToDisplayString(const IndexingPriority &priority) +{ + switch (priority) { + case IndexingPriority::Background: return Tr::tr("Background Priority"); + case IndexingPriority::Normal: return Tr::tr("Normal Priority"); + case IndexingPriority::Low: return Tr::tr("Low Priority"); + case IndexingPriority::Off: return Tr::tr("Off"); + } + return {}; +} + +QString ClangdSettings::headerSourceSwitchModeToDisplayString(HeaderSourceSwitchMode mode) +{ + switch (mode) { + case HeaderSourceSwitchMode::BuiltinOnly: return Tr::tr("Use Built-in Only"); + case HeaderSourceSwitchMode::ClangdOnly: return Tr::tr("Use Clangd Only"); + case HeaderSourceSwitchMode::Both: return Tr::tr("Try Both"); + } + return {}; +} + +QString ClangdSettings::rankingModelToCmdLineString(CompletionRankingModel model) +{ + switch (model) { + case CompletionRankingModel::Default: break; + case CompletionRankingModel::DecisionForest: return "decision_forest"; + case CompletionRankingModel::Heuristics: return "heuristics"; + } + QTC_ASSERT(false, return {}); +} + +QString ClangdSettings::rankingModelToDisplayString(CompletionRankingModel model) +{ + switch (model) { + case CompletionRankingModel::Default: return Tr::tr("Default"); + case CompletionRankingModel::DecisionForest: return Tr::tr("Decision Forest"); + case CompletionRankingModel::Heuristics: return Tr::tr("Heuristics"); + } + QTC_ASSERT(false, return {}); +} + +QString ClangdSettings::defaultProjectIndexPathTemplate() +{ + return QDir::toNativeSeparators("%{BuildConfig:BuildDirectory:FilePath}/.qtc_clangd"); +} + +QString ClangdSettings::defaultSessionIndexPathTemplate() +{ + return QDir::toNativeSeparators("%{IDE:UserResourcePath}/.qtc_clangd/%{Session:FileBaseName}"); +} + +ClangdSettings &ClangdSettings::instance() +{ + static ClangdSettings settings; + return settings; +} + +ClangdSettings::ClangdSettings() +{ + loadSettings(); + const auto sessionMgr = Core::SessionManager::instance(); + connect(sessionMgr, &Core::SessionManager::sessionRemoved, this, [this](const QString &name) { + m_data.sessionsWithOneClangd.removeOne(name); + }); + connect(sessionMgr, + &Core::SessionManager::sessionRenamed, + this, + [this](const QString &oldName, const QString &newName) { + const auto index = m_data.sessionsWithOneClangd.indexOf(oldName); + if (index != -1) + m_data.sessionsWithOneClangd[index] = newName; + }); +} + +bool ClangdSettings::useClangd() const +{ + return m_data.useClangd && clangdVersion(clangdFilePath()) >= minimumClangdVersion(); +} + +void ClangdSettings::setUseClangd(bool use) { instance().m_data.useClangd = use; } + +void ClangdSettings::setUseClangdAndSave(bool use) +{ + setUseClangd(use); + instance().saveSettings(); +} + +bool ClangdSettings::hardwareFulfillsRequirements() +{ + instance().m_data.haveCheckedHardwareReqirements = true; + instance().saveSettings(); + const quint64 minRam = quint64(12) * 1024 * 1024 * 1024; + const std::optional<quint64> totalRam = Utils::HostOsInfo::totalMemoryInstalledInBytes(); + return !totalRam || *totalRam >= minRam; +} + +bool ClangdSettings::haveCheckedHardwareRequirements() +{ + return instance().data().haveCheckedHardwareReqirements; +} + +void ClangdSettings::setDefaultClangdPath(const FilePath &filePath) +{ + g_defaultClangdFilePath = filePath; +} + +void ClangdSettings::setCustomDiagnosticConfigs(const ClangDiagnosticConfigs &configs) +{ + if (instance().customDiagnosticConfigs() == configs) + return; + instance().m_data.customDiagnosticConfigs = configs; + instance().saveSettings(); +} + +FilePath ClangdSettings::clangdFilePath() const +{ + if (!m_data.executableFilePath.isEmpty()) + return m_data.executableFilePath; + return fallbackClangdFilePath(); +} + +FilePath ClangdSettings::projectIndexPath(const Utils::MacroExpander &expander) const +{ + return FilePath::fromUserInput(expander.expand(m_data.projectIndexPathTemplate)); +} + +FilePath ClangdSettings::sessionIndexPath(const Utils::MacroExpander &expander) const +{ + return FilePath::fromUserInput(expander.expand(m_data.sessionIndexPathTemplate)); +} + +bool ClangdSettings::sizeIsOkay(const Utils::FilePath &fp) const +{ + return !sizeThresholdEnabled() || sizeThresholdInKb() * 1024 >= fp.fileSize(); +} + +ClangDiagnosticConfigs ClangdSettings::customDiagnosticConfigs() const +{ + return m_data.customDiagnosticConfigs; +} + +Id ClangdSettings::diagnosticConfigId() const +{ + if (!diagnosticConfigsModel().hasConfigWithId(m_data.diagnosticConfigId)) + return initialClangDiagnosticConfigId(); + return m_data.diagnosticConfigId; +} + +ClangDiagnosticConfig ClangdSettings::diagnosticConfig() const +{ + return diagnosticConfigsModel(customDiagnosticConfigs()).configWithId(diagnosticConfigId()); +} + +ClangdSettings::Granularity ClangdSettings::granularity() const +{ + if (m_data.sessionsWithOneClangd.contains(Core::SessionManager::activeSession())) + return Granularity::Session; + return Granularity::Project; +} + +void ClangdSettings::setData(const Data &data) +{ + if (this == &instance() && data != m_data) { + m_data = data; + saveSettings(); + emit changed(); + } +} + +static FilePath getClangHeadersPathFromClang(const FilePath &clangdFilePath) +{ + const FilePath clangFilePath = clangdFilePath.absolutePath().pathAppended("clang") + .withExecutableSuffix(); + if (!clangFilePath.exists()) + return {}; + Process clang; + clang.setCommand({clangFilePath, {"-print-resource-dir"}}); + clang.start(); + if (!clang.waitForFinished()) + return {}; + const FilePath resourceDir = FilePath::fromUserInput(QString::fromLocal8Bit( + clang.rawStdOut().trimmed())); + if (resourceDir.isEmpty() || !resourceDir.exists()) + return {}; + const FilePath includeDir = resourceDir.pathAppended("include"); + if (!includeDir.exists()) + return {}; + return includeDir; +} + +static FilePath getClangHeadersPath(const FilePath &clangdFilePath) +{ + const FilePath headersPath = getClangHeadersPathFromClang(clangdFilePath); + if (!headersPath.isEmpty()) + return headersPath; + + const QVersionNumber version = Utils::clangdVersion(clangdFilePath); + QTC_ASSERT(!version.isNull(), return {}); + static const QStringList libDirs{"lib", "lib64"}; + const QStringList versionStrings{QString::number(version.majorVersion()), version.toString()}; + for (const QString &libDir : libDirs) { + for (const QString &versionString : versionStrings) { + const FilePath includePath = clangdFilePath.absolutePath().parentDir() + .pathAppended(libDir).pathAppended("clang") + .pathAppended(versionString).pathAppended("include"); + if (includePath.exists()) + return includePath; + } + } + QTC_CHECK(false); + return {}; +} + +FilePath ClangdSettings::clangdIncludePath() const +{ + QTC_ASSERT(useClangd(), return {}); + FilePath clangdPath = clangdFilePath(); + QTC_ASSERT(!clangdPath.isEmpty() && clangdPath.exists(), return {}); + static QHash<FilePath, FilePath> headersPathCache; + const auto it = headersPathCache.constFind(clangdPath); + if (it != headersPathCache.constEnd()) + return *it; + const FilePath headersPath = getClangHeadersPath(clangdPath); + if (!headersPath.isEmpty()) + headersPathCache.insert(clangdPath, headersPath); + return headersPath; +} + +FilePath ClangdSettings::clangdUserConfigFilePath() +{ + return FilePath::fromString( + QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation)) + / "clangd/config.yaml"; +} + +void ClangdSettings::loadSettings() +{ + const auto settings = Core::ICore::settings(); + + m_data.fromMap(Utils::storeFromSettings(clangdSettingsKey(), settings)); + + settings->beginGroup(Constants::CPPEDITOR_SETTINGSGROUP); + m_data.customDiagnosticConfigs = diagnosticConfigsFromSettings(settings); + + // Pre-8.0 compat + static const Key oldKey("ClangDiagnosticConfig"); + const QVariant configId = settings->value(oldKey); + if (configId.isValid()) { + m_data.diagnosticConfigId = Id::fromSetting(configId); + settings->setValue(oldKey, {}); + } + + settings->endGroup(); +} + +void ClangdSettings::saveSettings() +{ + const auto settings = Core::ICore::settings(); + const ClangdSettings::Data defaultData; + Utils::storeToSettingsWithDefault(clangdSettingsKey(), + settings, + m_data.toMap(), + defaultData.toMap()); + settings->beginGroup(Constants::CPPEDITOR_SETTINGSGROUP); + diagnosticConfigsToSettings(settings, m_data.customDiagnosticConfigs); + settings->endGroup(); +} + +#ifdef WITH_TESTS +void ClangdSettings::setClangdFilePath(const FilePath &filePath) +{ + instance().m_data.executableFilePath = filePath; +} +#endif + +ClangdProjectSettings::ClangdProjectSettings(ProjectExplorer::Project *project) : m_project(project) +{ + loadSettings(); +} + +ClangdSettings::Data ClangdProjectSettings::settings() const +{ + const ClangdSettings::Data globalData = ClangdSettings::instance().data(); + ClangdSettings::Data data = globalData; + if (!m_useGlobalSettings) { + data = m_customSettings; + // This property is global by definition. + data.sessionsWithOneClangd = ClangdSettings::instance().data().sessionsWithOneClangd; + + // This list exists only once. + data.customDiagnosticConfigs = ClangdSettings::instance().data().customDiagnosticConfigs; + } + if (m_blockIndexing) + data.indexingPriority = ClangdSettings::IndexingPriority::Off; + return data; +} + +void ClangdProjectSettings::setSettings(const ClangdSettings::Data &data) +{ + m_customSettings = data; + saveSettings(); + ClangdSettings::setCustomDiagnosticConfigs(data.customDiagnosticConfigs); + emit ClangdSettings::instance().changed(); +} + +void ClangdProjectSettings::setUseGlobalSettings(bool useGlobal) +{ + m_useGlobalSettings = useGlobal; + saveSettings(); + emit ClangdSettings::instance().changed(); +} + +void ClangdProjectSettings::setDiagnosticConfigId(Utils::Id configId) +{ + m_customSettings.diagnosticConfigId = configId; + saveSettings(); + emit ClangdSettings::instance().changed(); +} + +void ClangdProjectSettings::blockIndexing() +{ + if (m_blockIndexing) + return; + m_blockIndexing = true; + saveSettings(); + emit ClangdSettings::instance().changed(); +} + +void ClangdProjectSettings::unblockIndexing() +{ + if (!m_blockIndexing) + return; + m_blockIndexing = false; + saveSettings(); + // Do not emit changed here since that would restart clients with blocked indexing +} + +void ClangdProjectSettings::loadSettings() +{ + if (!m_project) + return; + const Store data = storeFromVariant(m_project->namedSettings(clangdSettingsKey())); + m_useGlobalSettings = data.value(useGlobalSettingsKey(), true).toBool(); + m_blockIndexing = data.value(clangdblockIndexingSettingsKey(), false).toBool(); + if (!m_useGlobalSettings) + m_customSettings.fromMap(data); +} + +void ClangdProjectSettings::saveSettings() +{ + if (!m_project) + return; + Store data; + if (!m_useGlobalSettings) + data = m_customSettings.toMap(); + data.insert(useGlobalSettingsKey(), m_useGlobalSettings); + data.insert(clangdblockIndexingSettingsKey(), m_blockIndexing); + m_project->setNamedSettings(clangdSettingsKey(), variantFromStore(data)); +} + +Store ClangdSettings::Data::toMap() const +{ + Store map; + + map.insert(useClangdKey(), useClangd); + + map.insert(clangdPathKey(), + executableFilePath != fallbackClangdFilePath() ? executableFilePath.toString() + : QString()); + + map.insert(clangdIndexingKey(), indexingPriority != IndexingPriority::Off); + map.insert(clangdIndexingPriorityKey(), int(indexingPriority)); + map.insert(clangdProjectIndexPathKey(), projectIndexPathTemplate); + map.insert(clangdSessionIndexPathKey(), sessionIndexPathTemplate); + map.insert(clangdHeaderSourceSwitchModeKey(), int(headerSourceSwitchMode)); + map.insert(clangdCompletionRankingModelKey(), int(completionRankingModel)); + map.insert(clangdHeaderInsertionKey(), autoIncludeHeaders); + map.insert(clangdThreadLimitKey(), workerThreadLimit); + map.insert(clangdDocumentThresholdKey(), documentUpdateThreshold); + map.insert(clangdSizeThresholdEnabledKey(), sizeThresholdEnabled); + map.insert(clangdSizeThresholdKey(), sizeThresholdInKb); + map.insert(sessionsWithOneClangdKey(), sessionsWithOneClangd); + map.insert(diagnosticConfigIdKey(), diagnosticConfigId.toSetting()); + map.insert(checkedHardwareKey(), haveCheckedHardwareReqirements); + map.insert(completionResultsKey(), completionResults); + return map; +} + +void ClangdSettings::Data::fromMap(const Store &map) +{ + useClangd = map.value(useClangdKey(), true).toBool(); + executableFilePath = FilePath::fromString(map.value(clangdPathKey()).toString()); + indexingPriority = IndexingPriority( + map.value(clangdIndexingPriorityKey(), int(this->indexingPriority)).toInt()); + const auto it = map.find(clangdIndexingKey()); + if (it != map.end() && !it->toBool()) + indexingPriority = IndexingPriority::Off; + projectIndexPathTemplate + = map.value(clangdProjectIndexPathKey(), defaultProjectIndexPathTemplate()).toString(); + sessionIndexPathTemplate + = map.value(clangdSessionIndexPathKey(), defaultSessionIndexPathTemplate()).toString(); + headerSourceSwitchMode = HeaderSourceSwitchMode(map.value(clangdHeaderSourceSwitchModeKey(), + int(headerSourceSwitchMode)).toInt()); + completionRankingModel = CompletionRankingModel(map.value(clangdCompletionRankingModelKey(), + int(completionRankingModel)).toInt()); + autoIncludeHeaders = map.value(clangdHeaderInsertionKey(), false).toBool(); + workerThreadLimit = map.value(clangdThreadLimitKey(), 0).toInt(); + documentUpdateThreshold = map.value(clangdDocumentThresholdKey(), 500).toInt(); + sizeThresholdEnabled = map.value(clangdSizeThresholdEnabledKey(), false).toBool(); + sizeThresholdInKb = map.value(clangdSizeThresholdKey(), 1024).toLongLong(); + sessionsWithOneClangd = map.value(sessionsWithOneClangdKey()).toStringList(); + diagnosticConfigId = Id::fromSetting(map.value(diagnosticConfigIdKey(), + initialClangDiagnosticConfigId().toSetting())); + haveCheckedHardwareReqirements = map.value(checkedHardwareKey(), false).toBool(); + completionResults = map.value(completionResultsKey(), defaultCompletionResults()).toInt(); +} + +int ClangdSettings::Data::defaultCompletionResults() +{ + // Default clangd --limit-results value is 100 + bool ok = false; + const int userValue = qtcEnvironmentVariableIntValue("QTC_CLANGD_COMPLETION_RESULTS", &ok); + return ok ? userValue : 100; +} + +} // namespace CppEditor diff --git a/src/plugins/cppeditor/clangdsettings.h b/src/plugins/cppeditor/clangdsettings.h new file mode 100644 index 0000000000..c1fb3b6ae8 --- /dev/null +++ b/src/plugins/cppeditor/clangdsettings.h @@ -0,0 +1,162 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#pragma once + +#include "clangdiagnosticconfig.h" +#include "cppeditor_global.h" + +#include <utils/filepath.h> +#include <utils/store.h> + +namespace ProjectExplorer { class Project; } +namespace Utils { class MacroExpander; } + +namespace CppEditor { + +// TODO: Can we move this to ClangCodeModel? +class CPPEDITOR_EXPORT ClangdSettings : public QObject +{ + Q_OBJECT +public: + enum class IndexingPriority { Off, Background, Normal, Low, }; + enum class HeaderSourceSwitchMode { BuiltinOnly, ClangdOnly, Both }; + enum class CompletionRankingModel { Default, DecisionForest, Heuristics }; + + static QString priorityToString(const IndexingPriority &priority); + static QString priorityToDisplayString(const IndexingPriority &priority); + static QString headerSourceSwitchModeToDisplayString(HeaderSourceSwitchMode mode); + static QString rankingModelToCmdLineString(CompletionRankingModel model); + static QString rankingModelToDisplayString(CompletionRankingModel model); + static QString defaultProjectIndexPathTemplate(); + static QString defaultSessionIndexPathTemplate(); + + class CPPEDITOR_EXPORT Data + { + public: + Utils::Store toMap() const; + void fromMap(const Utils::Store &map); + + friend bool operator==(const Data &s1, const Data &s2) + { + return s1.useClangd == s2.useClangd + && s1.executableFilePath == s2.executableFilePath + && s1.projectIndexPathTemplate == s2.projectIndexPathTemplate + && s1.sessionIndexPathTemplate == s2.sessionIndexPathTemplate + && s1.sessionsWithOneClangd == s2.sessionsWithOneClangd + && s1.customDiagnosticConfigs == s2.customDiagnosticConfigs + && s1.diagnosticConfigId == s2.diagnosticConfigId + && s1.workerThreadLimit == s2.workerThreadLimit + && s1.indexingPriority == s2.indexingPriority + && s1.headerSourceSwitchMode == s2.headerSourceSwitchMode + && s1.completionRankingModel == s2.completionRankingModel + && s1.autoIncludeHeaders == s2.autoIncludeHeaders + && s1.documentUpdateThreshold == s2.documentUpdateThreshold + && s1.sizeThresholdEnabled == s2.sizeThresholdEnabled + && s1.sizeThresholdInKb == s2.sizeThresholdInKb + && s1.haveCheckedHardwareReqirements == s2.haveCheckedHardwareReqirements + && s1.completionResults == s2.completionResults; + } + friend bool operator!=(const Data &s1, const Data &s2) { return !(s1 == s2); } + + Utils::FilePath executableFilePath; + QStringList sessionsWithOneClangd; + ClangDiagnosticConfigs customDiagnosticConfigs; + Utils::Id diagnosticConfigId; + + int workerThreadLimit = 0; + int documentUpdateThreshold = 500; + qint64 sizeThresholdInKb = 1024; + bool useClangd = true; + IndexingPriority indexingPriority = IndexingPriority::Low; + QString projectIndexPathTemplate = defaultProjectIndexPathTemplate(); + QString sessionIndexPathTemplate = defaultSessionIndexPathTemplate(); + HeaderSourceSwitchMode headerSourceSwitchMode = HeaderSourceSwitchMode::Both; + CompletionRankingModel completionRankingModel = CompletionRankingModel::Default; + bool autoIncludeHeaders = false; + bool sizeThresholdEnabled = false; + bool haveCheckedHardwareReqirements = false; + int completionResults = defaultCompletionResults(); + + private: + static int defaultCompletionResults(); + }; + + ClangdSettings(const Data &data) : m_data(data) {} + + static ClangdSettings &instance(); + bool useClangd() const; + static void setUseClangd(bool use); + static void setUseClangdAndSave(bool use); + + static bool hardwareFulfillsRequirements(); + static bool haveCheckedHardwareRequirements(); + + static void setDefaultClangdPath(const Utils::FilePath &filePath); + static void setCustomDiagnosticConfigs(const ClangDiagnosticConfigs &configs); + Utils::FilePath clangdFilePath() const; + IndexingPriority indexingPriority() const { return m_data.indexingPriority; } + Utils::FilePath projectIndexPath(const Utils::MacroExpander &expander) const; + Utils::FilePath sessionIndexPath(const Utils::MacroExpander &expander) const; + HeaderSourceSwitchMode headerSourceSwitchMode() const { return m_data.headerSourceSwitchMode; } + CompletionRankingModel completionRankingModel() const { return m_data.completionRankingModel; } + bool autoIncludeHeaders() const { return m_data.autoIncludeHeaders; } + int workerThreadLimit() const { return m_data.workerThreadLimit; } + int documentUpdateThreshold() const { return m_data.documentUpdateThreshold; } + qint64 sizeThresholdInKb() const { return m_data.sizeThresholdInKb; } + bool sizeThresholdEnabled() const { return m_data.sizeThresholdEnabled; } + int completionResults() const { return m_data.completionResults; } + bool sizeIsOkay(const Utils::FilePath &fp) const; + ClangDiagnosticConfigs customDiagnosticConfigs() const; + Utils::Id diagnosticConfigId() const; + ClangDiagnosticConfig diagnosticConfig() const; + + enum class Granularity { Project, Session }; + Granularity granularity() const; + + void setData(const Data &data); + Data data() const { return m_data; } + + Utils::FilePath clangdIncludePath() const; + static Utils::FilePath clangdUserConfigFilePath(); + +#ifdef WITH_TESTS + static void setClangdFilePath(const Utils::FilePath &filePath); +#endif + +signals: + void changed(); + +private: + ClangdSettings(); + + void loadSettings(); + void saveSettings(); + + Data m_data; +}; + +class CPPEDITOR_EXPORT ClangdProjectSettings +{ +public: + ClangdProjectSettings(ProjectExplorer::Project *project); + + ClangdSettings::Data settings() const; + void setSettings(const ClangdSettings::Data &data); + bool useGlobalSettings() const { return m_useGlobalSettings; } + void setUseGlobalSettings(bool useGlobal); + void setDiagnosticConfigId(Utils::Id configId); + void blockIndexing(); + void unblockIndexing(); + +private: + void loadSettings(); + void saveSettings(); + + ProjectExplorer::Project * const m_project; + ClangdSettings::Data m_customSettings; + bool m_useGlobalSettings = true; + bool m_blockIndexing = false; +}; + +} // namespace CppEditor diff --git a/src/plugins/cppeditor/cppcodemodelsettings.cpp b/src/plugins/cppeditor/cppcodemodelsettings.cpp index d1b4c47098..d4a309363a 100644 --- a/src/plugins/cppeditor/cppcodemodelsettings.cpp +++ b/src/plugins/cppeditor/cppcodemodelsettings.cpp @@ -3,14 +3,10 @@ #include "cppcodemodelsettings.h" -#include "clangdiagnosticconfigsmodel.h" #include "compileroptionsbuilder.h" #include "cppeditorconstants.h" -#include "cppeditortr.h" -#include "cpptoolsreuse.h" #include <coreplugin/icore.h> -#include <coreplugin/session.h> #include <projectexplorer/project.h> #include <projectexplorer/projectmanager.h> @@ -27,14 +23,12 @@ #include <QHash> #include <QPair> #include <QSettings> -#include <QStandardPaths> using namespace ProjectExplorer; using namespace Utils; namespace CppEditor { -static Id initialClangDiagnosticConfigId() { return Constants::CPP_CLANG_DIAG_CONFIG_BUILDSYSTEM; } static Key pchUsageKey() { return Constants::CPPEDITOR_MODEL_MANAGER_PCH_USAGE; } static Key interpretAmbiguousHeadersAsCHeadersKey() { return Constants::CPPEDITOR_INTERPRET_AMBIGIUOUS_HEADERS_AS_C_HEADERS; } @@ -43,35 +37,7 @@ static Key ignoreFilesKey() { return Constants::CPPEDITOR_IGNORE_FILES; } static Key ignorePatternKey() { return Constants::CPPEDITOR_IGNORE_PATTERN; } static Key useBuiltinPreprocessorKey() { return Constants::CPPEDITOR_USE_BUILTIN_PREPROCESSOR; } static Key indexerFileSizeLimitKey() { return Constants::CPPEDITOR_INDEXER_FILE_SIZE_LIMIT; } - -static Key clangdSettingsKey() { return "ClangdSettings"; } -static Key useClangdKey() { return "UseClangdV7"; } -static Key clangdPathKey() { return "ClangdPath"; } -static Key clangdIndexingKey() { return "ClangdIndexing"; } -static Key clangdProjectIndexPathKey() { return "ClangdProjectIndexPath"; } -static Key clangdSessionIndexPathKey() { return "ClangdSessionIndexPath"; } -static Key clangdIndexingPriorityKey() { return "ClangdIndexingPriority"; } -static Key clangdHeaderSourceSwitchModeKey() { return "ClangdHeaderSourceSwitchMode"; } -static Key clangdCompletionRankingModelKey() { return "ClangdCompletionRankingModel"; } -static Key clangdHeaderInsertionKey() { return "ClangdHeaderInsertion"; } -static Key clangdThreadLimitKey() { return "ClangdThreadLimit"; } -static Key clangdDocumentThresholdKey() { return "ClangdDocumentThreshold"; } -static Key clangdSizeThresholdEnabledKey() { return "ClangdSizeThresholdEnabled"; } -static Key clangdSizeThresholdKey() { return "ClangdSizeThreshold"; } static Key useGlobalSettingsKey() { return "useGlobalSettings"; } -static Key clangdblockIndexingSettingsKey() { return "blockIndexing"; } -static Key sessionsWithOneClangdKey() { return "SessionsWithOneClangd"; } -static Key diagnosticConfigIdKey() { return "diagnosticConfigId"; } -static Key checkedHardwareKey() { return "checkedHardware"; } -static Key completionResultsKey() { return "completionResults"; } - -static FilePath g_defaultClangdFilePath; -static FilePath fallbackClangdFilePath() -{ - if (g_defaultClangdFilePath.exists()) - return g_defaultClangdFilePath; - return Environment::systemEnvironment().searchInPath("clangd"); -} bool operator==(const CppEditor::CppCodeModelSettings::Data &s1, const CppEditor::CppCodeModelSettings::Data &s2) @@ -230,440 +196,4 @@ void CppCodeModelProjectSettings::saveSettings() m_project->setNamedSettings(Constants::CPPEDITOR_SETTINGSGROUP, variantFromStore(data)); } -QString ClangdSettings::priorityToString(const IndexingPriority &priority) -{ - switch (priority) { - case IndexingPriority::Background: return "background"; - case IndexingPriority::Normal: return "normal"; - case IndexingPriority::Low: return "low"; - case IndexingPriority::Off: return {}; - } - return {}; -} - -QString ClangdSettings::priorityToDisplayString(const IndexingPriority &priority) -{ - switch (priority) { - case IndexingPriority::Background: return Tr::tr("Background Priority"); - case IndexingPriority::Normal: return Tr::tr("Normal Priority"); - case IndexingPriority::Low: return Tr::tr("Low Priority"); - case IndexingPriority::Off: return Tr::tr("Off"); - } - return {}; -} - -QString ClangdSettings::headerSourceSwitchModeToDisplayString(HeaderSourceSwitchMode mode) -{ - switch (mode) { - case HeaderSourceSwitchMode::BuiltinOnly: return Tr::tr("Use Built-in Only"); - case HeaderSourceSwitchMode::ClangdOnly: return Tr::tr("Use Clangd Only"); - case HeaderSourceSwitchMode::Both: return Tr::tr("Try Both"); - } - return {}; -} - -QString ClangdSettings::rankingModelToCmdLineString(CompletionRankingModel model) -{ - switch (model) { - case CompletionRankingModel::Default: break; - case CompletionRankingModel::DecisionForest: return "decision_forest"; - case CompletionRankingModel::Heuristics: return "heuristics"; - } - QTC_ASSERT(false, return {}); -} - -QString ClangdSettings::rankingModelToDisplayString(CompletionRankingModel model) -{ - switch (model) { - case CompletionRankingModel::Default: return Tr::tr("Default"); - case CompletionRankingModel::DecisionForest: return Tr::tr("Decision Forest"); - case CompletionRankingModel::Heuristics: return Tr::tr("Heuristics"); - } - QTC_ASSERT(false, return {}); -} - -QString ClangdSettings::defaultProjectIndexPathTemplate() -{ - return QDir::toNativeSeparators("%{BuildConfig:BuildDirectory:FilePath}/.qtc_clangd"); -} - -QString ClangdSettings::defaultSessionIndexPathTemplate() -{ - return QDir::toNativeSeparators("%{IDE:UserResourcePath}/.qtc_clangd/%{Session:FileBaseName}"); -} - -ClangdSettings &ClangdSettings::instance() -{ - static ClangdSettings settings; - return settings; -} - -ClangdSettings::ClangdSettings() -{ - loadSettings(); - const auto sessionMgr = Core::SessionManager::instance(); - connect(sessionMgr, &Core::SessionManager::sessionRemoved, this, [this](const QString &name) { - m_data.sessionsWithOneClangd.removeOne(name); - }); - connect(sessionMgr, - &Core::SessionManager::sessionRenamed, - this, - [this](const QString &oldName, const QString &newName) { - const auto index = m_data.sessionsWithOneClangd.indexOf(oldName); - if (index != -1) - m_data.sessionsWithOneClangd[index] = newName; - }); -} - -bool ClangdSettings::useClangd() const -{ - return m_data.useClangd && clangdVersion(clangdFilePath()) >= minimumClangdVersion(); -} - -void ClangdSettings::setUseClangd(bool use) { instance().m_data.useClangd = use; } - -void ClangdSettings::setUseClangdAndSave(bool use) -{ - setUseClangd(use); - instance().saveSettings(); -} - -bool ClangdSettings::hardwareFulfillsRequirements() -{ - instance().m_data.haveCheckedHardwareReqirements = true; - instance().saveSettings(); - const quint64 minRam = quint64(12) * 1024 * 1024 * 1024; - const std::optional<quint64> totalRam = Utils::HostOsInfo::totalMemoryInstalledInBytes(); - return !totalRam || *totalRam >= minRam; -} - -bool ClangdSettings::haveCheckedHardwareRequirements() -{ - return instance().data().haveCheckedHardwareReqirements; -} - -void ClangdSettings::setDefaultClangdPath(const FilePath &filePath) -{ - g_defaultClangdFilePath = filePath; -} - -void ClangdSettings::setCustomDiagnosticConfigs(const ClangDiagnosticConfigs &configs) -{ - if (instance().customDiagnosticConfigs() == configs) - return; - instance().m_data.customDiagnosticConfigs = configs; - instance().saveSettings(); -} - -FilePath ClangdSettings::clangdFilePath() const -{ - if (!m_data.executableFilePath.isEmpty()) - return m_data.executableFilePath; - return fallbackClangdFilePath(); -} - -FilePath ClangdSettings::projectIndexPath(const Utils::MacroExpander &expander) const -{ - return FilePath::fromUserInput(expander.expand(m_data.projectIndexPathTemplate)); -} - -FilePath ClangdSettings::sessionIndexPath(const Utils::MacroExpander &expander) const -{ - return FilePath::fromUserInput(expander.expand(m_data.sessionIndexPathTemplate)); -} - -bool ClangdSettings::sizeIsOkay(const Utils::FilePath &fp) const -{ - return !sizeThresholdEnabled() || sizeThresholdInKb() * 1024 >= fp.fileSize(); -} - -ClangDiagnosticConfigs ClangdSettings::customDiagnosticConfigs() const -{ - return m_data.customDiagnosticConfigs; -} - -Id ClangdSettings::diagnosticConfigId() const -{ - if (!diagnosticConfigsModel().hasConfigWithId(m_data.diagnosticConfigId)) - return initialClangDiagnosticConfigId(); - return m_data.diagnosticConfigId; -} - -ClangDiagnosticConfig ClangdSettings::diagnosticConfig() const -{ - return diagnosticConfigsModel(customDiagnosticConfigs()).configWithId(diagnosticConfigId()); -} - -ClangdSettings::Granularity ClangdSettings::granularity() const -{ - if (m_data.sessionsWithOneClangd.contains(Core::SessionManager::activeSession())) - return Granularity::Session; - return Granularity::Project; -} - -void ClangdSettings::setData(const Data &data) -{ - if (this == &instance() && data != m_data) { - m_data = data; - saveSettings(); - emit changed(); - } -} - -static FilePath getClangHeadersPathFromClang(const FilePath &clangdFilePath) -{ - const FilePath clangFilePath = clangdFilePath.absolutePath().pathAppended("clang") - .withExecutableSuffix(); - if (!clangFilePath.exists()) - return {}; - Process clang; - clang.setCommand({clangFilePath, {"-print-resource-dir"}}); - clang.start(); - if (!clang.waitForFinished()) - return {}; - const FilePath resourceDir = FilePath::fromUserInput(QString::fromLocal8Bit( - clang.rawStdOut().trimmed())); - if (resourceDir.isEmpty() || !resourceDir.exists()) - return {}; - const FilePath includeDir = resourceDir.pathAppended("include"); - if (!includeDir.exists()) - return {}; - return includeDir; -} - -static FilePath getClangHeadersPath(const FilePath &clangdFilePath) -{ - const FilePath headersPath = getClangHeadersPathFromClang(clangdFilePath); - if (!headersPath.isEmpty()) - return headersPath; - - const QVersionNumber version = Utils::clangdVersion(clangdFilePath); - QTC_ASSERT(!version.isNull(), return {}); - static const QStringList libDirs{"lib", "lib64"}; - const QStringList versionStrings{QString::number(version.majorVersion()), version.toString()}; - for (const QString &libDir : libDirs) { - for (const QString &versionString : versionStrings) { - const FilePath includePath = clangdFilePath.absolutePath().parentDir() - .pathAppended(libDir).pathAppended("clang") - .pathAppended(versionString).pathAppended("include"); - if (includePath.exists()) - return includePath; - } - } - QTC_CHECK(false); - return {}; -} - -FilePath ClangdSettings::clangdIncludePath() const -{ - QTC_ASSERT(useClangd(), return {}); - FilePath clangdPath = clangdFilePath(); - QTC_ASSERT(!clangdPath.isEmpty() && clangdPath.exists(), return {}); - static QHash<FilePath, FilePath> headersPathCache; - const auto it = headersPathCache.constFind(clangdPath); - if (it != headersPathCache.constEnd()) - return *it; - const FilePath headersPath = getClangHeadersPath(clangdPath); - if (!headersPath.isEmpty()) - headersPathCache.insert(clangdPath, headersPath); - return headersPath; -} - -FilePath ClangdSettings::clangdUserConfigFilePath() -{ - return FilePath::fromString( - QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation)) - / "clangd/config.yaml"; -} - -void ClangdSettings::loadSettings() -{ - const auto settings = Core::ICore::settings(); - - m_data.fromMap(Utils::storeFromSettings(clangdSettingsKey(), settings)); - - settings->beginGroup(Constants::CPPEDITOR_SETTINGSGROUP); - m_data.customDiagnosticConfigs = diagnosticConfigsFromSettings(settings); - - // Pre-8.0 compat - static const Key oldKey("ClangDiagnosticConfig"); - const QVariant configId = settings->value(oldKey); - if (configId.isValid()) { - m_data.diagnosticConfigId = Id::fromSetting(configId); - settings->setValue(oldKey, {}); - } - - settings->endGroup(); -} - -void ClangdSettings::saveSettings() -{ - const auto settings = Core::ICore::settings(); - const ClangdSettings::Data defaultData; - Utils::storeToSettingsWithDefault(clangdSettingsKey(), - settings, - m_data.toMap(), - defaultData.toMap()); - settings->beginGroup(Constants::CPPEDITOR_SETTINGSGROUP); - diagnosticConfigsToSettings(settings, m_data.customDiagnosticConfigs); - settings->endGroup(); -} - -#ifdef WITH_TESTS -void ClangdSettings::setClangdFilePath(const FilePath &filePath) -{ - instance().m_data.executableFilePath = filePath; -} -#endif - -ClangdProjectSettings::ClangdProjectSettings(ProjectExplorer::Project *project) : m_project(project) -{ - loadSettings(); -} - -ClangdSettings::Data ClangdProjectSettings::settings() const -{ - const ClangdSettings::Data globalData = ClangdSettings::instance().data(); - ClangdSettings::Data data = globalData; - if (!m_useGlobalSettings) { - data = m_customSettings; - // This property is global by definition. - data.sessionsWithOneClangd = ClangdSettings::instance().data().sessionsWithOneClangd; - - // This list exists only once. - data.customDiagnosticConfigs = ClangdSettings::instance().data().customDiagnosticConfigs; -} - if (m_blockIndexing) - data.indexingPriority = ClangdSettings::IndexingPriority::Off; - return data; -} - -void ClangdProjectSettings::setSettings(const ClangdSettings::Data &data) -{ - m_customSettings = data; - saveSettings(); - ClangdSettings::setCustomDiagnosticConfigs(data.customDiagnosticConfigs); - emit ClangdSettings::instance().changed(); -} - -void ClangdProjectSettings::setUseGlobalSettings(bool useGlobal) -{ - m_useGlobalSettings = useGlobal; - saveSettings(); - emit ClangdSettings::instance().changed(); -} - -void ClangdProjectSettings::setDiagnosticConfigId(Utils::Id configId) -{ - m_customSettings.diagnosticConfigId = configId; - saveSettings(); - emit ClangdSettings::instance().changed(); -} - -void ClangdProjectSettings::blockIndexing() -{ - if (m_blockIndexing) - return; - m_blockIndexing = true; - saveSettings(); - emit ClangdSettings::instance().changed(); -} - -void ClangdProjectSettings::unblockIndexing() -{ - if (!m_blockIndexing) - return; - m_blockIndexing = false; - saveSettings(); - // Do not emit changed here since that would restart clients with blocked indexing -} - -void ClangdProjectSettings::loadSettings() -{ - if (!m_project) - return; - const Store data = storeFromVariant(m_project->namedSettings(clangdSettingsKey())); - m_useGlobalSettings = data.value(useGlobalSettingsKey(), true).toBool(); - m_blockIndexing = data.value(clangdblockIndexingSettingsKey(), false).toBool(); - if (!m_useGlobalSettings) - m_customSettings.fromMap(data); -} - -void ClangdProjectSettings::saveSettings() -{ - if (!m_project) - return; - Store data; - if (!m_useGlobalSettings) - data = m_customSettings.toMap(); - data.insert(useGlobalSettingsKey(), m_useGlobalSettings); - data.insert(clangdblockIndexingSettingsKey(), m_blockIndexing); - m_project->setNamedSettings(clangdSettingsKey(), variantFromStore(data)); -} - -Store ClangdSettings::Data::toMap() const -{ - Store map; - - map.insert(useClangdKey(), useClangd); - - map.insert(clangdPathKey(), - executableFilePath != fallbackClangdFilePath() ? executableFilePath.toString() - : QString()); - - map.insert(clangdIndexingKey(), indexingPriority != IndexingPriority::Off); - map.insert(clangdIndexingPriorityKey(), int(indexingPriority)); - map.insert(clangdProjectIndexPathKey(), projectIndexPathTemplate); - map.insert(clangdSessionIndexPathKey(), sessionIndexPathTemplate); - map.insert(clangdHeaderSourceSwitchModeKey(), int(headerSourceSwitchMode)); - map.insert(clangdCompletionRankingModelKey(), int(completionRankingModel)); - map.insert(clangdHeaderInsertionKey(), autoIncludeHeaders); - map.insert(clangdThreadLimitKey(), workerThreadLimit); - map.insert(clangdDocumentThresholdKey(), documentUpdateThreshold); - map.insert(clangdSizeThresholdEnabledKey(), sizeThresholdEnabled); - map.insert(clangdSizeThresholdKey(), sizeThresholdInKb); - map.insert(sessionsWithOneClangdKey(), sessionsWithOneClangd); - map.insert(diagnosticConfigIdKey(), diagnosticConfigId.toSetting()); - map.insert(checkedHardwareKey(), haveCheckedHardwareReqirements); - map.insert(completionResultsKey(), completionResults); - return map; -} - -void ClangdSettings::Data::fromMap(const Store &map) -{ - useClangd = map.value(useClangdKey(), true).toBool(); - executableFilePath = FilePath::fromString(map.value(clangdPathKey()).toString()); - indexingPriority = IndexingPriority( - map.value(clangdIndexingPriorityKey(), int(this->indexingPriority)).toInt()); - const auto it = map.find(clangdIndexingKey()); - if (it != map.end() && !it->toBool()) - indexingPriority = IndexingPriority::Off; - projectIndexPathTemplate - = map.value(clangdProjectIndexPathKey(), defaultProjectIndexPathTemplate()).toString(); - sessionIndexPathTemplate - = map.value(clangdSessionIndexPathKey(), defaultSessionIndexPathTemplate()).toString(); - headerSourceSwitchMode = HeaderSourceSwitchMode(map.value(clangdHeaderSourceSwitchModeKey(), - int(headerSourceSwitchMode)).toInt()); - completionRankingModel = CompletionRankingModel(map.value(clangdCompletionRankingModelKey(), - int(completionRankingModel)).toInt()); - autoIncludeHeaders = map.value(clangdHeaderInsertionKey(), false).toBool(); - workerThreadLimit = map.value(clangdThreadLimitKey(), 0).toInt(); - documentUpdateThreshold = map.value(clangdDocumentThresholdKey(), 500).toInt(); - sizeThresholdEnabled = map.value(clangdSizeThresholdEnabledKey(), false).toBool(); - sizeThresholdInKb = map.value(clangdSizeThresholdKey(), 1024).toLongLong(); - sessionsWithOneClangd = map.value(sessionsWithOneClangdKey()).toStringList(); - diagnosticConfigId = Id::fromSetting(map.value(diagnosticConfigIdKey(), - initialClangDiagnosticConfigId().toSetting())); - haveCheckedHardwareReqirements = map.value(checkedHardwareKey(), false).toBool(); - completionResults = map.value(completionResultsKey(), defaultCompletionResults()).toInt(); -} - -int ClangdSettings::Data::defaultCompletionResults() -{ - // Default clangd --limit-results value is 100 - bool ok = false; - const int userValue = qtcEnvironmentVariableIntValue("QTC_CLANGD_COMPLETION_RESULTS", &ok); - return ok ? userValue : 100; -} - } // namespace CppEditor diff --git a/src/plugins/cppeditor/cppcodemodelsettings.h b/src/plugins/cppeditor/cppcodemodelsettings.h index 19cc078b26..0bd9b05fbd 100644 --- a/src/plugins/cppeditor/cppcodemodelsettings.h +++ b/src/plugins/cppeditor/cppcodemodelsettings.h @@ -3,10 +3,8 @@ #pragma once -#include "clangdiagnosticconfig.h" #include "cppeditor_global.h" -#include <utils/clangutils.h> #include <utils/filepath.h> #include <utils/id.h> #include <utils/store.h> @@ -14,12 +12,8 @@ #include <QObject> #include <QStringList> -#include <QVersionNumber> namespace ProjectExplorer { class Project; } -namespace Utils { -class MacroExpander; -} // namespace Utils namespace CppEditor { enum class UsePrecompiledHeaders; @@ -114,148 +108,4 @@ private: bool m_useGlobalSettings = true; }; -class CPPEDITOR_EXPORT ClangdSettings : public QObject -{ - Q_OBJECT -public: - enum class IndexingPriority { Off, Background, Normal, Low, }; - enum class HeaderSourceSwitchMode { BuiltinOnly, ClangdOnly, Both }; - enum class CompletionRankingModel { Default, DecisionForest, Heuristics }; - - static QString priorityToString(const IndexingPriority &priority); - static QString priorityToDisplayString(const IndexingPriority &priority); - static QString headerSourceSwitchModeToDisplayString(HeaderSourceSwitchMode mode); - static QString rankingModelToCmdLineString(CompletionRankingModel model); - static QString rankingModelToDisplayString(CompletionRankingModel model); - static QString defaultProjectIndexPathTemplate(); - static QString defaultSessionIndexPathTemplate(); - - class CPPEDITOR_EXPORT Data - { - public: - Utils::Store toMap() const; - void fromMap(const Utils::Store &map); - - friend bool operator==(const Data &s1, const Data &s2) - { - return s1.useClangd == s2.useClangd - && s1.executableFilePath == s2.executableFilePath - && s1.projectIndexPathTemplate == s2.projectIndexPathTemplate - && s1.sessionIndexPathTemplate == s2.sessionIndexPathTemplate - && s1.sessionsWithOneClangd == s2.sessionsWithOneClangd - && s1.customDiagnosticConfigs == s2.customDiagnosticConfigs - && s1.diagnosticConfigId == s2.diagnosticConfigId - && s1.workerThreadLimit == s2.workerThreadLimit - && s1.indexingPriority == s2.indexingPriority - && s1.headerSourceSwitchMode == s2.headerSourceSwitchMode - && s1.completionRankingModel == s2.completionRankingModel - && s1.autoIncludeHeaders == s2.autoIncludeHeaders - && s1.documentUpdateThreshold == s2.documentUpdateThreshold - && s1.sizeThresholdEnabled == s2.sizeThresholdEnabled - && s1.sizeThresholdInKb == s2.sizeThresholdInKb - && s1.haveCheckedHardwareReqirements == s2.haveCheckedHardwareReqirements - && s1.completionResults == s2.completionResults; - } - friend bool operator!=(const Data &s1, const Data &s2) { return !(s1 == s2); } - - Utils::FilePath executableFilePath; - QStringList sessionsWithOneClangd; - ClangDiagnosticConfigs customDiagnosticConfigs; - Utils::Id diagnosticConfigId; - - int workerThreadLimit = 0; - int documentUpdateThreshold = 500; - qint64 sizeThresholdInKb = 1024; - bool useClangd = true; - IndexingPriority indexingPriority = IndexingPriority::Low; - QString projectIndexPathTemplate = defaultProjectIndexPathTemplate(); - QString sessionIndexPathTemplate = defaultSessionIndexPathTemplate(); - HeaderSourceSwitchMode headerSourceSwitchMode = HeaderSourceSwitchMode::Both; - CompletionRankingModel completionRankingModel = CompletionRankingModel::Default; - bool autoIncludeHeaders = false; - bool sizeThresholdEnabled = false; - bool haveCheckedHardwareReqirements = false; - int completionResults = defaultCompletionResults(); - - private: - static int defaultCompletionResults(); - }; - - ClangdSettings(const Data &data) : m_data(data) {} - - static ClangdSettings &instance(); - bool useClangd() const; - static void setUseClangd(bool use); - static void setUseClangdAndSave(bool use); - - static bool hardwareFulfillsRequirements(); - static bool haveCheckedHardwareRequirements(); - - static void setDefaultClangdPath(const Utils::FilePath &filePath); - static void setCustomDiagnosticConfigs(const ClangDiagnosticConfigs &configs); - Utils::FilePath clangdFilePath() const; - IndexingPriority indexingPriority() const { return m_data.indexingPriority; } - Utils::FilePath projectIndexPath(const Utils::MacroExpander &expander) const; - Utils::FilePath sessionIndexPath(const Utils::MacroExpander &expander) const; - HeaderSourceSwitchMode headerSourceSwitchMode() const { return m_data.headerSourceSwitchMode; } - CompletionRankingModel completionRankingModel() const { return m_data.completionRankingModel; } - bool autoIncludeHeaders() const { return m_data.autoIncludeHeaders; } - int workerThreadLimit() const { return m_data.workerThreadLimit; } - int documentUpdateThreshold() const { return m_data.documentUpdateThreshold; } - qint64 sizeThresholdInKb() const { return m_data.sizeThresholdInKb; } - bool sizeThresholdEnabled() const { return m_data.sizeThresholdEnabled; } - int completionResults() const { return m_data.completionResults; } - bool sizeIsOkay(const Utils::FilePath &fp) const; - ClangDiagnosticConfigs customDiagnosticConfigs() const; - Utils::Id diagnosticConfigId() const; - ClangDiagnosticConfig diagnosticConfig() const; - - enum class Granularity { Project, Session }; - Granularity granularity() const; - - void setData(const Data &data); - Data data() const { return m_data; } - - Utils::FilePath clangdIncludePath() const; - static Utils::FilePath clangdUserConfigFilePath(); - -#ifdef WITH_TESTS - static void setClangdFilePath(const Utils::FilePath &filePath); -#endif - -signals: - void changed(); - -private: - ClangdSettings(); - - void loadSettings(); - void saveSettings(); - - Data m_data; -}; - -class CPPEDITOR_EXPORT ClangdProjectSettings -{ -public: - ClangdProjectSettings(ProjectExplorer::Project *project); - - ClangdSettings::Data settings() const; - void setSettings(const ClangdSettings::Data &data); - bool useGlobalSettings() const { return m_useGlobalSettings; } - void setUseGlobalSettings(bool useGlobal); - void setDiagnosticConfigId(Utils::Id configId); - void blockIndexing(); - void unblockIndexing(); - -private: - void loadSettings(); - void saveSettings(); - - ProjectExplorer::Project * const m_project; - ClangdSettings::Data m_customSettings; - bool m_useGlobalSettings = true; - bool m_blockIndexing = false; -}; - } // namespace CppEditor diff --git a/src/plugins/cppeditor/cppcodemodelsettingspage.cpp b/src/plugins/cppeditor/cppcodemodelsettingspage.cpp index 616bb34f61..0e880fcb55 100644 --- a/src/plugins/cppeditor/cppcodemodelsettingspage.cpp +++ b/src/plugins/cppeditor/cppcodemodelsettingspage.cpp @@ -5,6 +5,7 @@ #include "clangdiagnosticconfigsselectionwidget.h" #include "clangdiagnosticconfigswidget.h" +#include "clangdsettings.h" #include "cppcodemodelsettings.h" #include "cppeditorconstants.h" #include "cppeditortr.h" @@ -18,6 +19,7 @@ #include <projectexplorer/projectsettingswidget.h> #include <utils/algorithm.h> +#include <utils/clangutils.h> #include <utils/fancylineedit.h> #include <utils/infolabel.h> #include <utils/itemviews.h> diff --git a/src/plugins/cppeditor/cppeditor.qbs b/src/plugins/cppeditor/cppeditor.qbs index b684b0e0ea..b805e3fae9 100644 --- a/src/plugins/cppeditor/cppeditor.qbs +++ b/src/plugins/cppeditor/cppeditor.qbs @@ -45,6 +45,8 @@ QtcPlugin { "clangdiagnosticconfigsselectionwidget.h", "clangdiagnosticconfigswidget.cpp", "clangdiagnosticconfigswidget.h", + "clangdsettings.cpp", + "clangdsettings.h", "compileroptionsbuilder.cpp", "compileroptionsbuilder.h", "cppautocompleter.cpp", diff --git a/src/plugins/cppeditor/cpptoolsreuse.cpp b/src/plugins/cppeditor/cpptoolsreuse.cpp index f6e58abddf..947ecdd4c6 100644 --- a/src/plugins/cppeditor/cpptoolsreuse.cpp +++ b/src/plugins/cppeditor/cpptoolsreuse.cpp @@ -4,6 +4,7 @@ #include "cpptoolsreuse.h" #include "clangdiagnosticconfigsmodel.h" +#include "clangdsettings.h" #include "cppautocompleter.h" #include "cppcanonicalsymbol.h" #include "cppcodemodelsettings.h" diff --git a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp index 9bef50b0b8..41dd6b538f 100644 --- a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp +++ b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp @@ -3,6 +3,7 @@ #include "followsymbol_switchmethoddecldef_test.h" +#include "clangdsettings.h" #include "cppcodemodelsettings.h" #include "cppeditorwidget.h" #include "cppfollowsymbolundercursor.h" |