LUA: Client and Utils bindings update

Change-Id: Icad01906aa9f9405004ce342399fcb42354e77df
Reviewed-by: Marcus Tillmanns <marcus.tillmanns@qt.io>
Reviewed-by: <mua@spyro-soft.com>
This commit is contained in:
Lukasz Papierkowski
2024-07-19 11:44:26 +02:00
committed by lie
parent a858e305d5
commit f4d8eaca00
4 changed files with 126 additions and 40 deletions

View File

@@ -26,6 +26,43 @@ using namespace Core;
using namespace TextEditor; using namespace TextEditor;
using namespace ProjectExplorer; using namespace ProjectExplorer;
namespace {
class RequestWithResponse : public LanguageServerProtocol::JsonRpcMessage
{
sol::function m_callback;
LanguageServerProtocol::MessageId m_id;
public:
RequestWithResponse(const QJsonObject &obj, const sol::function &cb)
: LanguageServerProtocol::JsonRpcMessage(obj)
, m_callback(cb)
{
m_id = LanguageServerProtocol::MessageId(obj["id"]);
}
std::optional<LanguageServerProtocol::ResponseHandler> responseHandler() const override
{
if (!m_id.isValid())
qWarning() << "Invalid 'id' in request:" << toJsonObject();
return std::nullopt;
return LanguageServerProtocol::ResponseHandler{
m_id, [callback = m_callback](const JsonRpcMessage &msg) {
if (!callback.valid()) {
qWarning() << "Invalid Lua callback";
return;
}
auto result = ::Lua::LuaEngine::void_safe_call(
callback, ::Lua::LuaEngine::toTable(callback.lua_state(), msg.toJsonObject()));
QTC_CHECK_EXPECTED(result);
}};
}
};
} // anonymous namespace
namespace LanguageClient::Lua { namespace LanguageClient::Lua {
static void registerLuaApi(); static void registerLuaApi();
@@ -73,14 +110,16 @@ public:
} }
m_process = new Process; m_process = new Process;
m_process->setProcessMode(ProcessMode::Writer); m_process->setProcessMode(ProcessMode::Writer);
connect(m_process, connect(
&Process::readyReadStandardError, m_process,
this, &Process::readyReadStandardError,
&LuaLocalSocketClientInterface::readError); this,
connect(m_process, &LuaLocalSocketClientInterface::readError);
&Process::readyReadStandardOutput, connect(
this, m_process,
&LuaLocalSocketClientInterface::readOutput); &Process::readyReadStandardOutput,
this,
&LuaLocalSocketClientInterface::readOutput);
connect(m_process, &Process::started, this, [this]() { connect(m_process, &Process::started, this, [this]() {
this->LocalSocketClientInterface::startImpl(); this->LocalSocketClientInterface::startImpl();
emit started(); emit started();
@@ -348,15 +387,24 @@ public:
} }
} }
void sendMessage(const sol::table &message) void sendMessage(const sol::table &message, const sol::function &callback)
{ {
const QJsonValue messageValue = ::Lua::LuaEngine::toJson(message); const QJsonValue messageValue = ::Lua::LuaEngine::toJson(message);
if (!messageValue.isObject()) if (!messageValue.isObject())
throw sol::error("Message is not an object"); throw sol::error("Message is not an object");
const LanguageServerProtocol::JsonRpcMessage jsonrpcmessage(messageValue.toObject());
auto make_request = [&]() -> std::unique_ptr<LanguageServerProtocol::JsonRpcMessage> {
if (callback.valid()) {
return std::make_unique<RequestWithResponse>(messageValue.toObject(), callback);
}
return std::make_unique<LanguageServerProtocol::JsonRpcMessage>(messageValue.toObject());
};
auto const request = make_request();
for (Client *c : LanguageClientManager::clientsForSettingId(m_settingsTypeId.toString())) { for (Client *c : LanguageClientManager::clientsForSettingId(m_settingsTypeId.toString())) {
if (c) if (c)
c->sendMessage(jsonrpcmessage); c->sendMessage(*request);
} }
} }
@@ -545,6 +593,27 @@ static void registerLuaApi()
LanguageClientSettings::registerClientType(type); LanguageClientSettings::registerClientType(type);
return luaClient; return luaClient;
},
"documentVersion",
[](const Utils::FilePath &path) -> int {
auto client = LanguageClientManager::clientForFilePath(path);
if (!client) {
qWarning() << "documentVersion(). No client for file path:" << path;
return -1;
}
return client->documentVersion(path);
},
"hostPathToServerUri",
[](const Utils::FilePath &path) -> QString {
auto client = LanguageClientManager::clientForFilePath(path);
if (!client) {
qWarning() << "hostPathToServerUri(). No client for file path:" << path;
return {};
}
return client->hostPathToServerUri(path).toString();
}); });
return result; return result;

View File

@@ -9,6 +9,7 @@
#include <utils/hostosinfo.h> #include <utils/hostosinfo.h>
#include <QTimer> #include <QTimer>
#include <QUuid>
using namespace Utils; using namespace Utils;
@@ -25,41 +26,43 @@ void addUtilsModule()
sol::table utils = lua.create_table(); sol::table utils = lua.create_table();
utils.set_function("waitms_cb", [guard = pluginSpec->connectionGuard.get()](int ms, const sol::function &cb) { utils.set_function(
QTimer::singleShot(ms, guard, [cb]() { cb(); }); "waitms_cb",
}); [guard = pluginSpec->connectionGuard.get()](int ms, const sol::function &cb) {
QTimer::singleShot(ms, guard, [cb]() { cb(); });
});
auto dirEntries_cb = auto dirEntries_cb = [&futureSync, guard = pluginSpec->connectionGuard.get()](
[&futureSync, guard = pluginSpec->connectionGuard.get()]( const FilePath &p,
const FilePath &p, const sol::table &options, const sol::function &cb) { const sol::table &options,
const QStringList nameFilters = options.get_or<QStringList>("nameFilters", {}); const sol::function &cb) {
QDir::Filters fileFilters const QStringList nameFilters = options.get_or<QStringList>("nameFilters", {});
= (QDir::Filters) options.get_or<int>("fileFilters", QDir::NoFilter); QDir::Filters fileFilters
QDirIterator::IteratorFlags flags = (QDir::Filters) options.get_or<int>("fileFilters", QDir::NoFilter);
= (QDirIterator::IteratorFlags) QDirIterator::IteratorFlags flags
options.get_or<int>("flags", QDirIterator::NoIteratorFlags); = (QDirIterator::IteratorFlags)
options.get_or<int>("flags", QDirIterator::NoIteratorFlags);
FileFilter filter(nameFilters, fileFilters, flags); FileFilter filter(nameFilters, fileFilters, flags);
QFuture<FilePath> future = Utils::asyncRun( QFuture<FilePath> future = Utils::asyncRun([p, filter](QPromise<FilePath> &promise) {
[p, filter](QPromise<FilePath> &promise) { p.iterateDirectory(
p.iterateDirectory( [&promise](const FilePath &item) {
[&promise](const FilePath &item) { if (promise.isCanceled())
if (promise.isCanceled()) return IterationPolicy::Stop;
return IterationPolicy::Stop;
promise.addResult(item); promise.addResult(item);
return IterationPolicy::Continue; return IterationPolicy::Continue;
}, },
filter); filter);
}); });
futureSync.addFuture<FilePath>(future); futureSync.addFuture<FilePath>(future);
Utils::onFinished<FilePath>(future, guard, [cb](const QFuture<FilePath> &future) { Utils::onFinished<FilePath>(future, guard, [cb](const QFuture<FilePath> &future) {
cb(future.results()); cb(future.results());
}); });
}; };
auto searchInPath_cb = [&futureSync, auto searchInPath_cb = [&futureSync,
guard = pluginSpec->connectionGuard guard = pluginSpec->connectionGuard
@@ -77,6 +80,8 @@ void addUtilsModule()
utils.set_function("__dirEntries_cb__", dirEntries_cb); utils.set_function("__dirEntries_cb__", dirEntries_cb);
utils.set_function("__searchInPath_cb__", searchInPath_cb); utils.set_function("__searchInPath_cb__", searchInPath_cb);
utils.set_function("createUuid", []() { return QUuid::createUuid().toString(); });
sol::function wrap = async["wrap"].get<sol::function>(); sol::function wrap = async["wrap"].get<sol::function>();
utils["waitms"] = wrap(utils["waitms_cb"]); utils["waitms"] = wrap(utils["waitms_cb"]);

View File

@@ -32,6 +32,14 @@ function lsp.Client:registerMessage(msg, callback) end
---Sends a message to the language server. ---Sends a message to the language server.
function lsp.Client:sendMessage(msg, callback) end function lsp.Client:sendMessage(msg, callback) end
---@param filePath FilePath to get the version of.
---@return int Returns -1 on error, otherwise current document version.
function lsp.Client:documentVersion(filePath) end
---
---@param filePath table file path to get the uri of.
---@return QString Returns empty string on error, otherwise the server URI string.
function lsp.Client:hostPathToServerUri(filePath) end
---Creates a new Language Client. ---Creates a new Language Client.
---@param options ClientOptions ---@param options ClientOptions
---@return Client ---@return Client

View File

@@ -14,6 +14,10 @@ function utils.waitms(ms) end
---@param callback function The callback to call. ---@param callback function The callback to call.
function utils.waitms_cb(ms, callback) end function utils.waitms_cb(ms, callback) end
---Creates a UUID.
---@return QString Arbitrary UUID string.
function utils.createUuid() end
---@class FilePath ---@class FilePath
utils.FilePath = {} utils.FilePath = {}