[gnome-builder: 9/17] add rename provider and enhance lsp implementation
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder: 9/17] add rename provider and enhance lsp implementation
- Date: Mon, 22 Jun 2020 19:23:21 +0000 (UTC)
commit 50e7a9131365b60d130ce2ff66f345012a3c3abb
Author: Günther Wagner <info gunibert de>
Date: Sun May 24 12:35:54 2020 +0200
add rename provider and enhance lsp implementation
src/libide/lsp/ide-lsp-rename-provider.c | 181 ++++++++++++++-------
src/libide/sourceview/ide-source-view.c | 27 +++
src/plugins/rust-analyzer/meson.build | 1 +
.../rust-analyzer/rust-analyzer-rename-provider.c | 65 ++++++++
.../rust-analyzer/rust-analyzer-rename-provider.h | 31 ++++
src/plugins/rust-analyzer/rust-analyzer.c | 4 +
src/plugins/rust-analyzer/rust-analyzer.plugin | 2 +-
7 files changed, 254 insertions(+), 57 deletions(-)
---
diff --git a/src/libide/lsp/ide-lsp-rename-provider.c b/src/libide/lsp/ide-lsp-rename-provider.c
index 123d2e1a1..bdae4de7b 100644
--- a/src/libide/lsp/ide-lsp-rename-provider.c
+++ b/src/libide/lsp/ide-lsp-rename-provider.c
@@ -144,32 +144,61 @@ ide_lsp_rename_provider_init (IdeLspRenameProvider *self)
{
}
+/*
+ * Parsing a TextEdit Variant happens here. See specification
+ * https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textEdit
+ * for further details
+ */
+static IdeTextEdit *
+_extract_text_edit (GFile *gfile, GVariant *change)
+{
+ g_autoptr(IdeLocation) begin_location = NULL;
+ g_autoptr(IdeLocation) end_location = NULL;
+ g_autoptr(IdeRange) range = NULL;
+ const gchar *new_text = NULL;
+ gboolean success;
+ struct {
+ gint64 line;
+ gint64 column;
+ } begin, end;
+
+ success = JSONRPC_MESSAGE_PARSE (change,
+ "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 (!success)
+ {
+ IDE_TRACE_MSG ("Failed to extract change from variant");
+ return NULL;
+ }
+
+ begin_location = ide_location_new (gfile, begin.line, begin.column);
+ end_location = ide_location_new (gfile, end.line, end.column);
+ range = ide_range_new (begin_location, end_location);
+
+ return ide_text_edit_new (range, new_text);
+
+}
+
static void
-ide_lsp_rename_provider_rename_cb (GObject *object,
- GAsyncResult *result,
- gpointer user_data)
+ide_lsp_rename_provider_rename_cb_changes (IdeTask *task, GVariant *return_value)
{
- IdeLspClient *client = (IdeLspClient *)object;
- g_autoptr(GVariant) return_value = NULL;
- g_autoptr(GError) error = NULL;
- g_autoptr(IdeTask) task = user_data;
g_autoptr(GPtrArray) ret = NULL;
g_autoptr(GVariantIter) changes_by_uri = NULL;
const gchar *uri;
GVariant *changes;
IDE_ENTRY;
-
- g_assert (IDE_IS_LSP_CLIENT (client));
- g_assert (G_IS_ASYNC_RESULT (result));
- g_assert (IDE_IS_TASK (task));
-
- if (!ide_lsp_client_call_finish (client, result, &return_value, &error))
- {
- ide_task_return_error (task, g_steal_pointer (&error));
- IDE_EXIT;
- }
-
if (!JSONRPC_MESSAGE_PARSE (return_value, "changes", JSONRPC_MESSAGE_GET_ITER (&changes_by_uri)))
IDE_EXIT;
@@ -188,41 +217,49 @@ ide_lsp_rename_provider_rename_cb (GObject *object,
while (g_variant_iter_loop (&changes_iter, "v", &change))
{
- g_autoptr(IdeLocation) begin_location = NULL;
- g_autoptr(IdeLocation) end_location = NULL;
- g_autoptr(IdeRange) range = NULL;
- const gchar *new_text = NULL;
- gboolean success;
- struct {
- gint64 line;
- gint64 column;
- } begin, end;
-
- success = JSONRPC_MESSAGE_PARSE (change,
- "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 (!success)
- {
- IDE_TRACE_MSG ("Failed to extract change from variant");
- continue;
- }
-
- begin_location = ide_location_new (gfile, begin.line, begin.column);
- end_location = ide_location_new (gfile, end.line, end.column);
- range = ide_range_new (begin_location, end_location);
-
- g_ptr_array_add (ret, ide_text_edit_new (range, new_text));
+ IdeTextEdit *edit = _extract_text_edit (gfile, change);
+ 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 = _extract_text_edit (gfile, edit);
+ if (tedit != NULL)
+ g_ptr_array_add (ret, tedit);
}
}
@@ -231,6 +268,38 @@ ide_lsp_rename_provider_rename_cb (GObject *object,
IDE_EXIT;
}
+static void
+ide_lsp_rename_provider_rename_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ IdeLspClient *client = (IdeLspClient *)object;
+ g_autoptr(GVariant) return_value = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(IdeTask) task = user_data;
+ g_autoptr(GVariantDict) dict = NULL;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_LSP_CLIENT (client));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (IDE_IS_TASK (task));
+
+ if (!ide_lsp_client_call_finish (client, result, &return_value, &error))
+ {
+ ide_task_return_error (task, g_steal_pointer (&error));
+ 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);
+
+ IDE_EXIT;
+}
+
static void
ide_lsp_rename_provider_rename_async (IdeRenameProvider *provider,
IdeLocation *location,
@@ -307,9 +376,9 @@ ide_lsp_rename_provider_rename_async (IdeRenameProvider *provider,
static gboolean
ide_lsp_rename_provider_rename_finish (IdeRenameProvider *provider,
- GAsyncResult *result,
- GPtrArray **edits,
- GError **error)
+ GAsyncResult *result,
+ GPtrArray **edits,
+ GError **error)
{
g_autoptr(GPtrArray) ar = NULL;
gboolean ret;
diff --git a/src/libide/sourceview/ide-source-view.c b/src/libide/sourceview/ide-source-view.c
index 90b4ac3b9..e27dafcff 100644
--- a/src/libide/sourceview/ide-source-view.c
+++ b/src/libide/sourceview/ide-source-view.c
@@ -4951,6 +4951,9 @@ ide_source_view_real_begin_rename (IdeSourceView *self)
GtkTextBuffer *buffer;
GtkTextMark *insert;
GtkTextIter iter;
+ GtkTextIter word_start;
+ GtkTextIter word_end;
+ g_autofree gchar *symbol = NULL;
GdkRectangle loc;
IDE_ENTRY;
@@ -4982,9 +4985,33 @@ ide_source_view_real_begin_rename (IdeSourceView *self)
GTK_TEXT_WINDOW_WIDGET,
loc.x, loc.y, &loc.x, &loc.y);
+ // get symbol to rename (for the popup)
+ if (gtk_text_iter_inside_word (&iter) && !gtk_text_iter_starts_word (&iter))
+ {
+ word_start = iter;
+ word_end = iter;
+ gtk_text_iter_backward_word_start (&word_start);
+ gtk_text_iter_forward_word_end (&word_end);
+ }
+ else if (gtk_text_iter_starts_word (&iter))
+ {
+ word_start = iter;
+ word_end = iter;
+ gtk_text_iter_forward_word_end (&word_end);
+ }
+ else if (gtk_text_iter_ends_word (&iter))
+ {
+ word_start = iter;
+ word_end = iter;
+ gtk_text_iter_backward_word_start (&word_start);
+ }
+
+ symbol = gtk_text_iter_get_text (&word_start, &word_end);
+
popover = g_object_new (DZL_TYPE_SIMPLE_POPOVER,
"title", _("Rename symbol"),
"button-text", _("Rename"),
+ "text", symbol,
"relative-to", self,
"pointing-to", &loc,
NULL);
diff --git a/src/plugins/rust-analyzer/meson.build b/src/plugins/rust-analyzer/meson.build
index aa755b504..1d153a2df 100644
--- a/src/plugins/rust-analyzer/meson.build
+++ b/src/plugins/rust-analyzer/meson.build
@@ -9,6 +9,7 @@ plugins_sources += files([
'rust-analyzer-formatter.c',
'rust-analyzer-highlighter.c',
'rust-analyzer-hover-provider.c',
+ 'rust-analyzer-rename-provider.c',
'rust-analyzer-transfer.c',
'rust-analyzer-workbench-addin.c',
])
diff --git a/src/plugins/rust-analyzer/rust-analyzer-rename-provider.c
b/src/plugins/rust-analyzer/rust-analyzer-rename-provider.c
new file mode 100644
index 000000000..7e8bb875e
--- /dev/null
+++ b/src/plugins/rust-analyzer/rust-analyzer-rename-provider.c
@@ -0,0 +1,65 @@
+/* rust-analyzer-rename-provider.c
+ *
+ * Copyright 2020 Günther Wagner <info gunibert de>
+ *
+ * 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
+ */
+
+#include "rust-analyzer-rename-provider.h"
+#include "rust-analyzer-service.h"
+
+struct _RustAnalyzerRenameProvider
+{
+ IdeLspRenameProvider parent_instance;
+};
+
+static void provider_iface_init (IdeRenameProviderInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (RustAnalyzerRenameProvider,
+ rust_analyzer_rename_provider,
+ IDE_TYPE_LSP_RENAME_PROVIDER,
+ G_IMPLEMENT_INTERFACE (IDE_TYPE_RENAME_PROVIDER, provider_iface_init))
+
+static void
+rust_analyzer_rename_provider_class_init (RustAnalyzerRenameProviderClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+}
+
+static void
+rust_analyzer_rename_provider_init (RustAnalyzerRenameProvider *self)
+{
+}
+
+static void
+rust_analyzer_rename_provider_load (IdeRenameProvider *self)
+{
+ IdeContext *context = NULL;
+ RustAnalyzerService *service = NULL;
+
+ g_assert (RUST_IS_ANALYZER_RENAME_PROVIDER (self));
+
+ context = ide_object_get_context (IDE_OBJECT (self));
+ service = ide_object_ensure_child_typed (IDE_OBJECT (context), RUST_TYPE_ANALYZER_SERVICE);
+ rust_analyzer_service_ensure_started (service);
+ g_object_bind_property (service, "client", self, "client", G_BINDING_SYNC_CREATE);
+}
+
+static void
+provider_iface_init (IdeRenameProviderInterface *iface)
+{
+ iface->load = rust_analyzer_rename_provider_load;
+}
diff --git a/src/plugins/rust-analyzer/rust-analyzer-rename-provider.h
b/src/plugins/rust-analyzer/rust-analyzer-rename-provider.h
new file mode 100644
index 000000000..9605bdeed
--- /dev/null
+++ b/src/plugins/rust-analyzer/rust-analyzer-rename-provider.h
@@ -0,0 +1,31 @@
+/* rust-analyzer-rename-provider.h
+ *
+ * Copyright 2020 Günther Wagner <info gunibert de>
+ *
+ * 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
+
+#include <libide-lsp.h>
+
+G_BEGIN_DECLS
+
+#define RUST_TYPE_ANALYZER_RENAME_PROVIDER (rust_analyzer_rename_provider_get_type())
+
+G_DECLARE_FINAL_TYPE (RustAnalyzerRenameProvider, rust_analyzer_rename_provider, RUST,
ANALYZER_RENAME_PROVIDER, IdeLspRenameProvider)
+
+G_END_DECLS
diff --git a/src/plugins/rust-analyzer/rust-analyzer.c b/src/plugins/rust-analyzer/rust-analyzer.c
index 21948d834..f8d5d0062 100644
--- a/src/plugins/rust-analyzer/rust-analyzer.c
+++ b/src/plugins/rust-analyzer/rust-analyzer.c
@@ -28,6 +28,7 @@
#include "rust-analyzer-highlighter.h"
#include "rust-analyzer-hover-provider.h"
#include "rust-analyzer-workbench-addin.h"
+#include "rust-analyzer-rename-provider.h"
_IDE_EXTERN void
_rust_analyzer_register_types (PeasObjectModule *module)
@@ -53,4 +54,7 @@ _rust_analyzer_register_types (PeasObjectModule *module)
peas_object_module_register_extension_type (module,
IDE_TYPE_HOVER_PROVIDER,
RUST_TYPE_ANALYZER_HOVER_PROVIDER);
+ peas_object_module_register_extension_type (module,
+ IDE_TYPE_RENAME_PROVIDER,
+ RUST_TYPE_ANALYZER_RENAME_PROVIDER);
}
diff --git a/src/plugins/rust-analyzer/rust-analyzer.plugin b/src/plugins/rust-analyzer/rust-analyzer.plugin
index 42f80d458..53e86e0c7 100644
--- a/src/plugins/rust-analyzer/rust-analyzer.plugin
+++ b/src/plugins/rust-analyzer/rust-analyzer.plugin
@@ -12,4 +12,4 @@ X-Symbol-Resolver-Languages=rust
X-Formatter-Languages=rust
X-Highlighter-Languages=rust
X-Hover-Provider-Languages=rust
-#X-Rename-Provider-Languages=rust
+X-Rename-Provider-Languages=rust
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]