aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/languageclient/lualanguageclient
diff options
context:
space:
mode:
authorMarcus Tillmanns <[email protected]>2024-07-22 16:32:38 +0200
committerMarcus Tillmanns <[email protected]>2024-07-24 10:44:10 +0000
commit05b1d9cf68d385d23f9b2a38d213041882d14c8c (patch)
tree40df5e1505169c0431572e9b6c7996db04f095d7 /src/plugins/languageclient/lualanguageclient
parentdf583b2cd07f114bf91693862bedb522b051a732 (diff)
LuaLSP: Make init Options dynamic
Allows a LSP plugin to dynamically configure the initializationOptions Change-Id: Idc5d6526a732512b2e4e7394fb1c8b5749cde25d Reviewed-by: Christian Stenger <[email protected]>
Diffstat (limited to 'src/plugins/languageclient/lualanguageclient')
-rw-r--r--src/plugins/languageclient/lualanguageclient/lualanguageclient.cpp72
1 files changed, 54 insertions, 18 deletions
diff --git a/src/plugins/languageclient/lualanguageclient/lualanguageclient.cpp b/src/plugins/languageclient/lualanguageclient/lualanguageclient.cpp
index 2898e835e9a..faef1f0bf59 100644
--- a/src/plugins/languageclient/lualanguageclient/lualanguageclient.cpp
+++ b/src/plugins/languageclient/lualanguageclient/lualanguageclient.cpp
@@ -177,8 +177,10 @@ class LuaClientWrapper;
class LuaClientSettings : public BaseSettings
{
std::weak_ptr<LuaClientWrapper> m_wrapper;
+ QObject guard;
public:
+ LuaClientSettings(const LuaClientSettings &wrapper);
LuaClientSettings(const std::weak_ptr<LuaClientWrapper> &wrapper);
~LuaClientSettings() override = default;
@@ -200,9 +202,11 @@ enum class TransportType { StdIO, LocalSocket };
class LuaClientWrapper : public QObject
{
+ Q_OBJECT
public:
TransportType m_transportType{TransportType::StdIO};
std::function<expected_str<void>(CommandLine &)> m_cmdLineCallback;
+ std::function<expected_str<void>(QString &)> m_initOptionsCallback;
AspectContainer *m_aspects{nullptr};
QString m_name;
Utils::Id m_settingsTypeId;
@@ -242,6 +246,23 @@ public:
return cmdFromTable(res.get<sol::table>());
});
+ m_initOptionsCallback = addValue<QString>(
+ options,
+ "initializationOptions",
+ m_initializationOptions,
+ [](const sol::protected_function_result &res) -> expected_str<QString> {
+ if (res.get_type(0) == sol::type::table)
+ return ::Lua::LuaEngine::toJsonString(res.get<sol::table>());
+ else if (res.get_type(0) == sol::type::string)
+ return res.get<QString>(0);
+ return make_unexpected(QString("init callback did not return a table or string"));
+ });
+
+ if (auto initOptionsTable = options.get<sol::optional<sol::table>>("initializationOptions"))
+ m_initializationOptions = ::Lua::LuaEngine::toJsonString(*initOptionsTable);
+ else if (auto initOptionsString = options.get<sol::optional<QString>>("initializationOptions"))
+ m_initializationOptions = *initOptionsString;
+
m_name = options.get<QString>("name");
m_settingsTypeId = Utils::Id::fromString(QString("Lua_%1").arg(m_name));
m_serverName = options.get_or<QString>("serverName", "");
@@ -273,22 +294,6 @@ public:
m_languageFilter.mimeTypes.push_back(v.as<QString>());
}
- auto initOptionsTable = options.get<sol::optional<sol::table>>("initializationOptions");
- if (initOptionsTable) {
- QJsonValue json = ::Lua::LuaEngine::toJson(*initOptionsTable);
- QJsonDocument doc;
- if (json.isArray()) {
- doc.setArray(json.toArray());
- m_initializationOptions = QString::fromUtf8(doc.toJson());
- } else if (json.isObject()) {
- doc.setObject(json.toObject());
- m_initializationOptions = QString::fromUtf8(doc.toJson());
- }
- }
- auto initOptionsString = options.get<sol::optional<QString>>("initializationOptions");
- if (initOptionsString)
- m_initializationOptions = *initOptionsString;
-
// get<sol::optional<>> because on MSVC, get_or(..., nullptr) fails to compile
m_aspects = options.get<sol::optional<AspectContainer *>>("settings").value_or(nullptr);
@@ -461,6 +466,16 @@ public:
if (!result)
qWarning() << "Error applying option callback:" << result.error();
}
+ if (m_initOptionsCallback) {
+ expected_str<void> result = m_initOptionsCallback(m_initializationOptions);
+ if (!result)
+ qWarning() << "Error applying init option callback:" << result.error();
+
+ // Right now there is only one option that needs to be mirrored to the LSP Settings,
+ // so we only emit optionsChanged() here. If another setting should need to be dynamic
+ // optionsChanged() needs to be called for it as well, but only once per updateOptions()
+ emit optionsChanged();
+ }
}
static CommandLine cmdFromTable(const sol::table &tbl)
@@ -528,8 +543,23 @@ public:
}
return nullptr;
}
+
+signals:
+ void optionsChanged();
};
+LuaClientSettings::LuaClientSettings(const LuaClientSettings &other)
+ : BaseSettings::BaseSettings(other)
+ , m_wrapper(other.m_wrapper)
+{
+ if (auto w = m_wrapper.lock()) {
+ QObject::connect(w.get(), &LuaClientWrapper::optionsChanged, &guard, [this] {
+ if (auto w = m_wrapper.lock())
+ m_initializationOptions = w->m_initializationOptions;
+ });
+ }
+}
+
LuaClientSettings::LuaClientSettings(const std::weak_ptr<LuaClientWrapper> &wrapper)
: m_wrapper(wrapper)
{
@@ -539,6 +569,10 @@ LuaClientSettings::LuaClientSettings(const std::weak_ptr<LuaClientWrapper> &wrap
m_languageFilter = w->m_languageFilter;
m_initializationOptions = w->m_initializationOptions;
m_startBehavior = w->m_startBehavior;
+ QObject::connect(w.get(), &LuaClientWrapper::optionsChanged, &guard, [this] {
+ if (auto w = m_wrapper.lock())
+ m_initializationOptions = w->m_initializationOptions;
+ });
}
}
@@ -548,7 +582,8 @@ bool LuaClientSettings::applyFromSettingsWidget(QWidget *widget)
if (auto w = m_wrapper.lock()) {
w->m_name = m_name;
- w->m_initializationOptions = m_initializationOptions;
+ if (!w->m_initOptionsCallback)
+ w->m_initializationOptions = m_initializationOptions;
w->m_languageFilter = m_languageFilter;
w->m_startBehavior = m_startBehavior;
w->applySettings();
@@ -570,7 +605,8 @@ void LuaClientSettings::fromMap(const Utils::Store &map)
BaseSettings::fromMap(map);
if (auto w = m_wrapper.lock()) {
w->m_name = m_name;
- w->m_initializationOptions = m_initializationOptions;
+ if (!w->m_initOptionsCallback)
+ w->m_initializationOptions = m_initializationOptions;
w->m_languageFilter = m_languageFilter;
w->m_startBehavior = m_startBehavior;
w->fromMap(map);