[gnome-builder] lsp: implement workspace edit
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] lsp: implement workspace edit
- Date: Thu, 11 Nov 2021 21:04:23 +0000 (UTC)
commit dacd799593855d3d0b895cab2826142c98d12d33
Author: Georg Vienna <georg vienna himbarsoft com>
Date: Thu Nov 11 15:06:12 2021 +0100
lsp: implement workspace edit
src/libide/lsp/ide-lsp-client.c | 68 +------------
src/libide/lsp/ide-lsp-rename-provider.c | 90 ++---------------
src/libide/lsp/ide-lsp-workspace-edit.c | 163 +++++++++++++++++++++++++++++++
src/libide/lsp/ide-lsp-workspace-edit.h | 42 ++++++++
src/libide/lsp/libide-lsp.h | 1 +
src/libide/lsp/meson.build | 2 +
6 files changed, 218 insertions(+), 148 deletions(-)
---
diff --git a/src/libide/lsp/ide-lsp-client.c b/src/libide/lsp/ide-lsp-client.c
index 0e72fe720..bb09923e1 100644
--- a/src/libide/lsp/ide-lsp-client.c
+++ b/src/libide/lsp/ide-lsp-client.c
@@ -34,6 +34,7 @@
#include "ide-lsp-client.h"
#include "ide-lsp-enums.h"
+#include "ide-lsp-workspace-edit.h"
typedef struct
{
@@ -968,7 +969,7 @@ ide_lsp_client_handle_apply_edit (IdeLspClient *self,
GVariant *params)
{
g_autoptr(GVariant) parent = NULL;
- g_autoptr(GVariant) changes = NULL;
+ g_autoptr(IdeLspWorkspaceEdit) workspace_edit = NULL;
g_autoptr(GPtrArray) edits = NULL;
IDE_ENTRY;
@@ -983,69 +984,8 @@ ide_lsp_client_handle_apply_edit (IdeLspClient *self,
edits = g_ptr_array_new_with_free_func (g_object_unref);
-#if 0
- /* We'd prefer to support this, but do not currently */
- if (JSONRPC_MESSAGE_PARSE (edit, "documentChanges", JSONRPC_MESSAGE_GET_VARIANT (&changes)))
- {
- }
-#endif
-
- if (JSONRPC_MESSAGE_PARSE (parent, "changes", JSONRPC_MESSAGE_GET_VARIANT (&changes)))
- {
- if (g_variant_is_of_type (changes, G_VARIANT_TYPE_VARDICT))
- {
- GVariantIter iter;
- GVariant *value;
- gchar *uri;
-
- g_variant_iter_init (&iter, changes);
- while (g_variant_iter_loop (&iter, "{sv}", &uri, &value))
- {
- GVariantIter edit_iter;
- GVariant *item;
- struct {
- gint64 line;
- gint64 column;
- } begin, end;
-
- g_variant_iter_init (&edit_iter, value);
- while (g_variant_iter_loop (&edit_iter, "v", &item))
- {
- const gchar *new_text = NULL;
- gboolean r;
-
- r = JSONRPC_MESSAGE_PARSE (item,
- "range", "{",
- "start", "{",
- "line", JSONRPC_MESSAGE_GET_INT64 (&begin.line),
- "character", JSONRPC_MESSAGE_GET_INT64 (&begin.column),
- "}",
- "end", "{",
- "line", JSONRPC_MESSAGE_GET_INT64 (&end.line),
- "character", JSONRPC_MESSAGE_GET_INT64 (&end.column),
- "}",
- "}",
- "newText", JSONRPC_MESSAGE_GET_STRING (&new_text)
- );
-
- if (r)
- {
- g_autoptr(IdeLocation) begin_loc = NULL;
- g_autoptr(IdeLocation) end_loc = NULL;
- g_autoptr(IdeRange) range = NULL;
- g_autoptr(GFile) file = NULL;
-
- file = g_file_new_for_uri (uri);
- begin_loc = ide_location_new (file, begin.line, begin.column);
- end_loc = ide_location_new (file, end.line, end.column);
- range = ide_range_new (begin_loc, end_loc);
-
- g_ptr_array_add (edits, ide_text_edit_new (range, new_text));
- }
- }
- }
- }
- }
+ workspace_edit = ide_lsp_workspace_edit_new(parent);
+ edits = ide_lsp_workspace_edit_get_edits(workspace_edit);
if (edits->len > 0)
{
diff --git a/src/libide/lsp/ide-lsp-rename-provider.c b/src/libide/lsp/ide-lsp-rename-provider.c
index 6f9cc65b0..389001954 100644
--- a/src/libide/lsp/ide-lsp-rename-provider.c
+++ b/src/libide/lsp/ide-lsp-rename-provider.c
@@ -29,6 +29,7 @@
#include "ide-lsp-client.h"
#include "ide-lsp-rename-provider.h"
#include "ide-lsp-util.h"
+#include "ide-lsp-workspace-edit.h"
typedef struct
{
@@ -145,84 +146,6 @@ ide_lsp_rename_provider_init (IdeLspRenameProvider *self)
{
}
-static void
-ide_lsp_rename_provider_rename_cb_changes (IdeTask *task, GVariant *return_value)
-{
- g_autoptr(GPtrArray) ret = NULL;
- g_autoptr(GVariantIter) changes_by_uri = NULL;
- const gchar *uri;
- GVariant *changes;
-
- IDE_ENTRY;
- if (!JSONRPC_MESSAGE_PARSE (return_value, "changes", JSONRPC_MESSAGE_GET_ITER (&changes_by_uri)))
- IDE_EXIT;
-
- ret = g_ptr_array_new_with_free_func (g_object_unref);
-
- while (g_variant_iter_loop (changes_by_uri, "{sv}", &uri, &changes))
- {
- g_autoptr(GFile) gfile = g_file_new_for_uri (uri);
- GVariantIter changes_iter;
- GVariant *change;
-
- if (!g_variant_is_container (changes))
- continue;
-
- g_variant_iter_init (&changes_iter, changes);
-
- while (g_variant_iter_loop (&changes_iter, "v", &change))
- {
- IdeTextEdit *edit = ide_lsp_decode_text_edit (change, gfile);
- if (edit != NULL)
- g_ptr_array_add (ret, edit);
- }
- }
-
- ide_task_return_pointer (task, g_steal_pointer (&ret), g_ptr_array_unref);
-
- IDE_EXIT;
-}
-
-static void
-ide_lsp_rename_provider_rename_cb_document_changes (IdeTask *task, GVariant *return_value)
-{
- g_autoptr(GPtrArray) ret = NULL;
- g_autoptr(GVariantIter) changes_by_textdocument = NULL;
- GVariant *changes;
-
- IDE_ENTRY;
-
- if (!JSONRPC_MESSAGE_PARSE (return_value, "documentChanges", JSONRPC_MESSAGE_GET_ITER
(&changes_by_textdocument)))
- IDE_EXIT;
-
- ret = g_ptr_array_new_with_free_func (g_object_unref);
-
- while (g_variant_iter_loop (changes_by_textdocument, "v", &changes))
- {
- g_autoptr(GFile) gfile = NULL;
- g_autoptr(GVariantIter) edits = NULL;
- const gchar *uri;
- GVariant *edit;
-
- JSONRPC_MESSAGE_PARSE (changes, "textDocument", "{", "uri", JSONRPC_MESSAGE_GET_STRING (&uri), "}");
- gfile = g_file_new_for_uri (uri);
-
- if (!JSONRPC_MESSAGE_PARSE (changes, "edits", JSONRPC_MESSAGE_GET_ITER (&edits)))
- IDE_EXIT;
-
- while (g_variant_iter_loop (edits, "v", &edit))
- {
- IdeTextEdit *tedit = ide_lsp_decode_text_edit (edit, gfile);
- if (tedit != NULL)
- g_ptr_array_add (ret, tedit);
- }
- }
-
- ide_task_return_pointer (task, g_steal_pointer (&ret), g_ptr_array_unref);
-
- IDE_EXIT;
-}
-
static void
ide_lsp_rename_provider_rename_cb (GObject *object,
GAsyncResult *result,
@@ -232,7 +155,8 @@ ide_lsp_rename_provider_rename_cb (GObject *object,
g_autoptr(GVariant) return_value = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(IdeTask) task = user_data;
- g_autoptr(GVariantDict) dict = NULL;
+ g_autoptr(IdeLspWorkspaceEdit) workspace_edit = NULL;
+ g_autoptr(GPtrArray) ret = NULL;
IDE_ENTRY;
@@ -246,11 +170,9 @@ ide_lsp_rename_provider_rename_cb (GObject *object,
IDE_EXIT;
}
- dict = g_variant_dict_new (return_value);
- if (g_variant_dict_contains (dict, "changes"))
- ide_lsp_rename_provider_rename_cb_changes (g_steal_pointer (&task), return_value);
- else if (g_variant_dict_contains (dict, "documentChanges"))
- ide_lsp_rename_provider_rename_cb_document_changes (g_steal_pointer (&task), return_value);
+ workspace_edit = ide_lsp_workspace_edit_new(return_value);
+ ret = ide_lsp_workspace_edit_get_edits(workspace_edit);
+ ide_task_return_pointer (task, g_steal_pointer (&ret), g_ptr_array_unref);
IDE_EXIT;
}
diff --git a/src/libide/lsp/ide-lsp-workspace-edit.c b/src/libide/lsp/ide-lsp-workspace-edit.c
new file mode 100644
index 000000000..66cc274d8
--- /dev/null
+++ b/src/libide/lsp/ide-lsp-workspace-edit.c
@@ -0,0 +1,163 @@
+/* ide-lsp-workspace-edit.c
+ *
+ * Copyright 2021 Georg Vienna <georg vienna himbarsoft com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "ide-lsp-workspace-edit"
+
+#include "config.h"
+
+#include <jsonrpc-glib.h>
+
+#include "ide-lsp-workspace-edit.h"
+#include "ide-lsp-util.h"
+
+struct _IdeLspWorkspaceEdit
+{
+ GObject parent_instance;
+
+ GVariant* variant;
+};
+
+G_DEFINE_FINAL_TYPE (IdeLspWorkspaceEdit, ide_lsp_workspace_edit, G_TYPE_OBJECT)
+
+static void
+ide_lsp_workspace_edit_finalize (GObject *object)
+{
+ IdeLspWorkspaceEdit *self = (IdeLspWorkspaceEdit *)object;
+
+ g_clear_pointer (&self->variant, g_variant_unref);
+
+ G_OBJECT_CLASS (ide_lsp_workspace_edit_parent_class)->finalize (object);
+}
+
+static void
+ide_lsp_workspace_edit_class_init (IdeLspWorkspaceEditClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = ide_lsp_workspace_edit_finalize;
+}
+
+static void
+ide_lsp_workspace_edit_init (IdeLspWorkspaceEdit *self)
+{
+}
+
+IdeLspWorkspaceEdit *
+ide_lsp_workspace_edit_new (GVariant *variant)
+{
+ IdeLspWorkspaceEdit *self;
+
+ g_return_val_if_fail (variant != NULL, NULL);
+
+ self = g_object_new (IDE_TYPE_LSP_WORKSPACE_EDIT, NULL);
+ self->variant = g_variant_ref (variant);
+
+ return self;
+}
+
+/**
+ * ide_lsp_workspace_edit_get_edits:
+ *
+ * Returns the list of text edits that this workspace edit contains.
+ *
+ * Returns: (element-type IdeTextEdit) (transfer full): a #GPtrArray of #IdeTextEdit.
+ *
+ */
+GPtrArray *
+ide_lsp_workspace_edit_get_edits(IdeLspWorkspaceEdit *self)
+{
+ g_autoptr(GVariant) changes = NULL;
+ g_autoptr(GPtrArray) edits = NULL;
+
+ IDE_ENTRY;
+ g_return_val_if_fail(IDE_IS_LSP_WORKSPACE_EDIT(self), NULL);
+
+ edits = g_ptr_array_new_with_free_func(g_object_unref);
+
+ if (JSONRPC_MESSAGE_PARSE(self->variant, "documentChanges", JSONRPC_MESSAGE_GET_VARIANT(&changes)))
+ {
+ if (g_variant_is_of_type(changes, G_VARIANT_TYPE_ARRAY))
+ {
+ GVariantIter iter;
+ g_autoptr(GVariant) text_document_edit = NULL;
+ const gchar *uri = NULL;
+
+ g_variant_iter_init(&iter, changes);
+ while (g_variant_iter_loop(&iter, "v", &text_document_edit))
+ {
+ g_autoptr(GVariant) text_edits = NULL;
+
+ if (JSONRPC_MESSAGE_PARSE(text_document_edit,
+ "textDocument", "{",
+ "uri", JSONRPC_MESSAGE_GET_STRING(&uri),
+ "}",
+ "edits", JSONRPC_MESSAGE_GET_VARIANT(&text_edits)
+ ))
+ {
+ g_autoptr(GFile) gfile = NULL;
+ GVariantIter text_edit_iter;
+ g_autoptr(GVariant) item = NULL;
+
+ gfile = g_file_new_for_uri(uri);
+ g_variant_iter_init(&text_edit_iter, text_edits);
+ while (g_variant_iter_loop(&text_edit_iter, "v", &item))
+ {
+ IdeTextEdit* edit = ide_lsp_decode_text_edit(item, gfile);
+ if (edit)
+ {
+ g_ptr_array_add(edits, edit);
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (JSONRPC_MESSAGE_PARSE(self->variant, "changes", JSONRPC_MESSAGE_GET_VARIANT(&changes)))
+ {
+ if (g_variant_is_of_type(changes, G_VARIANT_TYPE_VARDICT))
+ {
+ GVariantIter iter;
+ g_autoptr(GVariant) value = NULL;
+ gchar *uri;
+
+ g_variant_iter_init(&iter, changes);
+ while (g_variant_iter_loop(&iter, "{sv}", &uri, &value))
+ {
+ g_autoptr(GFile) gfile = NULL;
+ GVariantIter edit_iter;
+ g_autoptr(GVariant) item = NULL;
+
+ gfile = g_file_new_for_uri(uri);
+ g_variant_iter_init(&edit_iter, value);
+ while (g_variant_iter_loop(&edit_iter, "v", &item))
+ {
+ IdeTextEdit* edit = ide_lsp_decode_text_edit(item, gfile);
+ if (edit)
+ {
+ g_ptr_array_add(edits, edit);
+ }
+ }
+ }
+ }
+ }
+
+ IDE_RETURN(IDE_PTR_ARRAY_STEAL_FULL(&edits));
+}
+
diff --git a/src/libide/lsp/ide-lsp-workspace-edit.h b/src/libide/lsp/ide-lsp-workspace-edit.h
new file mode 100644
index 000000000..370de42dd
--- /dev/null
+++ b/src/libide/lsp/ide-lsp-workspace-edit.h
@@ -0,0 +1,42 @@
+/* ide-lsp-workspace-edit.h
+ *
+ * Copyright 2021 Georg Vienna <georg vienna himbarsoft com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#if !defined (IDE_LSP_INSIDE) && !defined (IDE_LSP_COMPILATION)
+# error "Only <libide-lsp.h> can be included directly."
+#endif
+
+#include <libide-code.h>
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_LSP_WORKSPACE_EDIT (ide_lsp_workspace_edit_get_type())
+
+IDE_AVAILABLE_IN_42
+G_DECLARE_FINAL_TYPE(IdeLspWorkspaceEdit, ide_lsp_workspace_edit, IDE, LSP_WORKSPACE_EDIT, GObject)
+
+IDE_AVAILABLE_IN_42
+IdeLspWorkspaceEdit *ide_lsp_workspace_edit_new (GVariant * variant);
+
+IDE_AVAILABLE_IN_42
+GPtrArray* ide_lsp_workspace_edit_get_edits(IdeLspWorkspaceEdit *self);
+
+G_END_DECLS
diff --git a/src/libide/lsp/libide-lsp.h b/src/libide/lsp/libide-lsp.h
index a0eccb0cc..5f08b2410 100644
--- a/src/libide/lsp/libide-lsp.h
+++ b/src/libide/lsp/libide-lsp.h
@@ -41,5 +41,6 @@
#include "ide-lsp-symbol-resolver.h"
#include "ide-lsp-symbol-tree.h"
#include "ide-lsp-util.h"
+#include "ide-lsp-workspace-edit.h"
#undef IDE_LSP_INSIDE
diff --git a/src/libide/lsp/meson.build b/src/libide/lsp/meson.build
index 786e5eb04..f365940d8 100644
--- a/src/libide/lsp/meson.build
+++ b/src/libide/lsp/meson.build
@@ -22,6 +22,7 @@ libide_lsp_public_headers = [
'ide-lsp-symbol-resolver.h',
'ide-lsp-symbol-tree.h',
'ide-lsp-types.h',
+ 'ide-lsp-workspace-edit.h',
]
libide_lsp_private_headers = [
@@ -51,6 +52,7 @@ libide_lsp_public_sources = [
'ide-lsp-symbol-node.c',
'ide-lsp-symbol-resolver.c',
'ide-lsp-symbol-tree.c',
+ 'ide-lsp-workspace-edit.c',
]
libide_lsp_private_sources = [
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]