[gnome-builder: 2/6] Alternative algorithm to determine Cargo root



commit 61264fb859c995cf0290e538c5c315deef9cee08
Author: Günther Wagner <info gunibert de>
Date:   Wed Jul 1 23:25:41 2020 +0200

    Alternative algorithm to determine Cargo root

 src/libide/lsp/ide-lsp-client.c                    |   2 +-
 src/plugins/rust-analyzer/rust-analyzer-service.c  | 110 ++++++++++++++++++---
 .../rust-analyzer/rust-analyzer-workbench-addin.c  |   4 +-
 3 files changed, 100 insertions(+), 16 deletions(-)
---
diff --git a/src/libide/lsp/ide-lsp-client.c b/src/libide/lsp/ide-lsp-client.c
index e6a0efc76..29ba657fc 100644
--- a/src/libide/lsp/ide-lsp-client.c
+++ b/src/libide/lsp/ide-lsp-client.c
@@ -1414,7 +1414,7 @@ ide_lsp_client_start (IdeLspClient *self)
 
   workdir = ide_context_ref_workdir (context);
   root_path = g_file_get_path (workdir);
-  root_uri = priv->root_uri;
+  root_uri = g_strdup (priv->root_uri);
   if (root_uri == NULL)
     root_uri = g_file_get_uri (workdir);
 
diff --git a/src/plugins/rust-analyzer/rust-analyzer-service.c 
b/src/plugins/rust-analyzer/rust-analyzer-service.c
index 76368b12b..becee2d8f 100644
--- a/src/plugins/rust-analyzer/rust-analyzer-service.c
+++ b/src/plugins/rust-analyzer/rust-analyzer-service.c
@@ -30,6 +30,9 @@
 #include <glib/gi18n.h>
 #include <libide-search.h>
 #include <libide-io.h>
+#include <libide-editor.h>
+#include <libide-gui.h>
+#include <ide-gui-private.h>
 #include "rust-analyzer-search-provider.h"
 
 struct _RustAnalyzerService
@@ -92,31 +95,109 @@ _get_search_engine (RustAnalyzerService *self)
   return ide_object_get_child_typed (IDE_OBJECT (context), IDE_TYPE_SEARCH_ENGINE);
 }
 
+static GFile *
+rust_analyzer_service_get_current_file (RustAnalyzerService *self)
+{
+  g_autoptr(IdeContext) context = NULL;
+  IdeWorkbench *workbench = NULL;
+  IdeWorkspace *workspace = NULL;
+  IdeSurface *surface = NULL;
+  IdePage *page = NULL;
+
+  IDE_ENTRY;
+
+  g_assert (RUST_IS_ANALYZER_SERVICE (self));
+
+  context = ide_object_ref_context (IDE_OBJECT (self));
+  workbench = _ide_workbench_from_context (context);
+  workspace = ide_workbench_get_current_workspace (workbench);
+  surface = ide_workspace_get_surface_by_name (workspace, "editor");
+  page = ide_editor_surface_get_active_page (IDE_EDITOR_SURFACE (surface));
+
+  if (!IDE_IS_EDITOR_PAGE (page)) return NULL;
+
+  IDE_RETURN (g_object_ref (ide_editor_page_get_file (IDE_EDITOR_PAGE (page))));
+}
+
+static gboolean
+rust_analyzer_service_search_cargo_root (RustAnalyzerService *self,
+                                         GFile               *dir,
+                                         GPatternSpec        *spec)
+{
+  g_autoptr(GFileEnumerator) enumerator = NULL;
+
+  IDE_ENTRY;
+
+  g_assert (RUST_IS_ANALYZER_SERVICE (self));
+
+  enumerator = g_file_enumerate_children (dir,
+                                          G_FILE_ATTRIBUTE_STANDARD_NAME","
+                                          G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK","
+                                          G_FILE_ATTRIBUTE_STANDARD_TYPE,
+                                          G_FILE_QUERY_INFO_NONE,
+                                          NULL,
+                                          NULL);
+  if (enumerator == NULL)
+    return FALSE;
+
+  for (;;)
+    {
+      g_autoptr(GFileInfo) info = g_file_enumerator_next_file (enumerator, NULL, NULL);
+      const gchar *name;
+      GFileType file_type;
+
+      if (info == NULL)
+        break;
+
+      name = g_file_info_get_name (info);
+      file_type = g_file_info_get_file_type (info);
+
+      if (g_pattern_match_string (spec, name))
+        {
+          g_file_enumerator_close (enumerator, NULL, NULL);
+          IDE_RETURN (TRUE);
+        }
+    }
+
+  g_file_enumerator_close (enumerator, NULL, NULL);
+  IDE_RETURN (FALSE);
+}
+
 static GFile *
 rust_analyzer_service_determine_workdir (RustAnalyzerService *self)
 {
   g_autoptr(GFile) workdir = NULL;
-  g_autoptr(GPtrArray) possible_workdirs = NULL;
-  IdeContext *context = NULL;
+  g_autoptr(IdeContext) context = NULL;
+  g_autoptr(GPatternSpec) spec = NULL;
 
   g_assert (RUST_IS_ANALYZER_SERVICE (self));
 
-  context = ide_object_get_context (IDE_OBJECT (self));
-  workdir = ide_context_ref_workdir (context);
+  spec = g_pattern_spec_new ("Cargo.toml");
 
-  possible_workdirs = ide_g_file_find_with_depth (workdir, "Cargo.toml", 5, NULL);
-  IDE_PTR_ARRAY_SET_FREE_FUNC (possible_workdirs, g_object_unref);
-
-  if (possible_workdirs->len > 0)
+  /* Search workbench root first */
+  context = ide_object_ref_context (IDE_OBJECT (self));
+  workdir = ide_context_ref_workdir (context);
+  if (rust_analyzer_service_search_cargo_root (self, workdir, spec) == FALSE)
     {
-      // take the first directory with a Cargo.toml file as root. Multiple workspaces are only
-      // supported if a Cargo-workspace exists.
+      /* Search now from the current opened file upwards */
+      g_autoptr(GFile) current_file = NULL;
       g_autoptr(GFile) parent = NULL;
-      parent = g_file_get_parent (g_ptr_array_index (possible_workdirs, 0));
 
-      return g_steal_pointer (&parent);
+      current_file = rust_analyzer_service_get_current_file (self);
+      if (current_file == NULL) goto end;
+      parent = g_file_get_parent (current_file);
+
+      while (!g_file_equal (workdir, parent))
+        {
+          if (rust_analyzer_service_search_cargo_root (self, parent, spec))
+            {
+              return g_steal_pointer (&parent);
+            }
+          parent = g_file_get_parent (parent);
+        }
     }
 
+end:
   return g_steal_pointer (&workdir);
 }
 
@@ -303,7 +384,7 @@ rust_analyzer_service_set_client (RustAnalyzerService *self,
                                "load-configuration",
                                G_CALLBACK (rust_analyzer_service_load_configuration),
                                self,
-                               G_CONNECT_AFTER);
+                               0);
       g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_CLIENT]);
     }
 }
@@ -498,5 +579,6 @@ rust_analyzer_service_set_cargo_command (RustAnalyzerService *self,
   self->cargo_command = g_strdup (cargo_command);
 
   params = JSONRPC_MESSAGE_NEW ("settings", "");
-  ide_lsp_client_send_notification_async (self->client, "workspace/didChangeConfiguration", params, NULL, 
NULL, NULL);
+  if (self->client != NULL)
+    ide_lsp_client_send_notification_async (self->client, "workspace/didChangeConfiguration", params, NULL, 
NULL, NULL);
 }
diff --git a/src/plugins/rust-analyzer/rust-analyzer-workbench-addin.c 
b/src/plugins/rust-analyzer/rust-analyzer-workbench-addin.c
index b0a85969e..1cb9a9683 100644
--- a/src/plugins/rust-analyzer/rust-analyzer-workbench-addin.c
+++ b/src/plugins/rust-analyzer/rust-analyzer-workbench-addin.c
@@ -133,16 +133,18 @@ rust_analyzer_workbench_addin_workspace_added (IdeWorkbenchAddin *addin,
                                                IdeWorkspace      *workspace)
 {
   GSimpleAction *install_rust_analyzer = NULL;
+  IdeContext *context = NULL;
 
   g_assert (RUST_IS_ANALYZER_WORKBENCH_ADDIN (addin));
   g_assert (IDE_IS_WORKSPACE (workspace));
 
+  context = ide_workspace_get_context (workspace);
   install_rust_analyzer = g_simple_action_new ("install-rust-analyzer", NULL);
   g_simple_action_set_enabled (install_rust_analyzer, TRUE);
   g_signal_connect (install_rust_analyzer,
                     "activate",
                     G_CALLBACK (rust_analyzer_workbench_addin_install_rust_analyzer),
-                    ide_workspace_get_context (workspace));
+                    context);
   g_action_map_add_action (G_ACTION_MAP (workspace), G_ACTION (install_rust_analyzer));
 }
 


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