[gnome-builder] lsp: add lsp search provider



commit 00347004bbc2d4e54ff0860a5612ef9ce2fcfe84
Author: peter <blackwolf12333 gmail com>
Date:   Sat Feb 20 13:05:59 2021 +0100

    lsp: add lsp search provider

 src/libide/lsp/ide-lsp-search-provider.c           | 270 +++++++++++++++++++++
 src/libide/lsp/ide-lsp-search-provider.h           |  50 ++++
 .../lsp/ide-lsp-search-result.c}                   |  69 +++---
 .../lsp/ide-lsp-search-result.h}                   |  20 +-
 src/libide/lsp/libide-lsp.h                        |   1 +
 src/libide/lsp/meson.build                         |   4 +
 src/libide/meson.build                             |   2 +-
 src/libide/search/ide-search-engine.c              |  62 +++--
 src/libide/search/ide-search-provider.c            |  17 ++
 src/libide/search/ide-search-provider.h            |   5 +
 src/libide/search/meson.build                      |   2 +
 src/plugins/rust-analyzer/meson.build              |   1 -
 .../rust-analyzer/rust-analyzer-search-provider.c  | 216 +----------------
 .../rust-analyzer/rust-analyzer-search-provider.h  |   7 +-
 src/plugins/rust-analyzer/rust-analyzer-service.c  |  10 -
 src/plugins/rust-analyzer/rust-analyzer.c          |   4 +
 src/plugins/rust-analyzer/rust-analyzer.plugin     |   1 +
 17 files changed, 455 insertions(+), 286 deletions(-)
---
diff --git a/src/libide/lsp/ide-lsp-search-provider.c b/src/libide/lsp/ide-lsp-search-provider.c
new file mode 100644
index 000000000..d6a583dfc
--- /dev/null
+++ b/src/libide/lsp/ide-lsp-search-provider.c
@@ -0,0 +1,270 @@
+/* ide-lsp-search-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 "config.h"
+
+#define G_LOG_DOMAIN "ide-lsp-search-provider"
+
+#include <libide-search.h>
+#include <jsonrpc-glib.h>
+
+#include "ide-lsp-client.h"
+#include "ide-lsp-util.h"
+#include "ide-lsp-search-provider.h"
+#include "ide-lsp-search-result.h"
+
+typedef struct
+{
+  IdeLspClient *client;
+} IdeLspSearchProviderPrivate;
+
+static void provider_iface_init (IdeSearchProviderInterface *iface);
+
+G_DEFINE_ABSTRACT_TYPE_WITH_CODE (IdeLspSearchProvider, ide_lsp_search_provider, IDE_TYPE_OBJECT,
+                                  G_ADD_PRIVATE (IdeLspSearchProvider)
+                                  G_IMPLEMENT_INTERFACE (IDE_TYPE_SEARCH_PROVIDER, provider_iface_init))
+
+enum {
+  PROP_0,
+  PROP_CLIENT,
+  N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+/**
+ * ide_lsp_search_provider_get_client:
+ * @self: An #IdeLspSearchProvider
+ *
+ * Gets the client for the search provider.
+ *
+ * Returns: (transfer none) (nullable): An #IdeLspClient or %NULL
+ */
+IdeLspClient *
+ide_lsp_search_provider_get_client (IdeLspSearchProvider *self)
+{
+  IdeLspSearchProviderPrivate *priv = ide_lsp_search_provider_get_instance_private (self);
+
+  g_return_val_if_fail (IDE_IS_LSP_SEARCH_PROVIDER (self), NULL);
+
+  return priv->client;
+}
+
+void
+ide_lsp_search_provider_set_client (IdeLspSearchProvider *self,
+                                    IdeLspClient               *client)
+{
+  IdeLspSearchProviderPrivate *priv = ide_lsp_search_provider_get_instance_private (self);
+
+  g_return_if_fail (IDE_IS_LSP_SEARCH_PROVIDER (self));
+  g_return_if_fail (!client || IDE_IS_LSP_CLIENT (client));
+
+  if (priv->client != NULL)
+    g_clear_pointer (&priv->client, g_object_unref);
+  priv->client = g_object_ref (client);
+}
+
+static void
+ide_lsp_search_provider_finalize (GObject *object)
+{
+  IdeLspSearchProvider *self = (IdeLspSearchProvider *)object;
+  IdeLspSearchProviderPrivate *priv = ide_lsp_search_provider_get_instance_private (self);
+
+  g_clear_object (&priv->client);
+
+  G_OBJECT_CLASS (ide_lsp_search_provider_parent_class)->finalize (object);
+}
+
+static void
+ide_lsp_search_provider_get_property (GObject    *object,
+                                      guint       prop_id,
+                                      GValue     *value,
+                                      GParamSpec *pspec)
+{
+  IdeLspSearchProvider *self = IDE_LSP_SEARCH_PROVIDER (object);
+
+  switch (prop_id)
+    {
+    case PROP_CLIENT:
+      g_value_set_object (value, ide_lsp_search_provider_get_client (self));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+ide_lsp_search_provider_set_property (GObject      *object,
+                                      guint         prop_id,
+                                      const GValue *value,
+                                      GParamSpec   *pspec)
+{
+  IdeLspSearchProvider *self = IDE_LSP_SEARCH_PROVIDER (object);
+
+  switch (prop_id)
+    {
+    case PROP_CLIENT:
+      ide_lsp_search_provider_set_client (self, g_value_get_object (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+ide_lsp_search_provider_class_init (IdeLspSearchProviderClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = ide_lsp_search_provider_finalize;
+  object_class->get_property = ide_lsp_search_provider_get_property;
+  object_class->set_property = ide_lsp_search_provider_set_property;
+
+  properties[PROP_CLIENT] =
+    g_param_spec_object ("client",
+                         "client",
+                         "The Language Server client",
+                         IDE_TYPE_LSP_CLIENT,
+                         (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+ide_lsp_search_provider_init (IdeLspSearchProvider *self)
+{
+}
+
+static void
+ide_lsp_search_provider_search_cb (GObject      *source_object,
+                                   GAsyncResult *res,
+                                   gpointer      user_data)
+{
+  IdeLspClient *client = (IdeLspClient *) source_object;
+  GPtrArray *ar;
+  g_autoptr(IdeTask) task = user_data;
+  g_autoptr(GVariant) result = NULL;
+  g_autoptr(GVariantIter) iter = NULL;
+  GVariant *symbol_information;
+  GError *error = NULL;
+
+  IDE_ENTRY;
+
+  ar = g_ptr_array_new ();
+
+  ide_lsp_client_call_finish (client, res, &result, &error);
+  if (error != NULL)
+    {
+      ide_task_return_error (task, error);
+      return;
+    }
+
+  iter = g_variant_iter_new (result);
+
+  while (g_variant_iter_loop (iter, "v", &symbol_information))
+    {
+      g_autoptr(GFile) gfile = NULL;
+      g_autoptr(IdeLocation) location = NULL;
+      const gchar *title;
+      const gchar *uri;
+      gint64 kind;
+      gint64 line, character;
+      IdeSymbolKind symbol_kind;
+      const gchar *icon_name;
+
+      JSONRPC_MESSAGE_PARSE (symbol_information,
+                             "name", JSONRPC_MESSAGE_GET_STRING (&title),
+                             "kind", JSONRPC_MESSAGE_GET_INT64 (&kind),
+                             "location", "{",
+                               "uri", JSONRPC_MESSAGE_GET_STRING (&uri),
+                               "range", "{",
+                                 "start", "{",
+                                   "line", JSONRPC_MESSAGE_GET_INT64 (&line),
+                                   "character", JSONRPC_MESSAGE_GET_INT64 (&character),
+                                 "}",
+                               "}",
+                             "}");
+
+      symbol_kind = ide_lsp_decode_symbol_kind (kind);
+      icon_name = ide_symbol_kind_get_icon_name (symbol_kind);
+
+      gfile = g_file_new_for_uri (uri);
+      location = ide_location_new (gfile, line, character);
+
+      g_ptr_array_add (ar, ide_lsp_search_result_new (title, g_file_get_basename (gfile), location, 
icon_name));
+    }
+
+  ide_task_return_pointer (task,
+                           g_steal_pointer(&ar),
+                           g_ptr_array_unref);
+
+  IDE_EXIT;
+}
+
+static void
+ide_lsp_search_provider_search_async (IdeSearchProvider   *provider,
+                                      const gchar         *query,
+                                      guint                max_results,
+                                      GCancellable        *cancellable,
+                                      GAsyncReadyCallback  callback,
+                                      gpointer             user_data)
+{
+  IdeLspSearchProvider *self = (IdeLspSearchProvider *)provider;
+  IdeLspSearchProviderPrivate *priv = ide_lsp_search_provider_get_instance_private (self);
+  g_autoptr(IdeTask) task = NULL;
+  g_autoptr(GVariant) params = NULL;
+
+  IDE_ENTRY;
+
+  g_return_if_fail (IDE_IS_MAIN_THREAD ());
+  g_return_if_fail (IDE_IS_LSP_SEARCH_PROVIDER (self));
+  g_return_if_fail (query != NULL);
+  g_assert (priv->client != NULL);
+  g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  task = ide_task_new (self, cancellable, callback, user_data);
+  ide_task_set_source_tag (task, ide_lsp_search_provider_search_async);
+
+  params = JSONRPC_MESSAGE_NEW ("query", JSONRPC_MESSAGE_PUT_STRING (query));
+
+  ide_lsp_client_call_async (priv->client,
+                             "workspace/symbol",
+                             params,
+                             cancellable,
+                             ide_lsp_search_provider_search_cb,
+                             g_steal_pointer (&task));
+
+  IDE_EXIT;
+}
+
+static GPtrArray *
+ide_lsp_search_provider_search_finish (IdeSearchProvider  *provider,
+                                       GAsyncResult       *result,
+                                       GError            **error)
+{
+  return ide_task_propagate_pointer (IDE_TASK (result), error);
+}
+
+static void
+provider_iface_init (IdeSearchProviderInterface *iface)
+{
+  iface->search_async = ide_lsp_search_provider_search_async;
+  iface->search_finish = ide_lsp_search_provider_search_finish;
+}
diff --git a/src/libide/lsp/ide-lsp-search-provider.h b/src/libide/lsp/ide-lsp-search-provider.h
new file mode 100644
index 000000000..7f8964b99
--- /dev/null
+++ b/src/libide/lsp/ide-lsp-search-provider.h
@@ -0,0 +1,50 @@
+/* ide-lsp-search-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
+
+#if !defined (IDE_LSP_INSIDE) && !defined (IDE_LSP_COMPILATION)
+# error "Only <libide-lsp.h> can be included directly."
+#endif
+
+#include "ide-lsp-client.h"
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_LSP_SEARCH_PROVIDER (ide_lsp_search_provider_get_type())
+
+IDE_AVAILABLE_IN_3_40
+G_DECLARE_DERIVABLE_TYPE (IdeLspSearchProvider, ide_lsp_search_provider, IDE, LSP_SEARCH_PROVIDER, IdeObject)
+
+struct _IdeLspSearchProviderClass
+{
+  IdeObjectClass parent_class;
+
+  /*< private >*/
+  gpointer _reserved[8];
+};
+
+IDE_AVAILABLE_IN_3_40
+IdeLspClient               *ide_lsp_search_provider_get_client (IdeLspSearchProvider *self);
+IDE_AVAILABLE_IN_3_40
+void                        ide_lsp_search_provider_set_client (IdeLspSearchProvider *self,
+                                                                      IdeLspClient               *client);
+
+G_END_DECLS
diff --git a/src/plugins/rust-analyzer/rust-analyzer-search-result.c b/src/libide/lsp/ide-lsp-search-result.c
similarity index 56%
rename from src/plugins/rust-analyzer/rust-analyzer-search-result.c
rename to src/libide/lsp/ide-lsp-search-result.c
index a7c9e2201..f2ddf6f4f 100644
--- a/src/plugins/rust-analyzer/rust-analyzer-search-result.c
+++ b/src/libide/lsp/ide-lsp-search-result.c
@@ -1,4 +1,4 @@
-/* rust-analyzer-search-result.c
+/* ide-lsp-search-result.c
  *
  * Copyright 2020 Günther Wagner <info gunibert de>
  *
@@ -18,16 +18,19 @@
  * SPDX-License-Identifier: GPL-3.0-or-later
  */
 
-#include "rust-analyzer-search-result.h"
+#include "config.h"
+
+#include "ide-lsp-search-result.h"
+#include <libide-core.h>
 #include <libide-editor.h>
 
-struct _RustAnalyzerSearchResult
+struct _IdeLspSearchResult
 {
   IdeSearchResult  parent_instance;
   IdeLocation     *location;
 };
 
-G_DEFINE_TYPE (RustAnalyzerSearchResult, rust_analyzer_search_result, IDE_TYPE_SEARCH_RESULT)
+G_DEFINE_TYPE (IdeLspSearchResult, ide_lsp_search_result, IDE_TYPE_SEARCH_RESULT)
 
 enum {
   PROP_0,
@@ -37,13 +40,13 @@ enum {
 
 static GParamSpec *properties [N_PROPS];
 
-RustAnalyzerSearchResult *
-rust_analyzer_search_result_new (const gchar *title,
-                                 const gchar *subtitle,
-                                 IdeLocation *location,
-                                 const gchar *icon_name)
+IdeLspSearchResult *
+ide_lsp_search_result_new (const gchar *title,
+                           const gchar *subtitle,
+                           IdeLocation *location,
+                           const gchar *icon_name)
 {
-  return g_object_new (RUST_TYPE_ANALYZER_SEARCH_RESULT,
+  return g_object_new (IDE_TYPE_LSP_SEARCH_RESULT,
                        "title", title,
                        "subtitle", subtitle,
                        "location", location,
@@ -54,22 +57,22 @@ rust_analyzer_search_result_new (const gchar *title,
 }
 
 static void
-rust_analyzer_search_result_finalize (GObject *object)
+ide_lsp_search_result_finalize (GObject *object)
 {
-  RustAnalyzerSearchResult *self = (RustAnalyzerSearchResult *)object;
+  IdeLspSearchResult *self = (IdeLspSearchResult *)object;
 
   g_clear_object (&self->location);
 
-  G_OBJECT_CLASS (rust_analyzer_search_result_parent_class)->finalize (object);
+  G_OBJECT_CLASS (ide_lsp_search_result_parent_class)->finalize (object);
 }
 
 static void
-rust_analyzer_search_result_get_property (GObject    *object,
-                                          guint       prop_id,
-                                          GValue     *value,
-                                          GParamSpec *pspec)
+ide_lsp_search_result_get_property (GObject    *object,
+                                    guint       prop_id,
+                                    GValue     *value,
+                                    GParamSpec *pspec)
 {
-  RustAnalyzerSearchResult *self = RUST_ANALYZER_SEARCH_RESULT (object);
+  IdeLspSearchResult *self = IDE_LSP_SEARCH_RESULT (object);
 
   switch (prop_id)
     {
@@ -82,12 +85,12 @@ rust_analyzer_search_result_get_property (GObject    *object,
 }
 
 static void
-rust_analyzer_search_result_set_property (GObject      *object,
-                                          guint         prop_id,
-                                          const GValue *value,
-                                          GParamSpec   *pspec)
+ide_lsp_search_result_set_property (GObject      *object,
+                                    guint         prop_id,
+                                    const GValue *value,
+                                    GParamSpec   *pspec)
 {
-  RustAnalyzerSearchResult *self = RUST_ANALYZER_SEARCH_RESULT (object);
+  IdeLspSearchResult *self = IDE_LSP_SEARCH_RESULT (object);
 
   switch (prop_id)
     {
@@ -100,15 +103,15 @@ rust_analyzer_search_result_set_property (GObject      *object,
 }
 
 static void
-rust_analyzer_search_result_activate (IdeSearchResult *result,
-                                      GtkWidget       *last_focus)
+ide_lsp_search_result_activate (IdeSearchResult *result,
+                                GtkWidget       *last_focus)
 {
 
-  RustAnalyzerSearchResult *self = (RustAnalyzerSearchResult *)result;
+  IdeLspSearchResult *self = (IdeLspSearchResult *)result;
   IdeWorkspace *workspace;
   IdeSurface *editor;
 
-  g_assert (RUST_IS_ANALYZER_SEARCH_RESULT (self));
+  g_assert (IDE_IS_LSP_SEARCH_RESULT (self));
   g_assert (GTK_IS_WIDGET (last_focus));
 
   if (!last_focus)
@@ -120,15 +123,15 @@ rust_analyzer_search_result_activate (IdeSearchResult *result,
 }
 
 static void
-rust_analyzer_search_result_class_init (RustAnalyzerSearchResultClass *klass)
+ide_lsp_search_result_class_init (IdeLspSearchResultClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
   IdeSearchResultClass *search_class = IDE_SEARCH_RESULT_CLASS (klass);
 
-  object_class->finalize = rust_analyzer_search_result_finalize;
-  object_class->get_property = rust_analyzer_search_result_get_property;
-  object_class->set_property = rust_analyzer_search_result_set_property;
-  search_class->activate = rust_analyzer_search_result_activate;
+  object_class->finalize = ide_lsp_search_result_finalize;
+  object_class->get_property = ide_lsp_search_result_get_property;
+  object_class->set_property = ide_lsp_search_result_set_property;
+  search_class->activate = ide_lsp_search_result_activate;
 
   properties [PROP_LOCATION] =
     g_param_spec_object ("location",
@@ -141,6 +144,6 @@ rust_analyzer_search_result_class_init (RustAnalyzerSearchResultClass *klass)
 }
 
 static void
-rust_analyzer_search_result_init (RustAnalyzerSearchResult *self)
+ide_lsp_search_result_init (IdeLspSearchResult *self)
 {
 }
diff --git a/src/plugins/rust-analyzer/rust-analyzer-search-result.h b/src/libide/lsp/ide-lsp-search-result.h
similarity index 56%
rename from src/plugins/rust-analyzer/rust-analyzer-search-result.h
rename to src/libide/lsp/ide-lsp-search-result.h
index 8e9cd60bc..097bf8c39 100644
--- a/src/plugins/rust-analyzer/rust-analyzer-search-result.h
+++ b/src/libide/lsp/ide-lsp-search-result.h
@@ -1,4 +1,4 @@
-/* rust-analyzer-search-result.h
+/* ide-lsp-search-result.h
  *
  * Copyright 2020 Günther Wagner <info gunibert de>
  *
@@ -20,18 +20,24 @@
 
 #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>
 #include <libide-search.h>
 
 G_BEGIN_DECLS
 
-#define RUST_TYPE_ANALYZER_SEARCH_RESULT (rust_analyzer_search_result_get_type())
+#define IDE_TYPE_LSP_SEARCH_RESULT (ide_lsp_search_result_get_type())
 
-G_DECLARE_FINAL_TYPE (RustAnalyzerSearchResult, rust_analyzer_search_result, RUST, ANALYZER_SEARCH_RESULT, 
IdeSearchResult)
+IDE_AVAILABLE_IN_3_40
+G_DECLARE_FINAL_TYPE (IdeLspSearchResult, ide_lsp_search_result, IDE, LSP_SEARCH_RESULT, IdeSearchResult)
 
-RustAnalyzerSearchResult *rust_analyzer_search_result_new (const gchar *title,
-                                                           const gchar *subtitle,
-                                                           IdeLocation *location,
-                                                           const gchar *icon_name);
+IDE_AVAILABLE_IN_3_40
+IdeLspSearchResult *ide_lsp_search_result_new (const gchar *title,
+                                               const gchar *subtitle,
+                                               IdeLocation *location,
+                                               const gchar *icon_name);
 
 G_END_DECLS
diff --git a/src/libide/lsp/libide-lsp.h b/src/libide/lsp/libide-lsp.h
index c8f3e56f4..a0eccb0cc 100644
--- a/src/libide/lsp/libide-lsp.h
+++ b/src/libide/lsp/libide-lsp.h
@@ -36,6 +36,7 @@
 #include "ide-lsp-highlighter.h"
 #include "ide-lsp-hover-provider.h"
 #include "ide-lsp-rename-provider.h"
+#include "ide-lsp-search-provider.h"
 #include "ide-lsp-symbol-node.h"
 #include "ide-lsp-symbol-resolver.h"
 #include "ide-lsp-symbol-tree.h"
diff --git a/src/libide/lsp/meson.build b/src/libide/lsp/meson.build
index cdd6993c1..786e5eb04 100644
--- a/src/libide/lsp/meson.build
+++ b/src/libide/lsp/meson.build
@@ -17,6 +17,7 @@ libide_lsp_public_headers = [
   'ide-lsp-highlighter.h',
   'ide-lsp-hover-provider.h',
   'ide-lsp-rename-provider.h',
+  'ide-lsp-search-provider.h',
   'ide-lsp-symbol-node.h',
   'ide-lsp-symbol-resolver.h',
   'ide-lsp-symbol-tree.h',
@@ -45,6 +46,8 @@ libide_lsp_public_sources = [
   'ide-lsp-highlighter.c',
   'ide-lsp-hover-provider.c',
   'ide-lsp-rename-provider.c',
+  'ide-lsp-search-provider.c',
+  'ide-lsp-search-result.c',
   'ide-lsp-symbol-node.c',
   'ide-lsp-symbol-resolver.c',
   'ide-lsp-symbol-tree.c',
@@ -86,6 +89,7 @@ libide_lsp_deps = [
   libide_projects_dep,
   libide_sourceview_dep,
   libide_threading_dep,
+  libide_editor_dep,
 ]
 
 #
diff --git a/src/libide/meson.build b/src/libide/meson.build
index 14ca19775..7f5dff4f2 100644
--- a/src/libide/meson.build
+++ b/src/libide/meson.build
@@ -16,8 +16,8 @@ subdir('themes')
 subdir('gui')
 subdir('terminal')
 subdir('sourceview')
-subdir('lsp')
 subdir('editor')
+subdir('lsp')
 subdir('greeter')
 if libwebkit_dep.found()
   subdir('webkit')
diff --git a/src/libide/search/ide-search-engine.c b/src/libide/search/ide-search-engine.c
index 1c5b25c17..684e78c83 100644
--- a/src/libide/search/ide-search-engine.c
+++ b/src/libide/search/ide-search-engine.c
@@ -22,6 +22,7 @@
 
 #include "config.h"
 
+#include <libide-plugins.h>
 #include <libpeas/peas.h>
 #include <libide-core.h>
 #include <libide-threading.h>
@@ -34,10 +35,10 @@
 
 struct _IdeSearchEngine
 {
-  IdeObject         parent_instance;
-  PeasExtensionSet *extensions;
-  GPtrArray        *custom_provider;
-  guint             active_count;
+  IdeObject               parent_instance;
+  IdeExtensionSetAdapter *extensions;
+  GPtrArray              *custom_provider;
+  guint                   active_count;
 };
 
 typedef struct
@@ -83,21 +84,31 @@ request_destroy (Request *r)
 }
 
 static void
-on_extension_added_cb (PeasExtensionSet *set,
-                       PeasPluginInfo   *plugin_info,
-                       PeasExtension    *exten,
-                       gpointer          user_data)
+on_extension_added_cb (IdeExtensionSetAdapter *set,
+                       PeasPluginInfo         *plugin_info,
+                       PeasExtension          *exten,
+                       gpointer                user_data)
 {
-  ide_object_append (IDE_OBJECT (user_data), IDE_OBJECT (exten));
+  IdeSearchEngine *self = (IdeSearchEngine *)user_data;
+  IdeSearchProvider *provider = (IdeSearchProvider *)exten;
+  IdeContext *context = ide_object_get_context (IDE_OBJECT (self));
+
+  g_assert (IDE_IS_MAIN_THREAD ());
+  g_assert (plugin_info != NULL);
+  g_assert (IDE_IS_SEARCH_PROVIDER (provider));
+  g_assert (context != NULL);
+  g_assert (IDE_IS_CONTEXT (context));
+
+  ide_search_provider_load (provider, context);
 }
 
 static void
-on_extension_removed_cb (PeasExtensionSet *set,
-                         PeasPluginInfo   *plugin_info,
-                         PeasExtension    *exten,
-                         gpointer          user_data)
+on_extension_removed_cb (IdeExtensionSetAdapter *set,
+                         PeasPluginInfo         *plugin_info,
+                         PeasExtension          *exten,
+                         gpointer                user_data)
 {
-  ide_object_remove (IDE_OBJECT (user_data), IDE_OBJECT (exten));
+// FIXME ??
 }
 
 static void
@@ -115,9 +126,10 @@ ide_search_engine_parent_set (IdeObject *object,
       return;
     }
 
-  self->extensions = peas_extension_set_new (peas_engine_get_default (),
-                                             IDE_TYPE_SEARCH_PROVIDER,
-                                             NULL);
+  self->extensions = ide_extension_set_adapter_new (parent,
+                                                    peas_engine_get_default (),
+                                                    IDE_TYPE_SEARCH_PROVIDER,
+                                                    NULL, NULL);
 
   g_signal_connect (self->extensions,
                     "extension-added",
@@ -129,9 +141,9 @@ ide_search_engine_parent_set (IdeObject *object,
                     G_CALLBACK (on_extension_removed_cb),
                     self);
 
-  peas_extension_set_foreach (self->extensions,
-                              on_extension_added_cb,
-                              self);
+  ide_extension_set_adapter_foreach (self->extensions,
+                                     on_extension_added_cb,
+                                     self);
 }
 
 static void
@@ -289,7 +301,7 @@ _provider_search_async (IdeSearchProvider *provider,
 }
 
 static void
-ide_search_engine_search_foreach (PeasExtensionSet *set,
+ide_search_engine_search_foreach (IdeExtensionSetAdapter *set,
                                   PeasPluginInfo   *plugin_info,
                                   PeasExtension    *exten,
                                   gpointer          user_data)
@@ -297,7 +309,7 @@ ide_search_engine_search_foreach (PeasExtensionSet *set,
   IdeSearchProvider *provider = (IdeSearchProvider *)exten;
   Request *r = user_data;
 
-  g_assert (PEAS_IS_EXTENSION_SET (set));
+  g_assert (IDE_IS_EXTENSION_SET_ADAPTER (set));
   g_assert (plugin_info != NULL);
   g_assert (IDE_IS_SEARCH_PROVIDER (provider));
   g_assert (r != NULL);
@@ -351,9 +363,9 @@ ide_search_engine_search_async (IdeSearchEngine     *self,
   r->outstanding = 0;
   ide_task_set_task_data (task, r, request_destroy);
 
-  peas_extension_set_foreach (self->extensions,
-                              ide_search_engine_search_foreach,
-                              r);
+  ide_extension_set_adapter_foreach (self->extensions,
+                                     ide_search_engine_search_foreach,
+                                     r);
   g_ptr_array_foreach (self->custom_provider,
                        ide_search_engine_search_foreach_custom_provider,
                        r);
diff --git a/src/libide/search/ide-search-provider.c b/src/libide/search/ide-search-provider.c
index 95dd176a3..4934abe1f 100644
--- a/src/libide/search/ide-search-provider.c
+++ b/src/libide/search/ide-search-provider.c
@@ -28,6 +28,12 @@
 
 G_DEFINE_INTERFACE (IdeSearchProvider, ide_search_provider, IDE_TYPE_OBJECT)
 
+static void
+ide_search_provider_real_load (IdeSearchProvider *self,
+                               IdeContext        *context)
+{
+}
+
 static void
 ide_search_provider_real_search_async (IdeSearchProvider   *self,
                                        const gchar         *query,
@@ -62,10 +68,21 @@ ide_search_provider_real_search_finish (IdeSearchProvider  *self,
 static void
 ide_search_provider_default_init (IdeSearchProviderInterface *iface)
 {
+  iface->load = ide_search_provider_real_load;
   iface->search_async = ide_search_provider_real_search_async;
   iface->search_finish = ide_search_provider_real_search_finish;
 }
 
+void
+ide_search_provider_load (IdeSearchProvider   *self,
+                          IdeContext          *context)
+{
+  g_return_if_fail (IDE_IS_SEARCH_PROVIDER (self));
+  g_return_if_fail (IDE_IS_CONTEXT (context));
+
+  IDE_SEARCH_PROVIDER_GET_IFACE (self)->load (self, context);
+}
+
 void
 ide_search_provider_search_async (IdeSearchProvider   *self,
                                   const gchar         *query,
diff --git a/src/libide/search/ide-search-provider.h b/src/libide/search/ide-search-provider.h
index dee906538..9bd158d6c 100644
--- a/src/libide/search/ide-search-provider.h
+++ b/src/libide/search/ide-search-provider.h
@@ -37,6 +37,8 @@ struct _IdeSearchProviderInterface
 {
   GTypeInterface parent_interface;
 
+  void       (*load)          (IdeSearchProvider    *self,
+                               IdeContext           *context);
   void       (*search_async)  (IdeSearchProvider    *self,
                                const gchar          *query,
                                guint                 max_results,
@@ -48,6 +50,9 @@ struct _IdeSearchProviderInterface
                                GError              **error);
 };
 
+IDE_AVAILABLE_IN_3_40
+void       ide_search_provider_load          (IdeSearchProvider *self,
+                                              IdeContext        *context);
 IDE_AVAILABLE_IN_3_32
 void       ide_search_provider_search_async  (IdeSearchProvider    *self,
                                               const gchar          *query,
diff --git a/src/libide/search/meson.build b/src/libide/search/meson.build
index cf73aa91d..760c5a882 100644
--- a/src/libide/search/meson.build
+++ b/src/libide/search/meson.build
@@ -1,3 +1,4 @@
+libide_search_header_dir = join_paths(libide_header_dir, 'search')
 libide_search_header_subdir = join_paths(libide_header_subdir, 'search')
 libide_include_directories += include_directories('.')
 
@@ -38,6 +39,7 @@ libide_search_deps = [
   libpeas_dep,
   libide_core_dep,
   libide_threading_dep,
+  libide_plugins_dep
 ]
 
 #
diff --git a/src/plugins/rust-analyzer/meson.build b/src/plugins/rust-analyzer/meson.build
index 5a34141e4..e81e5846b 100644
--- a/src/plugins/rust-analyzer/meson.build
+++ b/src/plugins/rust-analyzer/meson.build
@@ -16,7 +16,6 @@ plugins_sources += files([
   'rust-analyzer-rename-provider.c',
   'rust-analyzer-transfer.c',
   'rust-analyzer-search-provider.c',
-  'rust-analyzer-search-result.c',
   'rust-analyzer-workbench-addin.c',
   'rust-analyzer-preferences-addin.c',
 ])
diff --git a/src/plugins/rust-analyzer/rust-analyzer-search-provider.c 
b/src/plugins/rust-analyzer/rust-analyzer-search-provider.c
index 8dd921999..838339489 100644
--- a/src/plugins/rust-analyzer/rust-analyzer-search-provider.c
+++ b/src/plugins/rust-analyzer/rust-analyzer-search-provider.c
@@ -18,106 +18,26 @@
  * SPDX-License-Identifier: GPL-3.0-or-later
  */
 
-#define G_LOG_DOMAIN "rust-analyzer-search-provider"
+#include <libide-search.h>
 
 #include "rust-analyzer-search-provider.h"
-#include <libide-search.h>
-#include <jsonrpc-glib.h>
-#include <libide-lsp.h>
 #include "rust-analyzer-service.h"
-#include "rust-analyzer-search-result.h"
 
 struct _RustAnalyzerSearchProvider
 {
-  IdeObject parent_instance;
-
-  IdeLspClient *client;
+  IdeLspSearchProvider parent_instance;
 };
 
 static void provider_iface_init (IdeSearchProviderInterface *iface);
 
 G_DEFINE_TYPE_WITH_CODE (RustAnalyzerSearchProvider,
                          rust_analyzer_search_provider,
-                         IDE_TYPE_OBJECT,
+                         IDE_TYPE_LSP_SEARCH_PROVIDER,
                          G_IMPLEMENT_INTERFACE (IDE_TYPE_SEARCH_PROVIDER, provider_iface_init))
 
-enum {
-  PROP_0,
-  PROP_CLIENT,
-  N_PROPS
-};
-
-static GParamSpec *properties [N_PROPS];
-
-RustAnalyzerSearchProvider *
-rust_analyzer_search_provider_new (void)
-{
-  return g_object_new (RUST_TYPE_ANALYZER_SEARCH_PROVIDER, NULL);
-}
-
-static void
-rust_analyzer_search_provider_finalize (GObject *object)
-{
-  RustAnalyzerSearchProvider *self = (RustAnalyzerSearchProvider *)object;
-
-  g_clear_object (&self->client);
-
-  G_OBJECT_CLASS (rust_analyzer_search_provider_parent_class)->finalize (object);
-}
-
-static void
-rust_analyzer_search_provider_get_property (GObject    *object,
-                                            guint       prop_id,
-                                            GValue     *value,
-                                            GParamSpec *pspec)
-{
-  RustAnalyzerSearchProvider *self = RUST_ANALYZER_SEARCH_PROVIDER (object);
-
-  switch (prop_id)
-    {
-    case PROP_CLIENT:
-      g_value_set_object (value, rust_analyzer_search_provider_get_client (self));
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-    }
-}
-
-static void
-rust_analyzer_search_provider_set_property (GObject      *object,
-                                            guint         prop_id,
-                                            const GValue *value,
-                                            GParamSpec   *pspec)
-{
-  RustAnalyzerSearchProvider *self = RUST_ANALYZER_SEARCH_PROVIDER (object);
-
-  switch (prop_id)
-    {
-    case PROP_CLIENT:
-      rust_analyzer_search_provider_set_client (self, g_value_get_object (value));
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-    }
-}
-
 static void
 rust_analyzer_search_provider_class_init (RustAnalyzerSearchProviderClass *klass)
 {
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
-  object_class->finalize = rust_analyzer_search_provider_finalize;
-  object_class->get_property = rust_analyzer_search_provider_get_property;
-  object_class->set_property = rust_analyzer_search_provider_set_property;
-
-  properties[PROP_CLIENT] =
-    g_param_spec_object ("client",
-                         "client",
-                         "The Language Server client",
-                         IDE_TYPE_LSP_CLIENT,
-                         (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
-
-  g_object_class_install_properties (object_class, N_PROPS, properties);
 }
 
 static void
@@ -126,136 +46,26 @@ rust_analyzer_search_provider_init (RustAnalyzerSearchProvider *self)
 }
 
 static void
-rust_analyzer_search_provider_search_cb (GObject      *source_object,
-                                         GAsyncResult *res,
-                                         gpointer      user_data)
-{
-  IdeLspClient *client = (IdeLspClient *) source_object;
-  GPtrArray *ar;
-  g_autoptr(IdeTask) task = user_data;
-  g_autoptr(GVariant) result = NULL;
-  g_autoptr(GVariantIter) iter = NULL;
-  GVariant *symbol_information;
-  GError *error = NULL;
-
-  IDE_ENTRY;
-
-  ar = g_ptr_array_new ();
-
-  ide_lsp_client_call_finish (client, res, &result, &error);
-  if (error != NULL)
-    {
-      ide_task_return_error (task, error);
-      return;
-    }
-
-  iter = g_variant_iter_new (result);
-
-  while (g_variant_iter_loop (iter, "v", &symbol_information))
-    {
-      g_autoptr(GFile) gfile = NULL;
-      g_autoptr(IdeLocation) location = NULL;
-      const gchar *title;
-      const gchar *uri;
-      gint64 kind;
-      gint64 line, character;
-      IdeSymbolKind symbol_kind;
-      const gchar *icon_name;
-
-      JSONRPC_MESSAGE_PARSE (symbol_information,
-                             "name", JSONRPC_MESSAGE_GET_STRING (&title),
-                             "kind", JSONRPC_MESSAGE_GET_INT64 (&kind),
-                             "location", "{",
-                               "uri", JSONRPC_MESSAGE_GET_STRING (&uri),
-                               "range", "{",
-                                 "start", "{",
-                                   "line", JSONRPC_MESSAGE_GET_INT64 (&line),
-                                   "character", JSONRPC_MESSAGE_GET_INT64 (&character),
-                                 "}",
-                               "}",
-                             "}");
-
-      symbol_kind = ide_lsp_decode_symbol_kind (kind);
-      icon_name = ide_symbol_kind_get_icon_name (symbol_kind);
-
-      gfile = g_file_new_for_uri (uri);
-      location = ide_location_new (gfile, line, character);
-
-      g_ptr_array_add (ar, rust_analyzer_search_result_new (title, g_file_get_basename (gfile), location, 
icon_name));
-    }
-
-  ide_task_return_pointer (task,
-                           g_steal_pointer(&ar),
-                           g_ptr_array_unref);
-
-  IDE_EXIT;
-}
-
-static void
-rust_analyzer_search_provider_search_async (IdeSearchProvider   *provider,
-                                            const gchar         *query,
-                                            guint                max_results,
-                                            GCancellable        *cancellable,
-                                            GAsyncReadyCallback  callback,
-                                            gpointer             user_data)
+rust_analyzer_search_provider_load (IdeSearchProvider *self,
+                                    IdeContext        *context)
 {
-  RustAnalyzerSearchProvider *self = (RustAnalyzerSearchProvider *)provider;
-  g_autoptr(IdeTask) task = NULL;
-  g_autoptr(GVariant) params = NULL;
+  RustAnalyzerService *service;
 
   IDE_ENTRY;
 
-  g_return_if_fail (IDE_IS_MAIN_THREAD ());
-  g_return_if_fail (RUST_IS_ANALYZER_SEARCH_PROVIDER (self));
-  g_return_if_fail (query != NULL);
-  g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
-
-  task = ide_task_new (self, cancellable, callback, user_data);
-  ide_task_set_source_tag (task, rust_analyzer_search_provider_search_async);
+  g_assert (RUST_IS_ANALYZER_SEARCH_PROVIDER (self));
+  g_assert (context != NULL);
+  g_assert (IDE_IS_CONTEXT (context));
 
-  params = JSONRPC_MESSAGE_NEW ("query", JSONRPC_MESSAGE_PUT_STRING (query));
-
-  ide_lsp_client_call_async (self->client,
-                             "workspace/symbol",
-                             params,
-                             cancellable,
-                             rust_analyzer_search_provider_search_cb,
-                             g_steal_pointer (&task));
+  service = ide_object_ensure_child_typed (IDE_OBJECT (context), RUST_TYPE_ANALYZER_SERVICE);
+  g_object_bind_property (service, "client", self, "client", G_BINDING_SYNC_CREATE);
+  rust_analyzer_service_ensure_started (service);
 
   IDE_EXIT;
 }
 
-static GPtrArray *
-rust_analyzer_search_provider_search_finish (IdeSearchProvider  *provider,
-                                      GAsyncResult       *result,
-                                      GError            **error)
-{
-  return ide_task_propagate_pointer (IDE_TASK (result), error);
-}
-
 static void
 provider_iface_init (IdeSearchProviderInterface *iface)
 {
-  iface->search_async = rust_analyzer_search_provider_search_async;
-  iface->search_finish = rust_analyzer_search_provider_search_finish;
-}
-
-IdeLspClient *
-rust_analyzer_search_provider_get_client (RustAnalyzerSearchProvider *self)
-{
-  g_return_val_if_fail (RUST_IS_ANALYZER_SEARCH_PROVIDER (self), NULL);
-
-  return self->client;
-}
-
-void
-rust_analyzer_search_provider_set_client (RustAnalyzerSearchProvider *self,
-                                          IdeLspClient               *client)
-{
-  g_return_if_fail (RUST_IS_ANALYZER_SEARCH_PROVIDER (self));
-  g_return_if_fail (!client || IDE_IS_LSP_CLIENT (client));
-
-  if (self->client != NULL)
-    g_clear_pointer (&self->client, g_object_unref);
-  self->client = g_object_ref (client);
+  iface->load = rust_analyzer_search_provider_load;
 }
diff --git a/src/plugins/rust-analyzer/rust-analyzer-search-provider.h 
b/src/plugins/rust-analyzer/rust-analyzer-search-provider.h
index 30ed6f96c..4b768a733 100644
--- a/src/plugins/rust-analyzer/rust-analyzer-search-provider.h
+++ b/src/plugins/rust-analyzer/rust-analyzer-search-provider.h
@@ -26,11 +26,6 @@ G_BEGIN_DECLS
 
 #define RUST_TYPE_ANALYZER_SEARCH_PROVIDER (rust_analyzer_search_provider_get_type())
 
-G_DECLARE_FINAL_TYPE (RustAnalyzerSearchProvider, rust_analyzer_search_provider, RUST, 
ANALYZER_SEARCH_PROVIDER, IdeObject)
-
-RustAnalyzerSearchProvider *rust_analyzer_search_provider_new        (void);
-IdeLspClient               *rust_analyzer_search_provider_get_client (RustAnalyzerSearchProvider *self);
-void                        rust_analyzer_search_provider_set_client (RustAnalyzerSearchProvider *self,
-                                                                      IdeLspClient               *client);
+G_DECLARE_FINAL_TYPE (RustAnalyzerSearchProvider, rust_analyzer_search_provider, RUST, 
ANALYZER_SEARCH_PROVIDER, IdeLspSearchProvider)
 
 G_END_DECLS
diff --git a/src/plugins/rust-analyzer/rust-analyzer-service.c 
b/src/plugins/rust-analyzer/rust-analyzer-service.c
index d42c3cd04..966a8ef8c 100644
--- a/src/plugins/rust-analyzer/rust-analyzer-service.c
+++ b/src/plugins/rust-analyzer/rust-analyzer-service.c
@@ -415,16 +415,6 @@ rust_analyzer_service_lsp_started (IdeSubprocessSupervisor *supervisor,
   root_uri = g_file_get_uri (workdir);
   ide_lsp_client_set_root_uri (client, root_uri);
   ide_lsp_client_start (client);
-
-  // register SearchProvider
-  if (self->search_provider == NULL)
-    {
-      IdeSearchEngine *search_engine = _get_search_engine (self);
-
-      self->search_provider = rust_analyzer_search_provider_new ();
-      ide_search_engine_add_provider (search_engine, IDE_SEARCH_PROVIDER (self->search_provider));
-    }
-  rust_analyzer_search_provider_set_client (self->search_provider, client);
 }
 
 static gboolean
diff --git a/src/plugins/rust-analyzer/rust-analyzer.c b/src/plugins/rust-analyzer/rust-analyzer.c
index fa711ea35..c71a0ff7e 100644
--- a/src/plugins/rust-analyzer/rust-analyzer.c
+++ b/src/plugins/rust-analyzer/rust-analyzer.c
@@ -29,6 +29,7 @@
 #include "rust-analyzer-hover-provider.h"
 #include "rust-analyzer-workbench-addin.h"
 #include "rust-analyzer-rename-provider.h"
+#include "rust-analyzer-search-provider.h"
 #include "rust-analyzer-preferences-addin.h"
 
 _IDE_EXTERN void
@@ -58,6 +59,9 @@ _rust_analyzer_register_types (PeasObjectModule *module)
   peas_object_module_register_extension_type (module,
                                               IDE_TYPE_RENAME_PROVIDER,
                                               RUST_TYPE_ANALYZER_RENAME_PROVIDER);
+  peas_object_module_register_extension_type (module,
+                                              IDE_TYPE_SEARCH_PROVIDER,
+                                              RUST_TYPE_ANALYZER_SEARCH_PROVIDER);
   peas_object_module_register_extension_type (module,
                                               IDE_TYPE_PREFERENCES_ADDIN,
                                               RUST_TYPE_ANALYZER_PREFERENCES_ADDIN);
diff --git a/src/plugins/rust-analyzer/rust-analyzer.plugin b/src/plugins/rust-analyzer/rust-analyzer.plugin
index 53e86e0c7..7fba318b7 100644
--- a/src/plugins/rust-analyzer/rust-analyzer.plugin
+++ b/src/plugins/rust-analyzer/rust-analyzer.plugin
@@ -13,3 +13,4 @@ X-Formatter-Languages=rust
 X-Highlighter-Languages=rust
 X-Hover-Provider-Languages=rust
 X-Rename-Provider-Languages=rust
+X-Search-Provider-Languages=rust


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