Clangd: Handle settings changes

Users no longer have to re-load a project for settings changes to take
effect.

Change-Id: I86dccccac14a30514c8dac292c7765ee4806f6ba
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
Christian Kandeler
2021-07-01 04:17:54 +02:00
parent b52f2d198a
commit f4a3310059
8 changed files with 66 additions and 31 deletions

View File

@@ -33,7 +33,6 @@
#include <coreplugin/find/searchresultitem.h> #include <coreplugin/find/searchresultitem.h>
#include <coreplugin/find/searchresultwindow.h> #include <coreplugin/find/searchresultwindow.h>
#include <cplusplus/FindUsages.h> #include <cplusplus/FindUsages.h>
#include <cpptools/cppcodemodelsettings.h>
#include <cpptools/cppeditorwidgetinterface.h> #include <cpptools/cppeditorwidgetinterface.h>
#include <cpptools/cppfindreferences.h> #include <cpptools/cppfindreferences.h>
#include <cpptools/cpptoolsreuse.h> #include <cpptools/cpptoolsreuse.h>
@@ -419,7 +418,7 @@ public:
static BaseClientInterface *clientInterface(Project *project, const Utils::FilePath &jsonDbDir) static BaseClientInterface *clientInterface(Project *project, const Utils::FilePath &jsonDbDir)
{ {
QString indexingOption = "--background-index"; QString indexingOption = "--background-index";
const CppTools::ClangdSettings settings = CppTools::ClangdProjectSettings(project).settings(); const CppTools::ClangdSettings settings(CppTools::ClangdProjectSettings(project).settings());
if (!settings.indexingEnabled()) if (!settings.indexingEnabled())
indexingOption += "=0"; indexingOption += "=0";
Utils::CommandLine cmd{settings.clangdFilePath(), {indexingOption, "--limit-results=0"}}; Utils::CommandLine cmd{settings.clangdFilePath(), {indexingOption, "--limit-results=0"}};
@@ -661,7 +660,8 @@ public:
class ClangdClient::Private class ClangdClient::Private
{ {
public: public:
Private(ClangdClient *q) : q(q) {} Private(ClangdClient *q, Project *project)
: q(q), settings(CppTools::ClangdProjectSettings(project).settings()) {}
void handleFindUsagesResult(quint64 key, const QList<Location> &locations); void handleFindUsagesResult(quint64 key, const QList<Location> &locations);
static void handleRenameRequest(const SearchResult *search, static void handleRenameRequest(const SearchResult *search,
@@ -689,6 +689,7 @@ public:
const QString &type = {}); const QString &type = {});
ClangdClient * const q; ClangdClient * const q;
const CppTools::ClangdSettings::Data settings;
QHash<quint64, ReferencesData> runningFindUsages; QHash<quint64, ReferencesData> runningFindUsages;
Utils::optional<FollowSymbolData> followSymbolData; Utils::optional<FollowSymbolData> followSymbolData;
Utils::optional<SwitchDeclDefData> switchDeclDefData; Utils::optional<SwitchDeclDefData> switchDeclDefData;
@@ -700,7 +701,7 @@ public:
}; };
ClangdClient::ClangdClient(Project *project, const Utils::FilePath &jsonDbDir) ClangdClient::ClangdClient(Project *project, const Utils::FilePath &jsonDbDir)
: Client(clientInterface(project, jsonDbDir)), d(new Private(this)) : Client(clientInterface(project, jsonDbDir)), d(new Private(this, project))
{ {
setName(tr("clangd")); setName(tr("clangd"));
LanguageFilter langFilter; LanguageFilter langFilter;
@@ -900,6 +901,8 @@ QVersionNumber ClangdClient::versionNumber() const
return d->versionNumber.value(); return d->versionNumber.value();
} }
CppTools::ClangdSettings::Data ClangdClient::settingsData() const { return d->settings; }
void ClangdClient::Private::handleFindUsagesResult(quint64 key, const QList<Location> &locations) void ClangdClient::Private::handleFindUsagesResult(quint64 key, const QList<Location> &locations)
{ {
const auto refData = runningFindUsages.find(key); const auto refData = runningFindUsages.find(key);

View File

@@ -25,6 +25,7 @@
#pragma once #pragma once
#include <cpptools/cppcodemodelsettings.h>
#include <cpptools/refactoringengineinterface.h> #include <cpptools/refactoringengineinterface.h>
#include <languageclient/client.h> #include <languageclient/client.h>
#include <utils/link.h> #include <utils/link.h>
@@ -49,6 +50,7 @@ public:
bool isFullyIndexed() const; bool isFullyIndexed() const;
QVersionNumber versionNumber() const; QVersionNumber versionNumber() const;
CppTools::ClangdSettings::Data settingsData() const;
void openExtraFile(const Utils::FilePath &filePath, const QString &content = {}); void openExtraFile(const Utils::FilePath &filePath, const QString &content = {});
void closeExtraFile(const Utils::FilePath &filePath); void closeExtraFile(const Utils::FilePath &filePath);

View File

@@ -122,6 +122,8 @@ ClangModelManagerSupport::ClangModelManagerSupport()
CppTools::ClangdSettings::setDefaultClangdPath(Utils::FilePath::fromString( CppTools::ClangdSettings::setDefaultClangdPath(Utils::FilePath::fromString(
Core::ICore::clangdExecutable(CLANG_BINDIR))); Core::ICore::clangdExecutable(CLANG_BINDIR)));
connect(&CppTools::ClangdSettings::instance(), &CppTools::ClangdSettings::changed,
this, &ClangModelManagerSupport::onClangdSettingsChanged);
CppTools::CppCodeModelSettings *settings = CppTools::codeModelSettings(); CppTools::CppCodeModelSettings *settings = CppTools::codeModelSettings();
connect(settings, &CppTools::CppCodeModelSettings::clangDiagnosticConfigsInvalidated, connect(settings, &CppTools::CppCodeModelSettings::clangDiagnosticConfigsInvalidated,
this, &ClangModelManagerSupport::onDiagnosticConfigsInvalidated); this, &ClangModelManagerSupport::onDiagnosticConfigsInvalidated);
@@ -247,7 +249,7 @@ void ClangModelManagerSupport::connectToWidgetsMarkContextMenuRequested(QWidget
void ClangModelManagerSupport::updateLanguageClient(ProjectExplorer::Project *project, void ClangModelManagerSupport::updateLanguageClient(ProjectExplorer::Project *project,
const CppTools::ProjectInfo &projectInfo) const CppTools::ProjectInfo &projectInfo)
{ {
if (!CppTools::ClangdProjectSettings(project).settings().useClangd()) if (!CppTools::ClangdProjectSettings(project).settings().useClangd)
return; return;
const auto getJsonDbDir = [project] { const auto getJsonDbDir = [project] {
if (const ProjectExplorer::Target * const target = project->activeTarget()) { if (const ProjectExplorer::Target * const target = project->activeTarget()) {
@@ -268,7 +270,7 @@ void ClangModelManagerSupport::updateLanguageClient(ProjectExplorer::Project *pr
generatorWatcher->deleteLater(); generatorWatcher->deleteLater();
if (!ProjectExplorer::SessionManager::hasProject(project)) if (!ProjectExplorer::SessionManager::hasProject(project))
return; return;
if (!CppTools::ClangdProjectSettings(project).settings().useClangd()) if (!CppTools::ClangdProjectSettings(project).settings().useClangd)
return; return;
if (cppModelManager()->projectInfo(project) != projectInfo) if (cppModelManager()->projectInfo(project) != projectInfo)
return; return;
@@ -288,7 +290,7 @@ void ClangModelManagerSupport::updateLanguageClient(ProjectExplorer::Project *pr
using namespace ProjectExplorer; using namespace ProjectExplorer;
if (!SessionManager::hasProject(project)) if (!SessionManager::hasProject(project))
return; return;
if (!CppTools::ClangdProjectSettings(project).settings().useClangd()) if (!CppTools::ClangdProjectSettings(project).settings().useClangd)
return; return;
if (cppModelManager()->projectInfo(project) != projectInfo) if (cppModelManager()->projectInfo(project) != projectInfo)
return; return;
@@ -587,6 +589,27 @@ void ClangModelManagerSupport::onProjectPartsRemoved(const QStringList &projectP
reinitializeBackendDocuments(projectPartIds); reinitializeBackendDocuments(projectPartIds);
} }
void ClangModelManagerSupport::onClangdSettingsChanged()
{
// TODO: Handle also project-less client
for (ProjectExplorer::Project * const project : ProjectExplorer::SessionManager::projects()) {
const CppTools::ClangdSettings settings(
CppTools::ClangdProjectSettings(project).settings());
ClangdClient * const client = clientForProject(project);
if (!client) {
if (settings.useClangd())
updateLanguageClient(project, cppModelManager()->projectInfo(project));
continue;
}
if (!settings.useClangd()) {
LanguageClientManager::shutdownClient(client);
continue;
}
if (client->settingsData() != settings.data())
updateLanguageClient(project, cppModelManager()->projectInfo(project));
}
}
static ClangEditorDocumentProcessors clangProcessorsWithDiagnosticConfig( static ClangEditorDocumentProcessors clangProcessorsWithDiagnosticConfig(
const QVector<::Utils::Id> &configIds) const QVector<::Utils::Id> &configIds)
{ {

View File

@@ -114,6 +114,7 @@ private:
void onProjectPartsUpdated(ProjectExplorer::Project *project); void onProjectPartsUpdated(ProjectExplorer::Project *project);
void onProjectPartsRemoved(const QStringList &projectPartIds); void onProjectPartsRemoved(const QStringList &projectPartIds);
void onClangdSettingsChanged();
void onDiagnosticConfigsInvalidated(const QVector<::Utils::Id> &configIds); void onDiagnosticConfigsInvalidated(const QVector<::Utils::Id> &configIds);

View File

@@ -303,18 +303,6 @@ void CppCodeModelSettings::setEnableLowerClazyLevels(bool yesno)
} }
static bool operator==(const ClangdSettings::Data &s1, const ClangdSettings::Data &s2)
{
return s1.useClangd == s2.useClangd
&& s1.executableFilePath == s2.executableFilePath
&& s1.workerThreadLimit == s2.workerThreadLimit
&& s1.enableIndexing == s2.enableIndexing;
}
static bool operator!=(const ClangdSettings::Data &s1, const ClangdSettings::Data &s2)
{
return !(s1 == s2);
}
ClangdSettings &ClangdSettings::instance() ClangdSettings &ClangdSettings::instance()
{ {
static ClangdSettings settings; static ClangdSettings settings;
@@ -338,6 +326,7 @@ void ClangdSettings::setData(const Data &data)
if (this == &instance() && data != m_data) { if (this == &instance() && data != m_data) {
m_data = data; m_data = data;
saveSettings(); saveSettings();
emit changed();
} }
} }
@@ -364,23 +353,25 @@ ClangdProjectSettings::ClangdProjectSettings(ProjectExplorer::Project *project)
loadSettings(); loadSettings();
} }
ClangdSettings ClangdProjectSettings::settings() const ClangdSettings::Data ClangdProjectSettings::settings() const
{ {
if (m_useGlobalSettings) if (m_useGlobalSettings)
return ClangdSettings::instance(); return ClangdSettings::instance().data();
return ClangdSettings(m_customSettings); return m_customSettings;
} }
void ClangdProjectSettings::setSettings(const ClangdSettings::Data &data) void ClangdProjectSettings::setSettings(const ClangdSettings::Data &data)
{ {
m_customSettings = data; m_customSettings = data;
saveSettings(); saveSettings();
emit ClangdSettings::instance().changed();
} }
void ClangdProjectSettings::setUseGlobalSettings(bool useGlobal) void ClangdProjectSettings::setUseGlobalSettings(bool useGlobal)
{ {
m_useGlobalSettings = useGlobal; m_useGlobalSettings = useGlobal;
saveSettings(); saveSettings();
emit ClangdSettings::instance().changed();
} }
void ClangdProjectSettings::loadSettings() void ClangdProjectSettings::loadSettings()

View File

@@ -98,10 +98,11 @@ private:
bool m_categorizeFindReferences = false; // Ephemeral! bool m_categorizeFindReferences = false; // Ephemeral!
}; };
class CPPTOOLS_EXPORT ClangdSettings class CPPTOOLS_EXPORT ClangdSettings : public QObject
{ {
Q_OBJECT
public: public:
class Data class CPPTOOLS_EXPORT Data
{ {
public: public:
QVariantMap toMap() const; QVariantMap toMap() const;
@@ -131,6 +132,9 @@ public:
static void setClangdFilePath(const Utils::FilePath &filePath); static void setClangdFilePath(const Utils::FilePath &filePath);
#endif #endif
signals:
void changed();
private: private:
ClangdSettings() { loadSettings(); } ClangdSettings() { loadSettings(); }
@@ -140,12 +144,24 @@ private:
Data m_data; Data m_data;
}; };
inline bool operator==(const ClangdSettings::Data &s1, const ClangdSettings::Data &s2)
{
return s1.useClangd == s2.useClangd
&& s1.executableFilePath == s2.executableFilePath
&& s1.workerThreadLimit == s2.workerThreadLimit
&& s1.enableIndexing == s2.enableIndexing;
}
inline bool operator!=(const ClangdSettings::Data &s1, const ClangdSettings::Data &s2)
{
return !(s1 == s2);
}
class CPPTOOLS_EXPORT ClangdProjectSettings class CPPTOOLS_EXPORT ClangdProjectSettings
{ {
public: public:
ClangdProjectSettings(ProjectExplorer::Project *project); ClangdProjectSettings(ProjectExplorer::Project *project);
ClangdSettings settings() const; ClangdSettings::Data settings() const;
void setSettings(const ClangdSettings::Data &data); void setSettings(const ClangdSettings::Data &data);
bool useGlobalSettings() const { return m_useGlobalSettings; } bool useGlobalSettings() const { return m_useGlobalSettings; }
void setUseGlobalSettings(bool useGlobal); void setUseGlobalSettings(bool useGlobal);

View File

@@ -200,12 +200,12 @@ public:
Utils::PathChooser clangdChooser; Utils::PathChooser clangdChooser;
}; };
ClangdSettingsWidget::ClangdSettingsWidget(const ClangdSettings &settings) : d(new Private) ClangdSettingsWidget::ClangdSettingsWidget(const ClangdSettings::Data &settingsData)
: d(new Private)
{ {
const ClangdSettings settings(settingsData);
d->useClangdCheckBox.setText(tr("Use clangd (EXPERIMENTAL)")); d->useClangdCheckBox.setText(tr("Use clangd (EXPERIMENTAL)"));
d->useClangdCheckBox.setChecked(settings.useClangd()); d->useClangdCheckBox.setChecked(settings.useClangd());
d->useClangdCheckBox.setToolTip(tr("Changing this option does not affect projects "
"that are already open."));
d->clangdChooser.setExpectedKind(Utils::PathChooser::ExistingCommand); d->clangdChooser.setExpectedKind(Utils::PathChooser::ExistingCommand);
d->clangdChooser.setFilePath(settings.clangdFilePath()); d->clangdChooser.setFilePath(settings.clangdFilePath());
d->clangdChooser.setEnabled(d->useClangdCheckBox.isChecked()); d->clangdChooser.setEnabled(d->useClangdCheckBox.isChecked());
@@ -273,9 +273,8 @@ class ClangdSettingsPageWidget final : public Core::IOptionsPageWidget
Q_DECLARE_TR_FUNCTIONS(CppTools::Internal::ClangdSettingsWidget) Q_DECLARE_TR_FUNCTIONS(CppTools::Internal::ClangdSettingsWidget)
public: public:
ClangdSettingsPageWidget() : m_widget(ClangdSettings::instance()) ClangdSettingsPageWidget() : m_widget(ClangdSettings::instance().data())
{ {
const auto layout = new QVBoxLayout(this); const auto layout = new QVBoxLayout(this);
layout->addWidget(&m_widget); layout->addWidget(&m_widget);
} }

View File

@@ -49,7 +49,7 @@ class ClangdSettingsWidget : public QWidget
Q_OBJECT Q_OBJECT
public: public:
ClangdSettingsWidget(const ClangdSettings &settings); ClangdSettingsWidget(const ClangdSettings::Data &settingsData);
~ClangdSettingsWidget(); ~ClangdSettingsWidget();
ClangdSettings::Data settingsData() const; ClangdSettings::Data settingsData() const;