[gnome-builder: 1/6] lsp: allow nested lsp project
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder: 1/6] lsp: allow nested lsp project
- Date: Sat, 4 Jul 2020 18:09:07 +0000 (UTC)
commit 6d13199df0609160b8c7dbdbdafb9e296677b608
Author: Günther Wagner <info gunibert de>
Date: Tue Jun 30 22:48:18 2020 +0200
lsp: allow nested lsp project
Its possible to set the root directory for the lsp now from the caller.
This way we can determine the root directory from a lsp plugin and
therefore enable nested projects.
src/libide/lsp/ide-lsp-client.c | 37 ++++++++++++++++-
src/libide/lsp/ide-lsp-client.h | 3 ++
src/plugins/rust-analyzer/rust-analyzer-service.c | 50 ++++++++++++++++++++---
3 files changed, 83 insertions(+), 7 deletions(-)
---
diff --git a/src/libide/lsp/ide-lsp-client.c b/src/libide/lsp/ide-lsp-client.c
index e73ef6d13..e6a0efc76 100644
--- a/src/libide/lsp/ide-lsp-client.c
+++ b/src/libide/lsp/ide-lsp-client.c
@@ -51,6 +51,7 @@ typedef struct
GPtrArray *languages;
GVariant *server_capabilities;
IdeLspTrace trace;
+ gchar *root_uri;
} IdeLspClientPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (IdeLspClient, ide_lsp_client, IDE_TYPE_OBJECT)
@@ -79,6 +80,7 @@ enum {
PROP_IO_STREAM,
PROP_SERVER_CAPABILITIES,
PROP_TRACE,
+ PROP_ROOT_URI,
N_PROPS
};
@@ -1034,6 +1036,7 @@ ide_lsp_client_finalize (GObject *object)
g_clear_pointer (&priv->diagnostics_by_file, g_hash_table_unref);
g_clear_pointer (&priv->server_capabilities, g_variant_unref);
g_clear_pointer (&priv->languages, g_ptr_array_unref);
+ g_clear_pointer (&priv->root_uri, g_free);
g_clear_object (&priv->rpc_client);
g_clear_object (&priv->buffer_manager_signals);
g_clear_object (&priv->project_signals);
@@ -1085,6 +1088,9 @@ ide_lsp_client_get_property (GObject *object,
g_value_set_enum (value, ide_lsp_client_get_trace (self));
break;
+ case PROP_ROOT_URI:
+ g_value_set_string (value, priv->root_uri);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@@ -1109,6 +1115,10 @@ ide_lsp_client_set_property (GObject *object,
ide_lsp_client_set_trace (self, g_value_get_enum (value));
break;
+ case PROP_ROOT_URI:
+ ide_lsp_client_set_root_uri (self, g_value_get_string (value));
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@@ -1149,6 +1159,13 @@ ide_lsp_client_class_init (IdeLspClientClass *klass)
IDE_LSP_TRACE_OFF,
(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ properties [PROP_ROOT_URI] =
+ g_param_spec_string ("root-uri",
+ "Root Uri",
+ "The root uri the LSP should work on",
+ "",
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
g_object_class_install_properties (object_class, N_PROPS, properties);
@@ -1397,7 +1414,9 @@ ide_lsp_client_start (IdeLspClient *self)
workdir = ide_context_ref_workdir (context);
root_path = g_file_get_path (workdir);
- root_uri = g_file_get_uri (workdir);
+ root_uri = priv->root_uri;
+ if (root_uri == NULL)
+ root_uri = g_file_get_uri (workdir);
switch (priv->trace)
{
@@ -1910,6 +1929,22 @@ ide_lsp_client_set_trace (IdeLspClient *self,
}
}
+void
+ide_lsp_client_set_root_uri (IdeLspClient *self,
+ const gchar *root_uri)
+{
+ IdeLspClientPrivate *priv = ide_lsp_client_get_instance_private (self);
+
+ g_return_if_fail (IDE_IS_LSP_CLIENT (self));
+
+ if (!ide_str_equal0 (priv->root_uri, root_uri))
+ {
+ g_free (priv->root_uri);
+ priv->root_uri = g_strdup (root_uri);
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_ROOT_URI]);
+ }
+}
+
/**
* ide_lsp_client_get_server_capabilities:
* @self: a #IdeLspClient
diff --git a/src/libide/lsp/ide-lsp-client.h b/src/libide/lsp/ide-lsp-client.h
index e6e1bfb55..66a4ea74e 100644
--- a/src/libide/lsp/ide-lsp-client.h
+++ b/src/libide/lsp/ide-lsp-client.h
@@ -71,6 +71,9 @@ GVariant *ide_lsp_client_get_server_capabilities (IdeLspClient *sel
IDE_AVAILABLE_IN_3_32
void ide_lsp_client_add_language (IdeLspClient *self,
const gchar *language_id);
+IDE_AVAILABLE_IN_3_38
+void ide_lsp_client_set_root_uri (IdeLspClient *self,
+ const gchar *root_uri);
IDE_AVAILABLE_IN_3_32
void ide_lsp_client_start (IdeLspClient *self);
IDE_AVAILABLE_IN_3_32
diff --git a/src/plugins/rust-analyzer/rust-analyzer-service.c
b/src/plugins/rust-analyzer/rust-analyzer-service.c
index 3a1948e22..76368b12b 100644
--- a/src/plugins/rust-analyzer/rust-analyzer-service.c
+++ b/src/plugins/rust-analyzer/rust-analyzer-service.c
@@ -29,6 +29,7 @@
#include <jsonrpc-glib.h>
#include <glib/gi18n.h>
#include <libide-search.h>
+#include <libide-io.h>
#include "rust-analyzer-search-provider.h"
struct _RustAnalyzerService
@@ -91,6 +92,34 @@ _get_search_engine (RustAnalyzerService *self)
return ide_object_get_child_typed (IDE_OBJECT (context), IDE_TYPE_SEARCH_ENGINE);
}
+static GFile *
+rust_analyzer_service_determine_workdir (RustAnalyzerService *self)
+{
+ g_autoptr(GFile) workdir = NULL;
+ g_autoptr(GPtrArray) possible_workdirs = NULL;
+ IdeContext *context = NULL;
+
+ g_assert (RUST_IS_ANALYZER_SERVICE (self));
+
+ context = ide_object_get_context (IDE_OBJECT (self));
+ workdir = ide_context_ref_workdir (context);
+
+ 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)
+ {
+ // take the first directory with a Cargo.toml file as root. Multiple workspaces are only
+ // supported if a Cargo-workspace exists.
+ g_autoptr(GFile) parent = NULL;
+ parent = g_file_get_parent (g_ptr_array_index (possible_workdirs, 0));
+
+ return g_steal_pointer (&parent);
+ }
+
+ return g_steal_pointer (&workdir);
+}
+
static GVariant *
rust_analyzer_service_load_configuration (IdeLspClient *client,
gpointer user_data)
@@ -270,7 +299,11 @@ rust_analyzer_service_set_client (RustAnalyzerService *self,
if (g_set_object (&self->client, client))
{
- g_signal_connect (self->client, "load-configuration", G_CALLBACK
(rust_analyzer_service_load_configuration), self);
+ g_signal_connect_object (self->client,
+ "load-configuration",
+ G_CALLBACK (rust_analyzer_service_load_configuration),
+ self,
+ G_CONNECT_AFTER);
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_CLIENT]);
}
}
@@ -296,6 +329,8 @@ rust_analyzer_service_lsp_started (IdeSubprocessSupervisor *supervisor,
{
RustAnalyzerService *self = user_data;
g_autoptr(GIOStream) io_stream = NULL;
+ g_autoptr(GFile) workdir = NULL;
+ g_autofree gchar *root_uri = NULL;
GInputStream *input;
GOutputStream *output;
IdeLspClient *client = NULL;
@@ -319,6 +354,9 @@ rust_analyzer_service_lsp_started (IdeSubprocessSupervisor *supervisor,
rust_analyzer_service_set_client (self, client);
ide_object_append (IDE_OBJECT (self), IDE_OBJECT (client));
ide_lsp_client_add_language (client, "rust");
+ workdir = rust_analyzer_service_determine_workdir (self);
+ root_uri = g_file_get_uri (workdir);
+ ide_lsp_client_set_root_uri (client, root_uri);
ide_lsp_client_start (client);
// register SearchProvider
@@ -404,18 +442,18 @@ rust_analyzer_service_ensure_started (RustAnalyzerService *self)
else if (self->state == RUST_ANALYZER_SERVICE_READY)
{
g_autofree gchar *newpath = NULL;
+ g_autoptr(GFile) workdir = NULL;
+ g_autofree gchar *root_path = NULL;
g_autoptr(IdeSubprocessLauncher) launcher = NULL;
- IdeContext *context = NULL;
- GFile *workdir = NULL;
const gchar *oldpath = NULL;
launcher = ide_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDOUT_PIPE |
G_SUBPROCESS_FLAGS_STDIN_PIPE);
ide_subprocess_launcher_set_run_on_host (launcher, TRUE);
ide_subprocess_launcher_set_clear_env (launcher, TRUE);
- context = ide_object_get_context (IDE_OBJECT (self));
- workdir = ide_context_ref_workdir (context);
- ide_subprocess_launcher_set_cwd (launcher, g_file_get_path (workdir));
+ workdir = rust_analyzer_service_determine_workdir (self);
+ root_path = g_file_get_path (workdir);
+ ide_subprocess_launcher_set_cwd (launcher, root_path);
oldpath = g_getenv ("PATH");
newpath = g_strdup_printf ("%s/%s:%s", g_get_home_dir (), ".cargo/bin", oldpath);
ide_subprocess_launcher_setenv (launcher, "PATH", newpath, TRUE);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]