[gnome-builder] lsp: Apply additionalTextEdits for completions



commit 82633778afb42b1e6a43bdd2a06a809c7c406ab0
Author: Tom A. Wagner <tom a wagner protonmail com>
Date:   Tue Aug 10 22:04:34 2021 +0200

    lsp: Apply additionalTextEdits for completions

 src/libide/lsp/ide-lsp-completion-item.c     | 44 +++++++++++++++++++++++
 src/libide/lsp/ide-lsp-completion-item.h     | 18 ++++++----
 src/libide/lsp/ide-lsp-completion-provider.c | 52 +++++++++++++++++++++++++---
 3 files changed, 102 insertions(+), 12 deletions(-)
---
diff --git a/src/libide/lsp/ide-lsp-completion-item.c b/src/libide/lsp/ide-lsp-completion-item.c
index 10aaf7678..271ca9579 100644
--- a/src/libide/lsp/ide-lsp-completion-item.c
+++ b/src/libide/lsp/ide-lsp-completion-item.c
@@ -182,3 +182,47 @@ ide_lsp_completion_item_get_snippet (IdeLspCompletionItem *self)
 
   return g_steal_pointer (&snippet);
 }
+
+
+/**
+ * ide_lsp_completion_item_get_additional_text_edits:
+ * @self: a #IdeLspCompletionItem
+ * @file: The file the completion is applied to
+ *
+ * Obtain an array of all additional text edits to be applied to the project.
+ *
+ * Returns: (transfer full) (element-type IdeTextEdit) (nullable): a #GPtrArray of #IdeTextEdit
+ *
+ * Since: 41
+ */
+GPtrArray *
+ide_lsp_completion_item_get_additional_text_edits(IdeLspCompletionItem *self,
+                                                  GFile                *file)
+{
+  g_autoptr(GPtrArray) result = NULL;
+  g_autoptr(GVariantIter) text_edit_iter = NULL;
+  GVariant *text_edit;
+
+  g_return_val_if_fail (IDE_IS_LSP_COMPLETION_ITEM (self), NULL);
+
+  if (!JSONRPC_MESSAGE_PARSE (self->variant, "additionalTextEdits" , JSONRPC_MESSAGE_GET_ITER 
(&text_edit_iter)))
+    return NULL;
+
+  result = g_ptr_array_new_with_free_func (g_object_unref);
+
+  while (g_variant_iter_loop (text_edit_iter, "v", &text_edit))
+    {
+      IdeTextEdit *edit = ide_lsp_decode_text_edit (text_edit, file);
+
+      if (edit != NULL)
+        {
+          g_ptr_array_add (result, edit);
+        }
+      else
+        {
+          g_warning ("Additional text edit could not be parsed: %s", g_variant_print (text_edit, TRUE));
+        }
+    }
+
+  return g_steal_pointer (&result);
+}
diff --git a/src/libide/lsp/ide-lsp-completion-item.h b/src/libide/lsp/ide-lsp-completion-item.h
index 3bf86a052..bb325a053 100644
--- a/src/libide/lsp/ide-lsp-completion-item.h
+++ b/src/libide/lsp/ide-lsp-completion-item.h
@@ -34,17 +34,21 @@ IDE_AVAILABLE_IN_3_32
 G_DECLARE_FINAL_TYPE (IdeLspCompletionItem, ide_lsp_completion_item, IDE, LSP_COMPLETION_ITEM, GObject)
 
 IDE_AVAILABLE_IN_3_32
-IdeLspCompletionItem *ide_lsp_completion_item_new             (GVariant             *variant);
+IdeLspCompletionItem *ide_lsp_completion_item_new                       (GVariant             *variant);
 IDE_AVAILABLE_IN_3_32
-const gchar          *ide_lsp_completion_item_get_icon_name   (IdeLspCompletionItem *self);
+const gchar          *ide_lsp_completion_item_get_icon_name             (IdeLspCompletionItem *self);
 IDE_AVAILABLE_IN_3_32
-const gchar          *ide_lsp_completion_item_get_return_type (IdeLspCompletionItem *self);
+const gchar          *ide_lsp_completion_item_get_return_type           (IdeLspCompletionItem *self);
 IDE_AVAILABLE_IN_3_32
-const gchar          *ide_lsp_completion_item_get_detail      (IdeLspCompletionItem *self);
+const gchar          *ide_lsp_completion_item_get_detail                (IdeLspCompletionItem *self);
 IDE_AVAILABLE_IN_3_32
-gchar                *ide_lsp_completion_item_get_markup      (IdeLspCompletionItem *self,
-                                                               const gchar          *typed_text);
+gchar                *ide_lsp_completion_item_get_markup                (IdeLspCompletionItem *self,
+                                                                         const gchar          *typed_text);
 IDE_AVAILABLE_IN_3_32
-IdeSnippet           *ide_lsp_completion_item_get_snippet     (IdeLspCompletionItem *self);
+IdeSnippet           *ide_lsp_completion_item_get_snippet               (IdeLspCompletionItem *self);
+
+IDE_AVAILABLE_IN_41
+GPtrArray            *ide_lsp_completion_item_get_additional_text_edits (IdeLspCompletionItem *self,
+                                                                         GFile                *file);
 
 G_END_DECLS
diff --git a/src/libide/lsp/ide-lsp-completion-provider.c b/src/libide/lsp/ide-lsp-completion-provider.c
index 6ddb7e586..c908000b7 100644
--- a/src/libide/lsp/ide-lsp-completion-provider.c
+++ b/src/libide/lsp/ide-lsp-completion-provider.c
@@ -385,9 +385,26 @@ ide_lsp_completion_provider_display_proposal (IdeCompletionProvider   *provider,
   ide_completion_list_box_row_set_right (row, NULL);
 }
 
+static void
+ide_lsp_client_apply_additional_edits_cb (GObject      *object,
+                                          GAsyncResult *result,
+                                          gpointer      user_data)
+{
+  IdeBufferManager *bufmgr = (IdeBufferManager *)object;
+  g_autoptr(GError) error = NULL;
+
+  g_assert (IDE_IS_BUFFER_MANAGER (bufmgr));
+  g_assert (G_IS_ASYNC_RESULT (result));
+
+  if (!ide_buffer_manager_apply_edits_finish (bufmgr, result, &error))
+    {
+      g_warning ("Failed to apply additional text edits for completion: %s", error->message);
+    }
+}
+
 static void
 ide_lsp_completion_provider_activate_proposal (IdeCompletionProvider *provider,
-                                               IdeCompletionContext  *context,
+                                               IdeCompletionContext  *completion_context,
                                                IdeCompletionProposal *proposal,
                                                const GdkEventKey     *key)
 {
@@ -395,21 +412,46 @@ ide_lsp_completion_provider_activate_proposal (IdeCompletionProvider *provider,
   GtkTextBuffer *buffer;
   GtkTextView *view;
   GtkTextIter begin, end;
+  IdeContext *context;
+  g_autoptr(GPtrArray) additional_text_edits;
+  IdeBufferManager *buffer_manager;
 
   g_assert (IDE_IS_COMPLETION_PROVIDER (provider));
-  g_assert (IDE_IS_COMPLETION_CONTEXT (context));
+  g_assert (IDE_IS_COMPLETION_CONTEXT (completion_context));
   g_assert (IDE_IS_LSP_COMPLETION_ITEM (proposal));
 
-  buffer = ide_completion_context_get_buffer (context);
-  view = ide_completion_context_get_view (context);
+  buffer = ide_completion_context_get_buffer (completion_context);
+
+  g_assert (IDE_IS_BUFFER (buffer));
+
+  view = ide_completion_context_get_view (completion_context);
 
   snippet = ide_lsp_completion_item_get_snippet (IDE_LSP_COMPLETION_ITEM (proposal));
 
   gtk_text_buffer_begin_user_action (buffer);
-  if (ide_completion_context_get_bounds (context, &begin, &end))
+  if (ide_completion_context_get_bounds (completion_context, &begin, &end))
     gtk_text_buffer_delete (buffer, &begin, &end);
   ide_source_view_push_snippet (IDE_SOURCE_VIEW (view), snippet, &begin);
   gtk_text_buffer_end_user_action (buffer);
+
+  additional_text_edits =
+    ide_lsp_completion_item_get_additional_text_edits (IDE_LSP_COMPLETION_ITEM (proposal),
+                                                       ide_buffer_get_file (IDE_BUFFER (buffer)));
+
+  if (additional_text_edits != NULL)
+    {
+      context = ide_object_get_context (IDE_OBJECT (provider));
+
+      g_return_if_fail (context != NULL);
+
+      buffer_manager = ide_buffer_manager_from_context (context);
+
+      ide_buffer_manager_apply_edits_async (buffer_manager,
+                                            IDE_PTR_ARRAY_STEAL_FULL (&additional_text_edits),
+                                            NULL,
+                                            ide_lsp_client_apply_additional_edits_cb,
+                                            NULL);
+    }
 }
 
 static gchar *


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]