[gnome-builder/wip/chergert/completion] langserv: port to new completion API
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/chergert/completion] langserv: port to new completion API
- Date: Mon, 4 Jun 2018 08:05:53 +0000 (UTC)
commit 83033e1785b3a423be1f31bac1207313bfad1e79
Author: Christian Hergert <chergert redhat com>
Date: Mon Jun 4 01:05:04 2018 -0700
langserv: port to new completion API
This brings the minimal language server implementation
we have up to date using the new completion API.
src/libide/ide.h | 2 +
src/libide/langserv/ide-langserv-completion-item.c | 141 +++++++++
src/libide/langserv/ide-langserv-completion-item.h | 47 +++
.../langserv/ide-langserv-completion-provider.c | 322 ++++++++++-----------
.../langserv/ide-langserv-completion-provider.h | 9 +-
.../langserv/ide-langserv-completion-results.c | 177 +++++++++++
.../langserv/ide-langserv-completion-results.h | 36 +++
src/libide/langserv/meson.build | 4 +
src/plugins/go-langserv/go_langserver_plugin.py | 2 +-
src/plugins/rust-langserv/rust_langserv_plugin.py | 2 -
10 files changed, 565 insertions(+), 177 deletions(-)
---
diff --git a/src/libide/ide.h b/src/libide/ide.h
index ec4ad3d00..dc21a4873 100644
--- a/src/libide/ide.h
+++ b/src/libide/ide.h
@@ -121,7 +121,9 @@ G_BEGIN_DECLS
#include "highlighting/ide-highlight-index.h"
#include "highlighting/ide-highlighter.h"
#include "langserv/ide-langserv-client.h"
+#include "langserv/ide-langserv-completion-item.h"
#include "langserv/ide-langserv-completion-provider.h"
+#include "langserv/ide-langserv-completion-results.h"
#include "langserv/ide-langserv-diagnostic-provider.h"
#include "langserv/ide-langserv-rename-provider.h"
#include "langserv/ide-langserv-symbol-resolver.h"
diff --git a/src/libide/langserv/ide-langserv-completion-item.c
b/src/libide/langserv/ide-langserv-completion-item.c
new file mode 100644
index 000000000..0f09ca35a
--- /dev/null
+++ b/src/libide/langserv/ide-langserv-completion-item.c
@@ -0,0 +1,141 @@
+/* ide-langserv-completion-item.c
+ *
+ * Copyright 2018 Christian Hergert <chergert redhat 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/>.
+ */
+
+#include "config.h"
+
+#define G_LOG_DOMAIN "ide-langserv-completion-item"
+
+#include <jsonrpc-glib.h>
+
+#include "ide-debug.h"
+
+#include "completion/ide-completion-item.h"
+#include "langserv/ide-langserv-completion-item.h"
+#include "langserv/ide-langserv-util.h"
+#include "snippets/ide-snippet-chunk.h"
+#include "symbols/ide-symbol.h"
+
+struct _IdeLangservCompletionItem
+{
+ GObject parent_instance;
+ GVariant *variant;
+ const gchar *label;
+ const gchar *detail;
+ guint kind;
+};
+
+G_DEFINE_TYPE_WITH_CODE (IdeLangservCompletionItem, ide_langserv_completion_item, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (IDE_TYPE_COMPLETION_PROPOSAL, NULL))
+
+static void
+ide_langserv_completion_item_finalize (GObject *object)
+{
+ IdeLangservCompletionItem *self = (IdeLangservCompletionItem *)object;
+
+ g_clear_pointer (&self->variant, g_variant_unref);
+
+ G_OBJECT_CLASS (ide_langserv_completion_item_parent_class)->finalize (object);
+}
+
+static void
+ide_langserv_completion_item_class_init (IdeLangservCompletionItemClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = ide_langserv_completion_item_finalize;
+}
+
+static void
+ide_langserv_completion_item_init (IdeLangservCompletionItem *self)
+{
+}
+
+IdeLangservCompletionItem *
+ide_langserv_completion_item_new (GVariant *variant)
+{
+ g_autoptr(GVariant) unboxed = NULL;
+ IdeLangservCompletionItem *self;
+ gint64 kind = 0;
+
+ g_return_val_if_fail (variant != NULL, NULL);
+
+ if (g_variant_is_of_type (variant, G_VARIANT_TYPE_VARIANT))
+ variant = unboxed = g_variant_get_variant (variant);
+
+ self = g_object_new (IDE_TYPE_LANGSERV_COMPLETION_ITEM, NULL);
+ self->variant = g_variant_ref_sink (variant);
+
+ g_variant_lookup (variant, "label", "&s", &self->label);
+ g_variant_lookup (variant, "detail", "&s", &self->detail);
+
+ if (JSONRPC_MESSAGE_PARSE (variant, "kind", JSONRPC_MESSAGE_GET_INT64 (&kind)))
+ self->kind = ide_langserv_decode_completion_kind (kind);
+
+ return self;
+}
+
+gchar *
+ide_langserv_completion_item_get_markup (IdeLangservCompletionItem *self,
+ const gchar *typed_text)
+{
+ g_return_val_if_fail (IDE_IS_LANGSERV_COMPLETION_ITEM (self), NULL);
+
+ return ide_completion_item_fuzzy_highlight (self->label, typed_text);
+}
+
+const gchar *
+ide_langserv_completion_item_get_return_type (IdeLangservCompletionItem *self)
+{
+ g_return_val_if_fail (IDE_IS_LANGSERV_COMPLETION_ITEM (self), NULL);
+
+ /* TODO: How do we get this from langserv? */
+
+ return NULL;
+}
+
+const gchar *
+ide_langserv_completion_item_get_icon_name (IdeLangservCompletionItem *self)
+{
+ g_return_val_if_fail (IDE_IS_LANGSERV_COMPLETION_ITEM (self), NULL);
+
+ return ide_symbol_kind_get_icon_name (self->kind);
+}
+
+const gchar *
+ide_langserv_completion_item_get_detail (IdeLangservCompletionItem *self)
+{
+ g_return_val_if_fail (IDE_IS_LANGSERV_COMPLETION_ITEM (self), NULL);
+
+ return self->detail;
+}
+
+IdeSnippet *
+ide_langserv_completion_item_get_snippet (IdeLangservCompletionItem *self)
+{
+ g_autoptr(IdeSnippet) snippet = NULL;
+ g_autoptr(IdeSnippetChunk) chunk = NULL;
+
+ g_return_val_if_fail (IDE_IS_LANGSERV_COMPLETION_ITEM (self), NULL);
+
+ snippet = ide_snippet_new (NULL, NULL);
+ chunk = ide_snippet_chunk_new ();
+ ide_snippet_chunk_set_spec (chunk, self->label);
+ ide_snippet_add_chunk (snippet, chunk);
+
+ return g_steal_pointer (&snippet);
+}
diff --git a/src/libide/langserv/ide-langserv-completion-item.h
b/src/libide/langserv/ide-langserv-completion-item.h
new file mode 100644
index 000000000..e5b9d948f
--- /dev/null
+++ b/src/libide/langserv/ide-langserv-completion-item.h
@@ -0,0 +1,47 @@
+/* ide-langserv-completion-item.h
+ *
+ * Copyright 2018 Christian Hergert <chergert redhat 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/>.
+ */
+
+#pragma once
+
+#include "ide-version-macros.h"
+
+#include "completion/ide-completion-proposal.h"
+#include "snippets/ide-snippet.h"
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_LANGSERV_COMPLETION_ITEM (ide_langserv_completion_item_get_type())
+
+IDE_AVAILABLE_IN_3_30
+G_DECLARE_FINAL_TYPE (IdeLangservCompletionItem, ide_langserv_completion_item, IDE,
LANGSERV_COMPLETION_ITEM, GObject)
+
+IDE_AVAILABLE_IN_3_30
+IdeLangservCompletionItem *ide_langserv_completion_item_new (GVariant *variant);
+IDE_AVAILABLE_IN_3_30
+const gchar *ide_langserv_completion_item_get_icon_name (IdeLangservCompletionItem *self);
+IDE_AVAILABLE_IN_3_30
+const gchar *ide_langserv_completion_item_get_return_type (IdeLangservCompletionItem *self);
+IDE_AVAILABLE_IN_3_30
+const gchar *ide_langserv_completion_item_get_detail (IdeLangservCompletionItem *self);
+IDE_AVAILABLE_IN_3_30
+gchar *ide_langserv_completion_item_get_markup (IdeLangservCompletionItem *self,
+ const gchar
*typed_text);
+IDE_AVAILABLE_IN_3_30
+IdeSnippet *ide_langserv_completion_item_get_snippet (IdeLangservCompletionItem *self);
+
+G_END_DECLS
diff --git a/src/libide/langserv/ide-langserv-completion-provider.c
b/src/libide/langserv/ide-langserv-completion-provider.c
index 9561333fa..87b541aef 100644
--- a/src/libide/langserv/ide-langserv-completion-provider.c
+++ b/src/libide/langserv/ide-langserv-completion-provider.c
@@ -16,36 +16,38 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#define G_LOG_DOMAIN "ide-langserv-completion-provider"
-
#include "config.h"
+#define G_LOG_DOMAIN "ide-langserv-completion-provider"
+
#include <jsonrpc-glib.h>
#include "ide-debug.h"
#include "buffers/ide-buffer.h"
+#include "completion/ide-completion-context.h"
+#include "completion/ide-completion-provider.h"
+#include "completion/ide-completion-list-box-row.h"
#include "langserv/ide-langserv-completion-provider.h"
+#include "langserv/ide-langserv-completion-item.h"
+#include "langserv/ide-langserv-completion-results.h"
#include "langserv/ide-langserv-util.h"
+#include "snippets/ide-snippet.h"
+#include "sourceview/ide-source-view.h"
#include "symbols/ide-symbol.h"
+#include "threading/ide-task.h"
typedef struct
{
IdeLangservClient *client;
+ gchar *word;
} IdeLangservCompletionProviderPrivate;
-typedef struct
-{
- IdeLangservCompletionProvider *self;
- GtkSourceCompletionContext *context;
-} CompletionState;
-
-static void source_completion_provider_iface_init (GtkSourceCompletionProviderIface *iface);
+static void provider_iface_init (IdeCompletionProviderInterface *iface);
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (IdeLangservCompletionProvider, ide_langserv_completion_provider,
IDE_TYPE_OBJECT,
G_ADD_PRIVATE (IdeLangservCompletionProvider)
- G_IMPLEMENT_INTERFACE (GTK_SOURCE_TYPE_COMPLETION_PROVIDER,
source_completion_provider_iface_init)
- G_IMPLEMENT_INTERFACE (IDE_TYPE_COMPLETION_PROVIDER, NULL))
+ G_IMPLEMENT_INTERFACE (IDE_TYPE_COMPLETION_PROVIDER, provider_iface_init))
enum {
PROP_0,
@@ -55,29 +57,6 @@ enum {
static GParamSpec *properties [N_PROPS];
-static void
-completion_state_free (CompletionState *state)
-{
- g_clear_object (&state->self);
- g_clear_object (&state->context);
- g_slice_free (CompletionState, state);
-}
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC (CompletionState, completion_state_free);
-
-CompletionState *
-completion_state_new (IdeLangservCompletionProvider *self,
- GtkSourceCompletionContext *context)
-{
- CompletionState *state;
-
- state = g_slice_new0 (CompletionState);
- state->self = g_object_ref (self);
- state->context = g_object_ref (context);
-
- return state;
-}
-
static void
ide_langserv_completion_provider_finalize (GObject *object)
{
@@ -85,6 +64,7 @@ ide_langserv_completion_provider_finalize (GObject *object)
IdeLangservCompletionProviderPrivate *priv = ide_langserv_completion_provider_get_instance_private (self);
g_clear_object (&priv->client);
+ g_clear_pointer (&priv->word, g_free);
G_OBJECT_CLASS (ide_langserv_completion_provider_parent_class)->finalize (object);
}
@@ -182,170 +162,93 @@ ide_langserv_completion_provider_set_client (IdeLangservCompletionProvider *self
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_CLIENT]);
}
-static gchar *
-ide_langserv_completion_provider_get_name (GtkSourceCompletionProvider *provider)
-{
- return g_strdup ("Rust");
-}
-
static gint
-ide_langserv_completion_provider_get_priority (GtkSourceCompletionProvider *provider)
+ide_langserv_completion_provider_get_priority (IdeCompletionProvider *provider)
{
return IDE_LANGSERV_COMPLETION_PROVIDER_PRIORITY;
}
-static gboolean
-ide_langserv_completion_provider_match (GtkSourceCompletionProvider *provider,
- GtkSourceCompletionContext *context)
-{
- GtkSourceCompletionActivation activation;
- GtkTextIter iter;
-
- g_assert (IDE_IS_LANGSERV_COMPLETION_PROVIDER (provider));
- g_assert (GTK_SOURCE_IS_COMPLETION_CONTEXT (context));
-
- if (!gtk_source_completion_context_get_iter (context, &iter))
- return FALSE;
-
- activation = gtk_source_completion_context_get_activation (context);
-
- if (activation == GTK_SOURCE_COMPLETION_ACTIVATION_INTERACTIVE)
- {
- if (gtk_text_iter_starts_line (&iter) ||
- !gtk_text_iter_backward_char (&iter) ||
- g_unichar_isspace (gtk_text_iter_get_char (&iter)))
- return FALSE;
- }
-
- if (ide_completion_provider_context_in_comment (context))
- return FALSE;
-
- return TRUE;
-}
-
static void
ide_langserv_completion_provider_complete_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
+ IdeLangservCompletionProviderPrivate *priv;
+ IdeLangservCompletionProvider *self;
IdeLangservClient *client = (IdeLangservClient *)object;
- g_autoptr(CompletionState) state = user_data;
g_autoptr(GVariant) return_value = NULL;
+ g_autoptr(IdeTask) task = user_data;
g_autoptr(GError) error = NULL;
- GQueue queue = G_QUEUE_INIT;
- GVariant *node;
- GVariantIter iter;
+ IdeLangservCompletionResults *ret;
IDE_ENTRY;
g_assert (IDE_IS_LANGSERV_CLIENT (client));
g_assert (G_IS_ASYNC_RESULT (result));
- g_assert (state != NULL);
- g_assert (IDE_IS_LANGSERV_COMPLETION_PROVIDER (state->self));
- g_assert (GTK_SOURCE_IS_COMPLETION_CONTEXT (state->context));
if (!ide_langserv_client_call_finish (client, result, &return_value, &error))
{
- /* If we were cancelled, we shouldn't report anything to the context,
- * as it is no longer the active contenxt for completion.
- */
- if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
- IDE_EXIT;
- g_debug ("%s", error->message);
- IDE_GOTO (failure);
+ ide_task_return_error (task, g_steal_pointer (&error));
+ return;
}
- /*
- * TODO: We will want to make a much more optimized version of this using
- * the other completion result work we've done.
- */
-
- g_variant_iter_init (&iter, return_value);
+ self = ide_task_get_source_object (task);
+ priv = ide_langserv_completion_provider_get_instance_private (self);
- while (g_variant_iter_loop (&iter, "v", &node))
- {
- g_autoptr(GtkSourceCompletionItem) item = NULL;
- g_autofree gchar *full_label = NULL;
- const gchar *label;
- const gchar *detail;
- const gchar *icon_name = NULL;
- gboolean success;
- gint64 kind = 0;
-
- success = JSONRPC_MESSAGE_PARSE (node,
- "label", JSONRPC_MESSAGE_GET_STRING (&label),
- "detail", JSONRPC_MESSAGE_GET_STRING (&detail)
- );
-
- if (!success)
- {
- IDE_TRACE_MSG ("Failed to extract completion item from node");
- continue;
- }
-
- /* Optional kind field */
- JSONRPC_MESSAGE_PARSE (node, "kind", JSONRPC_MESSAGE_GET_INT64 (&kind));
- kind = ide_langserv_decode_completion_kind (kind);
- if (kind != IDE_SYMBOL_NONE)
- icon_name = ide_symbol_kind_get_icon_name (kind);
-
- if (label != NULL && detail != NULL)
- full_label = g_strdup_printf ("%s : %s", label, detail);
- else
- full_label = g_strdup (label);
-
- item = g_object_new (GTK_SOURCE_TYPE_COMPLETION_ITEM,
- "icon-name", icon_name,
- "label", full_label,
- "text", label,
- NULL);
-
- g_queue_push_tail (&queue, g_steal_pointer (&item));
- }
-
-failure:
- gtk_source_completion_context_add_proposals (state->context,
- GTK_SOURCE_COMPLETION_PROVIDER (state->self),
- queue.head,
- TRUE);
+ ret = ide_langserv_completion_results_new (return_value);
+ if (priv->word != NULL && *priv->word != 0)
+ ide_langserv_completion_results_refilter (ret, priv->word);
- g_queue_foreach (&queue, (GFunc)g_object_unref, NULL);
- g_queue_clear (&queue);
+ ide_task_return_object (task, g_steal_pointer (&ret));
IDE_EXIT;
}
static void
-ide_langserv_completion_provider_populate (GtkSourceCompletionProvider *provider,
- GtkSourceCompletionContext *context)
+ide_langserv_completion_provider_populate_async (IdeCompletionProvider *provider,
+ IdeCompletionContext *context,
+ GCancellable *cancellable,
+ GListModel **proposals,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
IdeLangservCompletionProvider *self = (IdeLangservCompletionProvider *)provider;
IdeLangservCompletionProviderPrivate *priv = ide_langserv_completion_provider_get_instance_private (self);
+ g_autoptr(IdeTask) task = NULL;
g_autoptr(GVariant) params = NULL;
- g_autoptr(GCancellable) cancellable = NULL;
- g_autoptr(CompletionState) state = NULL;
g_autofree gchar *uri = NULL;
- GtkTextIter iter;
- IdeBuffer *buffer;
+ GtkTextIter iter, end;
+ GtkTextBuffer *buffer;
gint line;
gint column;
IDE_ENTRY;
g_assert (IDE_IS_LANGSERV_COMPLETION_PROVIDER (self));
- g_assert (GTK_SOURCE_IS_COMPLETION_CONTEXT (context));
+ g_assert (IDE_IS_COMPLETION_CONTEXT (context));
+ g_assert (proposals != NULL);
+
+ *proposals = NULL;
+
+ task = ide_task_new (self, cancellable, callback, user_data);
+ ide_task_set_source_tag (task, ide_langserv_completion_provider_populate_async);
if (priv->client == NULL)
{
- IDE_TRACE_MSG ("No client set, cannot provide proposals");
- gtk_source_completion_context_add_proposals (context, provider, NULL, TRUE);
+ ide_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ "No client for completion");
IDE_EXIT;
}
- gtk_source_completion_context_get_iter (context, &iter);
+ ide_completion_context_get_bounds (context, &iter, &end);
- buffer = IDE_BUFFER (gtk_text_iter_get_buffer (&iter));
- uri = ide_buffer_get_uri (buffer);
+ g_clear_pointer (&priv->word, g_free);
+ priv->word = ide_completion_context_get_word (context);
+
+ buffer = ide_completion_context_get_buffer (context);
+ uri = ide_buffer_get_uri (IDE_BUFFER (buffer));
line = gtk_text_iter_get_line (&iter);
column = gtk_text_iter_get_line_offset (&iter);
@@ -360,32 +263,119 @@ ide_langserv_completion_provider_populate (GtkSourceCompletionProvider *provider
"}"
);
- cancellable = g_cancellable_new ();
-
- g_signal_connect_data (context,
- "cancelled",
- G_CALLBACK (g_cancellable_cancel),
- g_object_ref (cancellable),
- (GClosureNotify)g_object_unref,
- G_CONNECT_SWAPPED);
-
- state = completion_state_new (self, context);
-
ide_langserv_client_call_async (priv->client,
"textDocument/completion",
params,
cancellable,
ide_langserv_completion_provider_complete_cb,
- g_steal_pointer (&state));
+ g_steal_pointer (&task));
IDE_EXIT;
}
+static GListModel *
+ide_langserv_completion_provider_populate_finish (IdeCompletionProvider *provider,
+ GAsyncResult *result,
+ GError **error)
+{
+ GListModel *ret;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_COMPLETION_PROVIDER (provider));
+ g_assert (IDE_IS_TASK (result));
+
+ ret = ide_task_propagate_object (IDE_TASK (result), error);
+
+ IDE_RETURN (ret);
+}
+
+static gboolean
+ide_langserv_completion_provider_refilter (IdeCompletionProvider *provider,
+ IdeCompletionContext *context,
+ GListModel *model)
+{
+ IdeLangservCompletionResults *results = (IdeLangservCompletionResults *)model;
+ g_autofree gchar *word = NULL;
+
+ g_assert (IDE_IS_LANGSERV_COMPLETION_PROVIDER (provider));
+ g_assert (IDE_IS_COMPLETION_CONTEXT (context));
+ g_assert (IDE_IS_LANGSERV_COMPLETION_RESULTS (results));
+
+ word = ide_completion_context_get_word (context);
+ ide_langserv_completion_results_refilter (results, word);
+
+ return TRUE;
+}
+
+static void
+ide_langserv_completion_provider_display_proposal (IdeCompletionProvider *provider,
+ IdeCompletionListBoxRow *row,
+ IdeCompletionContext *context,
+ const gchar *typed_text,
+ IdeCompletionProposal *proposal)
+{
+ IdeLangservCompletionItem *item = (IdeLangservCompletionItem *)proposal;
+ g_autofree gchar *markup = NULL;
+
+ g_assert (IDE_IS_LANGSERV_COMPLETION_PROVIDER (provider));
+ g_assert (IDE_IS_COMPLETION_LIST_BOX_ROW (row));
+ g_assert (IDE_IS_COMPLETION_CONTEXT (context));
+ g_assert (IDE_IS_LANGSERV_COMPLETION_ITEM (proposal));
+
+ markup = ide_langserv_completion_item_get_markup (item, typed_text);
+
+ ide_completion_list_box_row_set_icon_name (row, ide_langserv_completion_item_get_icon_name (item));
+ ide_completion_list_box_row_set_left (row, NULL);
+ ide_completion_list_box_row_set_center_markup (row, markup);
+ ide_completion_list_box_row_set_right (row, NULL);
+}
+
+static void
+ide_langserv_completion_provider_activate_proposal (IdeCompletionProvider *provider,
+ IdeCompletionContext *context,
+ IdeCompletionProposal *proposal,
+ const GdkEventKey *key)
+{
+ g_autoptr(IdeSnippet) snippet = NULL;
+ GtkTextBuffer *buffer;
+ GtkTextView *view;
+ GtkTextIter begin, end;
+
+ g_assert (IDE_IS_COMPLETION_PROVIDER (provider));
+ g_assert (IDE_IS_COMPLETION_CONTEXT (context));
+ g_assert (IDE_IS_LANGSERV_COMPLETION_ITEM (proposal));
+
+ buffer = ide_completion_context_get_buffer (context);
+ view = ide_completion_context_get_view (context);
+
+ snippet = ide_langserv_completion_item_get_snippet (IDE_LANGSERV_COMPLETION_ITEM (proposal));
+
+ gtk_text_buffer_begin_user_action (buffer);
+ if (ide_completion_context_get_bounds (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);
+}
+
+static gchar *
+ide_langserv_completion_provider_get_comment (IdeCompletionProvider *provider,
+ IdeCompletionProposal *proposal)
+{
+ g_assert (IDE_IS_COMPLETION_PROVIDER (provider));
+ g_assert (IDE_IS_LANGSERV_COMPLETION_ITEM (proposal));
+
+ return g_strdup (ide_langserv_completion_item_get_detail (IDE_LANGSERV_COMPLETION_ITEM (proposal)));
+}
+
static void
-source_completion_provider_iface_init (GtkSourceCompletionProviderIface *iface)
+provider_iface_init (IdeCompletionProviderInterface *iface)
{
- iface->get_name = ide_langserv_completion_provider_get_name;
iface->get_priority = ide_langserv_completion_provider_get_priority;
- iface->match = ide_langserv_completion_provider_match;
- iface->populate = ide_langserv_completion_provider_populate;
+ iface->populate_async = ide_langserv_completion_provider_populate_async;
+ iface->populate_finish = ide_langserv_completion_provider_populate_finish;
+ iface->refilter = ide_langserv_completion_provider_refilter;
+ iface->display_proposal = ide_langserv_completion_provider_display_proposal;
+ iface->activate_proposal = ide_langserv_completion_provider_activate_proposal;
+ iface->get_comment = ide_langserv_completion_provider_get_comment;
}
diff --git a/src/libide/langserv/ide-langserv-completion-provider.h
b/src/libide/langserv/ide-langserv-completion-provider.h
index b88e94e94..cd664852d 100644
--- a/src/libide/langserv/ide-langserv-completion-provider.h
+++ b/src/libide/langserv/ide-langserv-completion-provider.h
@@ -39,14 +39,7 @@ struct _IdeLangservCompletionProviderClass
IdeObjectClass parent_class;
/*< private >*/
- gpointer _reserved1;
- gpointer _reserved2;
- gpointer _reserved3;
- gpointer _reserved4;
- gpointer _reserved5;
- gpointer _reserved6;
- gpointer _reserved7;
- gpointer _reserved8;
+ gpointer _reserved[8];
};
IDE_AVAILABLE_IN_ALL
diff --git a/src/libide/langserv/ide-langserv-completion-results.c
b/src/libide/langserv/ide-langserv-completion-results.c
new file mode 100644
index 000000000..15a5a8b5f
--- /dev/null
+++ b/src/libide/langserv/ide-langserv-completion-results.c
@@ -0,0 +1,177 @@
+/* ide-langserv-completion-results.c
+ *
+ * Copyright 2018 Christian Hergert <chergert redhat 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/>.
+ */
+
+#include "config.h"
+
+#define G_LOG_DOMAIN "ide-langserv-completion-results.h"
+
+#include "ide-debug.h"
+
+#include "completion/ide-completion-item.h"
+#include "langserv/ide-langserv-completion-item.h"
+#include "langserv/ide-langserv-completion-results.h"
+
+struct _IdeLangservCompletionResults
+{
+ GObject parent_instance;
+ GVariant *results;
+ GArray *items;
+};
+
+typedef struct
+{
+ guint index;
+ guint priority;
+} Item;
+
+static void list_model_iface_init (GListModelInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (IdeLangservCompletionResults, ide_langserv_completion_results, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, list_model_iface_init))
+
+static void
+ide_langserv_completion_results_finalize (GObject *object)
+{
+ IdeLangservCompletionResults *self = (IdeLangservCompletionResults *)object;
+
+ g_clear_pointer (&self->results, g_variant_unref);
+ g_clear_pointer (&self->items, g_array_unref);
+
+ G_OBJECT_CLASS (ide_langserv_completion_results_parent_class)->finalize (object);
+}
+
+static void
+ide_langserv_completion_results_class_init (IdeLangservCompletionResultsClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = ide_langserv_completion_results_finalize;
+}
+
+static void
+ide_langserv_completion_results_init (IdeLangservCompletionResults *self)
+{
+ self->items = g_array_new (FALSE, FALSE, sizeof (Item));
+}
+
+IdeLangservCompletionResults *
+ide_langserv_completion_results_new (GVariant *results)
+{
+ IdeLangservCompletionResults *self;
+
+ g_return_val_if_fail (results != NULL, NULL);
+
+ self = g_object_new (IDE_TYPE_LANGSERV_COMPLETION_RESULTS, NULL);
+ self->results = g_variant_ref_sink (results);
+
+ ide_langserv_completion_results_refilter (self, NULL);
+
+ return self;
+}
+
+static GType
+ide_langserv_completion_results_get_item_type (GListModel *model)
+{
+ return IDE_TYPE_LANGSERV_COMPLETION_ITEM;
+}
+
+static guint
+ide_langserv_completion_results_get_n_items (GListModel *model)
+{
+ IdeLangservCompletionResults *self = (IdeLangservCompletionResults *)model;
+
+ g_assert (IDE_IS_LANGSERV_COMPLETION_RESULTS (self));
+
+ return self->results ? g_variant_n_children (self->results) : 0;
+}
+
+static gpointer
+ide_langserv_completion_results_get_item (GListModel *model,
+ guint position)
+{
+ IdeLangservCompletionResults *self = (IdeLangservCompletionResults *)model;
+ g_autoptr(GVariant) child = NULL;
+
+ g_assert (IDE_IS_LANGSERV_COMPLETION_RESULTS (self));
+ g_assert (self->results != NULL);
+
+ child = g_variant_get_child_value (self->results, position);
+
+ return ide_langserv_completion_item_new (child);
+}
+
+static void
+list_model_iface_init (GListModelInterface *iface)
+{
+ iface->get_item = ide_langserv_completion_results_get_item;
+ iface->get_n_items = ide_langserv_completion_results_get_n_items;
+ iface->get_item_type = ide_langserv_completion_results_get_item_type;
+}
+
+void
+ide_langserv_completion_results_refilter (IdeLangservCompletionResults *self,
+ const gchar *typed_text)
+{
+ GVariantIter iter;
+ GVariant *node;
+ guint index = 0;
+ guint old_len;
+
+ g_return_if_fail (IDE_IS_LANGSERV_COMPLETION_RESULTS (self));
+
+ if ((old_len = self->items->len))
+ g_array_remove_range (self->items, 0, old_len);
+
+ if (self->results == NULL)
+ return;
+
+ if (typed_text == NULL || *typed_text == 0)
+ {
+ guint n_items = g_variant_n_children (self->results);
+
+ for (guint i = 0; i < n_items; i++)
+ {
+ Item item = { i };
+ g_array_append_val (self->items, item);
+ }
+
+ g_list_model_items_changed (G_LIST_MODEL (self), 0, old_len, n_items);
+
+ return;
+ }
+
+ g_variant_iter_init (&iter, self->results);
+
+ while (g_variant_iter_loop (&iter, "v", &node))
+ {
+ const gchar *detail;
+ guint priority;
+
+ g_variant_lookup (node, "detail", "&s", &detail);
+
+ if (ide_completion_item_fuzzy_match (detail, typed_text, &priority))
+ {
+ Item item = { .index = index, .priority = priority };
+ g_array_append_val (self->items, item);
+ }
+
+ index++;
+ }
+
+ g_list_model_items_changed (G_LIST_MODEL (self), 0, old_len, index);
+}
diff --git a/src/libide/langserv/ide-langserv-completion-results.h
b/src/libide/langserv/ide-langserv-completion-results.h
new file mode 100644
index 000000000..1887e3b40
--- /dev/null
+++ b/src/libide/langserv/ide-langserv-completion-results.h
@@ -0,0 +1,36 @@
+/* ide-langserv-completion-results.h
+ *
+ * Copyright 2018 Christian Hergert <chergert redhat 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/>.
+ */
+
+#pragma once
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_LANGSERV_COMPLETION_RESULTS (ide_langserv_completion_results_get_type())
+
+IDE_AVAILABLE_IN_3_30
+G_DECLARE_FINAL_TYPE (IdeLangservCompletionResults, ide_langserv_completion_results, IDE,
LANGSERV_COMPLETION_RESULTS, GObject)
+
+IDE_AVAILABLE_IN_3_30
+IdeLangservCompletionResults *ide_langserv_completion_results_new (GVariant
*results);
+IDE_AVAILABLE_IN_3_30
+void ide_langserv_completion_results_refilter (IdeLangservCompletionResults *self,
+ const gchar
*typed_text);
+
+G_END_DECLS
diff --git a/src/libide/langserv/meson.build b/src/libide/langserv/meson.build
index bc765159b..6e70a4630 100644
--- a/src/libide/langserv/meson.build
+++ b/src/libide/langserv/meson.build
@@ -1,6 +1,8 @@
langserv_headers = [
'ide-langserv-client.h',
+ 'ide-langserv-completion-item.h',
'ide-langserv-completion-provider.h',
+ 'ide-langserv-completion-results.h',
'ide-langserv-diagnostic-provider.h',
'ide-langserv-formatter.h',
'ide-langserv-highlighter.h',
@@ -14,7 +16,9 @@ langserv_headers = [
langserv_sources = [
'ide-langserv-client.c',
+ 'ide-langserv-completion-item.c',
'ide-langserv-completion-provider.c',
+ 'ide-langserv-completion-results.c',
'ide-langserv-diagnostic-provider.c',
'ide-langserv-formatter.c',
'ide-langserv-highlighter.c',
diff --git a/src/plugins/go-langserv/go_langserver_plugin.py b/src/plugins/go-langserv/go_langserver_plugin.py
index 630b2b59b..ad31384e0 100644
--- a/src/plugins/go-langserv/go_langserver_plugin.py
+++ b/src/plugins/go-langserv/go_langserver_plugin.py
@@ -111,7 +111,7 @@ class GoSymbolResolver(Ide.LangservSymbolResolver, Ide.SymbolResolver):
## This is supported as of a few weeks ago, but at least for me, it seems
## awfully crashy, so I'm going to leave it disabled by default so as to
## not give a bad impression
-#class GoCompletionProvider(Ide.LangservCompletionProvider, GtkSource.CompletionProvider,
Ide.CompletionProvider):
+#class GoCompletionProvider(Ide.LangservCompletionProvider, Ide.CompletionProvider):
# def do_load(self, context):
# GoService.bind_client(self)
diff --git a/src/plugins/rust-langserv/rust_langserv_plugin.py
b/src/plugins/rust-langserv/rust_langserv_plugin.py
index 1a1039edc..a56560445 100644
--- a/src/plugins/rust-langserv/rust_langserv_plugin.py
+++ b/src/plugins/rust-langserv/rust_langserv_plugin.py
@@ -27,12 +27,10 @@ import gi
import os
gi.require_version('Ide', '1.0')
-gi.require_version('GtkSource', '3.0')
from gi.repository import GLib
from gi.repository import Gio
from gi.repository import GObject
-from gi.repository import GtkSource
from gi.repository import Ide
DEV_MODE = False
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]