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