Commit 6d13199d authored by Günther Wagner's avatar Günther Wagner

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.
parent 70f85f19
......@@ -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
......
......@@ -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
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment