[gnome-builder: 2/4] wip: add messages before init to queue to be flushed after init
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder: 2/4] wip: add messages before init to queue to be flushed after init
- Date: Fri, 19 Feb 2021 19:58:29 +0000 (UTC)
commit d5fb15104244b54cf1ad8c754e9f32d494650808
Author: peter <blackwolf12333 gmail com>
Date: Fri Feb 19 12:42:12 2021 +0100
wip: add messages before init to queue to be flushed after init
src/libide/lsp/ide-lsp-client.c | 110 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 105 insertions(+), 5 deletions(-)
---
diff --git a/src/libide/lsp/ide-lsp-client.c b/src/libide/lsp/ide-lsp-client.c
index cdaf303a8..c028deace 100644
--- a/src/libide/lsp/ide-lsp-client.c
+++ b/src/libide/lsp/ide-lsp-client.c
@@ -41,6 +41,14 @@ typedef struct
GVariant *id;
} AsyncCall;
+typedef struct
+{
+ IdeTask *task;
+ const gchar *method;
+ GVariant *params;
+ GCancellable *cancellable;
+} LspMessage;
+
typedef struct
{
DzlSignalGroup *buffer_manager_signals;
@@ -53,6 +61,7 @@ typedef struct
IdeLspTrace trace;
gchar *root_uri;
gboolean initialized;
+ GQueue *pending_messages;
} IdeLspClientPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (IdeLspClient, ide_lsp_client, IDE_TYPE_OBJECT)
@@ -123,6 +132,37 @@ async_call_unref (gpointer data)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (AsyncCall, async_call_unref);
+static LspMessage *
+lsp_message_new (IdeTask *task,
+ const gchar *method,
+ GVariant *params,
+ GCancellable *cancellable)
+{
+ LspMessage *lm = g_atomic_rc_box_new0 (LspMessage);
+ lm->task = g_object_ref (task);
+ lm->method = method;
+ lm->params = g_variant_ref (params);
+ lm->cancellable = g_object_ref (cancellable);
+ return lm;
+}
+
+static void
+lsp_message_finalize (gpointer data)
+{
+ LspMessage *lm = data;
+ g_clear_object (&lm->task);
+ g_clear_pointer (&lm->params, g_variant_unref);
+ g_clear_pointer (&lm->cancellable, g_object_unref);
+}
+
+static void
+lsp_message_unref (gpointer data)
+{
+ g_atomic_rc_box_release_full (data, lsp_message_finalize);
+}
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (LspMessage, lsp_message_unref);
+
static gboolean
ide_lsp_client_supports_buffer (IdeLspClient *self,
IdeBuffer *buffer)
@@ -1041,6 +1081,7 @@ ide_lsp_client_finalize (GObject *object)
g_clear_object (&priv->rpc_client);
g_clear_object (&priv->buffer_manager_signals);
g_clear_object (&priv->project_signals);
+ g_clear_object (&priv->pending_messages);
G_OBJECT_CLASS (ide_lsp_client_parent_class)->finalize (object);
}
@@ -1295,6 +1336,53 @@ ide_lsp_client_init (IdeLspClient *self)
G_CONNECT_SWAPPED);
}
+static void
+ide_lsp_client_call_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data);
+
+static void
+ide_lsp_client_flush_queue (IdeLspClient *self)
+{
+ IdeLspClientPrivate *priv = ide_lsp_client_get_instance_private (self);
+ guint queue_length;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (IDE_IS_LSP_CLIENT (self));
+ g_return_if_fail (!priv->rpc_client || JSONRPC_IS_CLIENT (priv->rpc_client));
+
+ queue_length = g_queue_get_length (priv->pending_messages);
+
+ if (queue_length > 0)
+ {
+ g_autoptr (LspMessage) message;
+
+ while (NULL != (message = g_queue_pop_head (priv->pending_messages)))
+ {
+ g_return_if_fail (message->method != NULL);
+ g_return_if_fail (!message->cancellable || G_IS_CANCELLABLE (message->cancellable));
+
+ if (priv->rpc_client == NULL)
+ ide_task_return_new_error (message->task,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_CONNECTED,
+ "No connection to language server");
+
+ jsonrpc_client_call_async (priv->rpc_client,
+ message->method,
+ message->params,
+ message->cancellable,
+ ide_lsp_client_call_cb,
+ g_steal_pointer (&message->task));
+ }
+ }
+ IDE_TRACE_MSG ("LSP processed build up queue of length: %d", queue_length);
+
+ IDE_EXIT;
+}
+
static void
ide_lsp_client_initialized_cb (GObject *object,
GAsyncResult *result,
@@ -1307,6 +1395,7 @@ ide_lsp_client_initialized_cb (GObject *object,
IdeBufferManager *buffer_manager;
IdeProject *project;
IdeContext *context;
+ guint queue_length;
IDE_ENTRY;
@@ -1330,6 +1419,13 @@ ide_lsp_client_initialized_cb (GObject *object,
g_signal_emit (self, signals[INITIALIZED], 0);
+ queue_length = g_queue_get_length (priv->pending_messages);
+
+ if (queue_length > 0)
+ {
+ ide_lsp_client_flush_queue (self);
+ }
+
IDE_EXIT;
}
@@ -1415,6 +1511,7 @@ ide_lsp_client_start (IdeLspClient *self)
}
priv->rpc_client = jsonrpc_client_new (priv->io_stream);
+ priv->pending_messages = g_queue_new();
workdir = ide_context_ref_workdir (context);
root_path = g_file_get_path (workdir);
@@ -1678,6 +1775,7 @@ ide_lsp_client_call_async (IdeLspClient *self,
{
IdeLspClientPrivate *priv = ide_lsp_client_get_instance_private (self);
g_autoptr(IdeTask) task = NULL;
+ g_autoptr(LspMessage) message = NULL;
IDE_ENTRY;
@@ -1695,11 +1793,13 @@ ide_lsp_client_call_async (IdeLspClient *self,
G_IO_ERROR,
G_IO_ERROR_NOT_CONNECTED,
"No connection to language server");
- else if (!priv->initialized)
- ide_task_return_new_error (task,
- G_IO_ERROR,
- G_IO_ERROR_NOT_CONNECTED,
- "Server is not ready yet");
+ else if (!priv->initialized && !(g_str_equal(method, "initialize") || g_str_equal (method, "initialized")))
+ {
+ IDE_TRACE_MSG("queueing up method: %s", method);
+ message = lsp_message_new(g_steal_pointer(&task), method, params, g_steal_pointer (&cancellable));
+
+ g_queue_push_head(priv->pending_messages, g_steal_pointer (&message));
+ }
else
jsonrpc_client_call_async (priv->rpc_client,
method,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]