From 42d7304d2b641b4dfd4343aa5071b2457f9e15d3 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Thu, 12 Jan 2023 15:44:40 +0100 Subject: [PATCH] ClangCodeModel: Allow cancelling the background index Restarts the client with temporarily disabled indexing. The block is reset after starting clangd, so any subsequent changes to the configuration or the project will start the client again with indexing enabled. Change-Id: I16c975b6ef0b56f27ce5b2ced01f534f8ae0b4d3 Reviewed-by: Reviewed-by: Christian Kandeler --- src/plugins/clangcodemodel/clangdclient.cpp | 17 +++++----- .../cppeditor/cppcodemodelsettings.cpp | 33 ++++++++++++++++--- src/plugins/cppeditor/cppcodemodelsettings.h | 3 ++ .../languageclient/progressmanager.cpp | 18 +++++++--- src/plugins/languageclient/progressmanager.h | 6 +++- 5 files changed, 58 insertions(+), 19 deletions(-) diff --git a/src/plugins/clangcodemodel/clangdclient.cpp b/src/plugins/clangcodemodel/clangdclient.cpp index 4129a8ac30e..6735b96aeb5 100644 --- a/src/plugins/clangcodemodel/clangdclient.cpp +++ b/src/plugins/clangcodemodel/clangdclient.cpp @@ -14,6 +14,7 @@ #include "clangdquickfixes.h" #include "clangdsemantichighlighting.h" #include "clangdswitchdecldef.h" +#include "clangmodelmanagersupport.h" #include "clangtextmark.h" #include "clangutils.h" #include "tasktimers.h" @@ -170,6 +171,7 @@ static BaseClientInterface *clientInterface(Project *project, const Utils::FileP const bool indexingEnabled = indexingPriority != ClangdSettings::IndexingPriority::Off; if (!indexingEnabled) indexingOption += "=0"; + CppEditor::ClangdProjectSettings(project).unblockIndexing(); const QString headerInsertionOption = QString("--header-insertion=") + (settings.autoIncludeHeaders() ? "iwyu" : "never"); const QString limitResults = QString("--limit-results=%1").arg(settings.completionResults()); @@ -416,15 +418,12 @@ ClangdClient::ClangdClient(Project *project, const Utils::FilePath &jsonDbDir, c setLocatorsEnabled(false); setAutoRequestCodeActions(false); // clangd sends code actions inside diagnostics progressManager()->setTitleForToken(indexingToken(), - project ? Tr::tr("Indexing %1 with clangd").arg(project->displayName()) - : Tr::tr("Indexing session with clangd")); - progressManager()->setClickHandlerForToken(indexingToken(), [] { - // don't directly open modal dialog from click handler, because that would mess - // up the stack - QMetaObject::invokeMethod( - ICore::instance(), - [] { ICore::showOptionsDialog(CppEditor::Constants::CPP_CLANGD_SETTINGS_ID); }, - Qt::QueuedConnection); + project ? tr("Indexing %1 with clangd").arg(project->displayName()) + : tr("Indexing session with clangd")); + progressManager()->setCancelHandlerForToken(indexingToken(), [this, project]() { + CppEditor::ClangdProjectSettings projectSettings(project); + projectSettings.blockIndexing(); + progressManager()->endProgressReport(indexingToken()); }); setCurrentProject(project); setDocumentChangeUpdateThreshold(d->settings.documentUpdateThreshold); diff --git a/src/plugins/cppeditor/cppcodemodelsettings.cpp b/src/plugins/cppeditor/cppcodemodelsettings.cpp index b8edf452854..e4b567b7326 100644 --- a/src/plugins/cppeditor/cppcodemodelsettings.cpp +++ b/src/plugins/cppeditor/cppcodemodelsettings.cpp @@ -69,6 +69,7 @@ static QString clangdDocumentThresholdKey() { return QLatin1String("ClangdDocume static QString clangdSizeThresholdEnabledKey() { return QLatin1String("ClangdSizeThresholdEnabled"); } static QString clangdSizeThresholdKey() { return QLatin1String("ClangdSizeThreshold"); } static QString clangdUseGlobalSettingsKey() { return QLatin1String("useGlobalSettings"); } +static QString clangdblockIndexingSettingsKey() { return QLatin1String("blockIndexing"); } static QString sessionsWithOneClangdKey() { return QLatin1String("SessionsWithOneClangd"); } static QString diagnosticConfigIdKey() { return QLatin1String("diagnosticConfigId"); } static QString checkedHardwareKey() { return QLatin1String("checkedHardware"); } @@ -436,16 +437,18 @@ ClangdProjectSettings::ClangdProjectSettings(ProjectExplorer::Project *project) ClangdSettings::Data ClangdProjectSettings::settings() const { - if (m_useGlobalSettings) - return ClangdSettings::instance().data(); - ClangdSettings::Data data = m_customSettings; - + 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; } @@ -470,12 +473,31 @@ void ClangdProjectSettings::setDiagnosticConfigId(Utils::Id configId) saveSettings(); } +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 QVariantMap data = m_project->namedSettings(clangdSettingsKey()).toMap(); m_useGlobalSettings = data.value(clangdUseGlobalSettingsKey(), true).toBool(); + m_blockIndexing = data.value(clangdblockIndexingSettingsKey(), false).toBool(); if (!m_useGlobalSettings) m_customSettings.fromMap(data); } @@ -488,6 +510,7 @@ void ClangdProjectSettings::saveSettings() if (!m_useGlobalSettings) data = m_customSettings.toMap(); data.insert(clangdUseGlobalSettingsKey(), m_useGlobalSettings); + data.insert(clangdblockIndexingSettingsKey(), m_blockIndexing); m_project->setNamedSettings(clangdSettingsKey(), data); } diff --git a/src/plugins/cppeditor/cppcodemodelsettings.h b/src/plugins/cppeditor/cppcodemodelsettings.h index 589ebdea2a5..7bfdc2e85e8 100644 --- a/src/plugins/cppeditor/cppcodemodelsettings.h +++ b/src/plugins/cppeditor/cppcodemodelsettings.h @@ -190,6 +190,8 @@ public: bool useGlobalSettings() const { return m_useGlobalSettings; } void setUseGlobalSettings(bool useGlobal); void setDiagnosticConfigId(Utils::Id configId); + void blockIndexing(); + void unblockIndexing(); private: void loadSettings(); @@ -198,6 +200,7 @@ private: ProjectExplorer::Project * const m_project; ClangdSettings::Data m_customSettings; bool m_useGlobalSettings = true; + bool m_blockIndexing = false; }; } // namespace CppEditor diff --git a/src/plugins/languageclient/progressmanager.cpp b/src/plugins/languageclient/progressmanager.cpp index 3c367715b1c..285080e4980 100644 --- a/src/plugins/languageclient/progressmanager.cpp +++ b/src/plugins/languageclient/progressmanager.cpp @@ -47,11 +47,17 @@ void ProgressManager::setClickHandlerForToken(const LanguageServerProtocol::Prog m_clickHandlers.insert(token, handler); } +void ProgressManager::setCancelHandlerForToken(const LanguageServerProtocol::ProgressToken &token, + const std::function &handler) +{ + m_cancelHandlers.insert(token, handler); +} + void ProgressManager::reset() { const QList &tokens = m_progress.keys(); for (const ProgressToken &token : tokens) - endProgress(token); + endProgressReport(token); } bool ProgressManager::isProgressEndMessage(const LanguageServerProtocol::ProgressParams ¶ms) @@ -78,10 +84,14 @@ void ProgressManager::beginProgress(const ProgressToken &token, const WorkDonePr const QString title = m_titles.value(token, begin.title()); Core::FutureProgress *progress = Core::ProgressManager::addTask( interface->future(), title, languageClientProgressId(token)); - progress->setCancelEnabled(false); const std::function clickHandler = m_clickHandlers.value(token); if (clickHandler) QObject::connect(progress, &Core::FutureProgress::clicked, clickHandler); + const std::function cancelHandler = m_cancelHandlers.value(token); + if (cancelHandler) + QObject::connect(progress, &Core::FutureProgress::canceled, cancelHandler); + else + progress->setCancelEnabled(false); m_progress[token] = {progress, interface}; if (LOGPROGRESS().isDebugEnabled()) m_timer[token].start(); @@ -125,10 +135,10 @@ void ProgressManager::endProgress(const ProgressToken &token, const WorkDoneProg .toString(Qt::ISODateWithMs)); } } - endProgress(token); + endProgressReport(token); } -void ProgressManager::endProgress(const ProgressToken &token) +void ProgressManager::endProgressReport(const ProgressToken &token) { const LanguageClientProgress &progress = m_progress.take(token); if (progress.futureInterface) diff --git a/src/plugins/languageclient/progressmanager.h b/src/plugins/languageclient/progressmanager.h index e2afaa62ab4..1e0ad781806 100644 --- a/src/plugins/languageclient/progressmanager.h +++ b/src/plugins/languageclient/progressmanager.h @@ -31,6 +31,10 @@ public: const QString &message); void setClickHandlerForToken(const LanguageServerProtocol::ProgressToken &token, const std::function &handler); + void setCancelHandlerForToken(const LanguageServerProtocol::ProgressToken &token, + const std::function &handler); + void endProgressReport(const LanguageServerProtocol::ProgressToken &token); + void reset(); static bool isProgressEndMessage(const LanguageServerProtocol::ProgressParams ¶ms); @@ -42,7 +46,6 @@ private: const LanguageServerProtocol::WorkDoneProgressReport &report); void endProgress(const LanguageServerProtocol::ProgressToken &token, const LanguageServerProtocol::WorkDoneProgressEnd &end); - void endProgress(const LanguageServerProtocol::ProgressToken &token); struct LanguageClientProgress { QPointer progressInterface = nullptr; @@ -53,6 +56,7 @@ private: QMap m_titles; QMap m_timer; QMap> m_clickHandlers; + QMap> m_cancelHandlers; }; } // namespace LanguageClient