forked from qt-creator/qt-creator
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: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
@@ -14,6 +14,7 @@
|
|||||||
#include "clangdquickfixes.h"
|
#include "clangdquickfixes.h"
|
||||||
#include "clangdsemantichighlighting.h"
|
#include "clangdsemantichighlighting.h"
|
||||||
#include "clangdswitchdecldef.h"
|
#include "clangdswitchdecldef.h"
|
||||||
|
#include "clangmodelmanagersupport.h"
|
||||||
#include "clangtextmark.h"
|
#include "clangtextmark.h"
|
||||||
#include "clangutils.h"
|
#include "clangutils.h"
|
||||||
#include "tasktimers.h"
|
#include "tasktimers.h"
|
||||||
@@ -170,6 +171,7 @@ static BaseClientInterface *clientInterface(Project *project, const Utils::FileP
|
|||||||
const bool indexingEnabled = indexingPriority != ClangdSettings::IndexingPriority::Off;
|
const bool indexingEnabled = indexingPriority != ClangdSettings::IndexingPriority::Off;
|
||||||
if (!indexingEnabled)
|
if (!indexingEnabled)
|
||||||
indexingOption += "=0";
|
indexingOption += "=0";
|
||||||
|
CppEditor::ClangdProjectSettings(project).unblockIndexing();
|
||||||
const QString headerInsertionOption = QString("--header-insertion=")
|
const QString headerInsertionOption = QString("--header-insertion=")
|
||||||
+ (settings.autoIncludeHeaders() ? "iwyu" : "never");
|
+ (settings.autoIncludeHeaders() ? "iwyu" : "never");
|
||||||
const QString limitResults = QString("--limit-results=%1").arg(settings.completionResults());
|
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);
|
setLocatorsEnabled(false);
|
||||||
setAutoRequestCodeActions(false); // clangd sends code actions inside diagnostics
|
setAutoRequestCodeActions(false); // clangd sends code actions inside diagnostics
|
||||||
progressManager()->setTitleForToken(indexingToken(),
|
progressManager()->setTitleForToken(indexingToken(),
|
||||||
project ? Tr::tr("Indexing %1 with clangd").arg(project->displayName())
|
project ? tr("Indexing %1 with clangd").arg(project->displayName())
|
||||||
: Tr::tr("Indexing session with clangd"));
|
: tr("Indexing session with clangd"));
|
||||||
progressManager()->setClickHandlerForToken(indexingToken(), [] {
|
progressManager()->setCancelHandlerForToken(indexingToken(), [this, project]() {
|
||||||
// don't directly open modal dialog from click handler, because that would mess
|
CppEditor::ClangdProjectSettings projectSettings(project);
|
||||||
// up the stack
|
projectSettings.blockIndexing();
|
||||||
QMetaObject::invokeMethod(
|
progressManager()->endProgressReport(indexingToken());
|
||||||
ICore::instance(),
|
|
||||||
[] { ICore::showOptionsDialog(CppEditor::Constants::CPP_CLANGD_SETTINGS_ID); },
|
|
||||||
Qt::QueuedConnection);
|
|
||||||
});
|
});
|
||||||
setCurrentProject(project);
|
setCurrentProject(project);
|
||||||
setDocumentChangeUpdateThreshold(d->settings.documentUpdateThreshold);
|
setDocumentChangeUpdateThreshold(d->settings.documentUpdateThreshold);
|
||||||
|
@@ -69,6 +69,7 @@ static QString clangdDocumentThresholdKey() { return QLatin1String("ClangdDocume
|
|||||||
static QString clangdSizeThresholdEnabledKey() { return QLatin1String("ClangdSizeThresholdEnabled"); }
|
static QString clangdSizeThresholdEnabledKey() { return QLatin1String("ClangdSizeThresholdEnabled"); }
|
||||||
static QString clangdSizeThresholdKey() { return QLatin1String("ClangdSizeThreshold"); }
|
static QString clangdSizeThresholdKey() { return QLatin1String("ClangdSizeThreshold"); }
|
||||||
static QString clangdUseGlobalSettingsKey() { return QLatin1String("useGlobalSettings"); }
|
static QString clangdUseGlobalSettingsKey() { return QLatin1String("useGlobalSettings"); }
|
||||||
|
static QString clangdblockIndexingSettingsKey() { return QLatin1String("blockIndexing"); }
|
||||||
static QString sessionsWithOneClangdKey() { return QLatin1String("SessionsWithOneClangd"); }
|
static QString sessionsWithOneClangdKey() { return QLatin1String("SessionsWithOneClangd"); }
|
||||||
static QString diagnosticConfigIdKey() { return QLatin1String("diagnosticConfigId"); }
|
static QString diagnosticConfigIdKey() { return QLatin1String("diagnosticConfigId"); }
|
||||||
static QString checkedHardwareKey() { return QLatin1String("checkedHardware"); }
|
static QString checkedHardwareKey() { return QLatin1String("checkedHardware"); }
|
||||||
@@ -436,16 +437,18 @@ ClangdProjectSettings::ClangdProjectSettings(ProjectExplorer::Project *project)
|
|||||||
|
|
||||||
ClangdSettings::Data ClangdProjectSettings::settings() const
|
ClangdSettings::Data ClangdProjectSettings::settings() const
|
||||||
{
|
{
|
||||||
if (m_useGlobalSettings)
|
const ClangdSettings::Data globalData = ClangdSettings::instance().data();
|
||||||
return ClangdSettings::instance().data();
|
ClangdSettings::Data data = globalData;
|
||||||
ClangdSettings::Data data = m_customSettings;
|
if (!m_useGlobalSettings) {
|
||||||
|
data = m_customSettings;
|
||||||
// This property is global by definition.
|
// This property is global by definition.
|
||||||
data.sessionsWithOneClangd = ClangdSettings::instance().data().sessionsWithOneClangd;
|
data.sessionsWithOneClangd = ClangdSettings::instance().data().sessionsWithOneClangd;
|
||||||
|
|
||||||
// This list exists only once.
|
// This list exists only once.
|
||||||
data.customDiagnosticConfigs = ClangdSettings::instance().data().customDiagnosticConfigs;
|
data.customDiagnosticConfigs = ClangdSettings::instance().data().customDiagnosticConfigs;
|
||||||
|
}
|
||||||
|
if (m_blockIndexing)
|
||||||
|
data.indexingPriority = ClangdSettings::IndexingPriority::Off;
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -470,12 +473,31 @@ void ClangdProjectSettings::setDiagnosticConfigId(Utils::Id configId)
|
|||||||
saveSettings();
|
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()
|
void ClangdProjectSettings::loadSettings()
|
||||||
{
|
{
|
||||||
if (!m_project)
|
if (!m_project)
|
||||||
return;
|
return;
|
||||||
const QVariantMap data = m_project->namedSettings(clangdSettingsKey()).toMap();
|
const QVariantMap data = m_project->namedSettings(clangdSettingsKey()).toMap();
|
||||||
m_useGlobalSettings = data.value(clangdUseGlobalSettingsKey(), true).toBool();
|
m_useGlobalSettings = data.value(clangdUseGlobalSettingsKey(), true).toBool();
|
||||||
|
m_blockIndexing = data.value(clangdblockIndexingSettingsKey(), false).toBool();
|
||||||
if (!m_useGlobalSettings)
|
if (!m_useGlobalSettings)
|
||||||
m_customSettings.fromMap(data);
|
m_customSettings.fromMap(data);
|
||||||
}
|
}
|
||||||
@@ -488,6 +510,7 @@ void ClangdProjectSettings::saveSettings()
|
|||||||
if (!m_useGlobalSettings)
|
if (!m_useGlobalSettings)
|
||||||
data = m_customSettings.toMap();
|
data = m_customSettings.toMap();
|
||||||
data.insert(clangdUseGlobalSettingsKey(), m_useGlobalSettings);
|
data.insert(clangdUseGlobalSettingsKey(), m_useGlobalSettings);
|
||||||
|
data.insert(clangdblockIndexingSettingsKey(), m_blockIndexing);
|
||||||
m_project->setNamedSettings(clangdSettingsKey(), data);
|
m_project->setNamedSettings(clangdSettingsKey(), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -190,6 +190,8 @@ public:
|
|||||||
bool useGlobalSettings() const { return m_useGlobalSettings; }
|
bool useGlobalSettings() const { return m_useGlobalSettings; }
|
||||||
void setUseGlobalSettings(bool useGlobal);
|
void setUseGlobalSettings(bool useGlobal);
|
||||||
void setDiagnosticConfigId(Utils::Id configId);
|
void setDiagnosticConfigId(Utils::Id configId);
|
||||||
|
void blockIndexing();
|
||||||
|
void unblockIndexing();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void loadSettings();
|
void loadSettings();
|
||||||
@@ -198,6 +200,7 @@ private:
|
|||||||
ProjectExplorer::Project * const m_project;
|
ProjectExplorer::Project * const m_project;
|
||||||
ClangdSettings::Data m_customSettings;
|
ClangdSettings::Data m_customSettings;
|
||||||
bool m_useGlobalSettings = true;
|
bool m_useGlobalSettings = true;
|
||||||
|
bool m_blockIndexing = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace CppEditor
|
} // namespace CppEditor
|
||||||
|
@@ -47,11 +47,17 @@ void ProgressManager::setClickHandlerForToken(const LanguageServerProtocol::Prog
|
|||||||
m_clickHandlers.insert(token, handler);
|
m_clickHandlers.insert(token, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ProgressManager::setCancelHandlerForToken(const LanguageServerProtocol::ProgressToken &token,
|
||||||
|
const std::function<void ()> &handler)
|
||||||
|
{
|
||||||
|
m_cancelHandlers.insert(token, handler);
|
||||||
|
}
|
||||||
|
|
||||||
void ProgressManager::reset()
|
void ProgressManager::reset()
|
||||||
{
|
{
|
||||||
const QList<ProgressToken> &tokens = m_progress.keys();
|
const QList<ProgressToken> &tokens = m_progress.keys();
|
||||||
for (const ProgressToken &token : tokens)
|
for (const ProgressToken &token : tokens)
|
||||||
endProgress(token);
|
endProgressReport(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProgressManager::isProgressEndMessage(const LanguageServerProtocol::ProgressParams ¶ms)
|
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());
|
const QString title = m_titles.value(token, begin.title());
|
||||||
Core::FutureProgress *progress = Core::ProgressManager::addTask(
|
Core::FutureProgress *progress = Core::ProgressManager::addTask(
|
||||||
interface->future(), title, languageClientProgressId(token));
|
interface->future(), title, languageClientProgressId(token));
|
||||||
progress->setCancelEnabled(false);
|
|
||||||
const std::function<void()> clickHandler = m_clickHandlers.value(token);
|
const std::function<void()> clickHandler = m_clickHandlers.value(token);
|
||||||
if (clickHandler)
|
if (clickHandler)
|
||||||
QObject::connect(progress, &Core::FutureProgress::clicked, clickHandler);
|
QObject::connect(progress, &Core::FutureProgress::clicked, clickHandler);
|
||||||
|
const std::function<void()> cancelHandler = m_cancelHandlers.value(token);
|
||||||
|
if (cancelHandler)
|
||||||
|
QObject::connect(progress, &Core::FutureProgress::canceled, cancelHandler);
|
||||||
|
else
|
||||||
|
progress->setCancelEnabled(false);
|
||||||
m_progress[token] = {progress, interface};
|
m_progress[token] = {progress, interface};
|
||||||
if (LOGPROGRESS().isDebugEnabled())
|
if (LOGPROGRESS().isDebugEnabled())
|
||||||
m_timer[token].start();
|
m_timer[token].start();
|
||||||
@@ -125,10 +135,10 @@ void ProgressManager::endProgress(const ProgressToken &token, const WorkDoneProg
|
|||||||
.toString(Qt::ISODateWithMs));
|
.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);
|
const LanguageClientProgress &progress = m_progress.take(token);
|
||||||
if (progress.futureInterface)
|
if (progress.futureInterface)
|
||||||
|
@@ -31,6 +31,10 @@ public:
|
|||||||
const QString &message);
|
const QString &message);
|
||||||
void setClickHandlerForToken(const LanguageServerProtocol::ProgressToken &token,
|
void setClickHandlerForToken(const LanguageServerProtocol::ProgressToken &token,
|
||||||
const std::function<void()> &handler);
|
const std::function<void()> &handler);
|
||||||
|
void setCancelHandlerForToken(const LanguageServerProtocol::ProgressToken &token,
|
||||||
|
const std::function<void()> &handler);
|
||||||
|
void endProgressReport(const LanguageServerProtocol::ProgressToken &token);
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
static bool isProgressEndMessage(const LanguageServerProtocol::ProgressParams ¶ms);
|
static bool isProgressEndMessage(const LanguageServerProtocol::ProgressParams ¶ms);
|
||||||
@@ -42,7 +46,6 @@ private:
|
|||||||
const LanguageServerProtocol::WorkDoneProgressReport &report);
|
const LanguageServerProtocol::WorkDoneProgressReport &report);
|
||||||
void endProgress(const LanguageServerProtocol::ProgressToken &token,
|
void endProgress(const LanguageServerProtocol::ProgressToken &token,
|
||||||
const LanguageServerProtocol::WorkDoneProgressEnd &end);
|
const LanguageServerProtocol::WorkDoneProgressEnd &end);
|
||||||
void endProgress(const LanguageServerProtocol::ProgressToken &token);
|
|
||||||
|
|
||||||
struct LanguageClientProgress {
|
struct LanguageClientProgress {
|
||||||
QPointer<Core::FutureProgress> progressInterface = nullptr;
|
QPointer<Core::FutureProgress> progressInterface = nullptr;
|
||||||
@@ -53,6 +56,7 @@ private:
|
|||||||
QMap<LanguageServerProtocol::ProgressToken, QString> m_titles;
|
QMap<LanguageServerProtocol::ProgressToken, QString> m_titles;
|
||||||
QMap<LanguageServerProtocol::ProgressToken, QElapsedTimer> m_timer;
|
QMap<LanguageServerProtocol::ProgressToken, QElapsedTimer> m_timer;
|
||||||
QMap<LanguageServerProtocol::ProgressToken, std::function<void()>> m_clickHandlers;
|
QMap<LanguageServerProtocol::ProgressToken, std::function<void()>> m_clickHandlers;
|
||||||
|
QMap<LanguageServerProtocol::ProgressToken, std::function<void()>> m_cancelHandlers;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace LanguageClient
|
} // namespace LanguageClient
|
||||||
|
Reference in New Issue
Block a user