[gnome-builder] lsp: teach LSP service to locate programs
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] lsp: teach LSP service to locate programs
- Date: Wed, 22 Dec 2021 00:04:03 +0000 (UTC)
commit 772c0a49cad7fae3edaef27aba94f1e786d06688
Author: Christian Hergert <chergert redhat com>
Date: Tue Dec 21 15:58:18 2021 -0800
lsp: teach LSP service to locate programs
This simplfies the IdeLspService by allowing subclasses to define their
program name and let the IdeLspService abstract class locate them within
either the build runtime, host runtime, or Builder's runtime.
src/libide/lsp/ide-lsp-service.c | 402 +++++++++++++++++----
src/libide/lsp/ide-lsp-service.h | 37 +-
src/libide/lsp/meson.build | 1 +
src/plugins/blueprint/blueprint_plugin.py | 10 +-
.../jedi_language_server_plugin.py | 9 +-
.../ts_language_server_plugin.py | 10 +-
6 files changed, 370 insertions(+), 99 deletions(-)
---
diff --git a/src/libide/lsp/ide-lsp-service.c b/src/libide/lsp/ide-lsp-service.c
index 211cdfd5a..ba8beb152 100644
--- a/src/libide/lsp/ide-lsp-service.c
+++ b/src/libide/lsp/ide-lsp-service.c
@@ -21,12 +21,22 @@
#define G_LOG_DOMAIN "ide-lsp-service"
#include "config.h"
+
#include "ide-lsp-service.h"
+/**
+ * SECTION:ide-lsp-service
+ * @title: IdeLspService
+ * @short_description: Service integration for LSPs
+ *
+ * Since: 42.0
+ */
+
typedef struct
{
IdeSubprocessSupervisor *supervisor;
IdeLspClient *client;
+ char *program;
guint has_started : 1;
guint inherit_stderr : 1;
} IdeLspServicePrivate;
@@ -36,12 +46,61 @@ G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (IdeLspService, ide_lsp_service, IDE_TYPE_OB
enum {
PROP_0,
PROP_CLIENT,
- PROP_SUPERVISOR,
PROP_INHERIT_STDERR,
+ PROP_PROGRAM,
+ PROP_SUPERVISOR,
N_PROPS
};
+enum {
+ CREATE_LAUNCHER,
+ N_SIGNALS
+};
+
static GParamSpec *properties [N_PROPS];
+static guint signals [N_SIGNALS];
+
+static void
+ide_lsp_service_stop (IdeLspService *self)
+{
+ IdeLspServicePrivate *priv = ide_lsp_service_get_instance_private (self);
+ gboolean notify_client = FALSE;
+ gboolean notify_supervisor = FALSE;
+
+ IDE_ENTRY;
+
+ g_return_if_fail (IDE_IS_MAIN_THREAD ());
+ g_return_if_fail (IDE_IS_LSP_SERVICE (self));
+
+ if (priv->has_started)
+ g_debug ("Stopping LSP client %s", G_OBJECT_TYPE_NAME (self));
+
+ if (priv->client != NULL)
+ {
+ ide_lsp_client_stop (priv->client);
+ ide_object_destroy (IDE_OBJECT (priv->client));
+ priv->client = NULL;
+ notify_client = TRUE;
+ }
+
+ if (priv->supervisor != NULL)
+ {
+ ide_subprocess_supervisor_stop (priv->supervisor);
+ g_clear_object (&priv->supervisor);
+ notify_supervisor = TRUE;
+ }
+
+ priv->has_started = FALSE;
+
+ if (notify_client)
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_CLIENT]);
+
+ if (notify_supervisor)
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SUPERVISOR]);
+
+ IDE_EXIT;
+}
+
static void
ide_lsp_service_get_property (GObject *object,
@@ -58,6 +117,10 @@ ide_lsp_service_get_property (GObject *object,
g_value_set_object (value, priv->client);
break;
+ case PROP_PROGRAM:
+ g_value_set_string (value, priv->program);
+ break;
+
case PROP_SUPERVISOR:
g_value_set_object (value, priv->supervisor);
break;
@@ -85,6 +148,10 @@ ide_lsp_service_set_property (GObject *object,
ide_lsp_service_set_inherit_stderr (self, g_value_get_boolean (value));
break;
+ case PROP_PROGRAM:
+ ide_lsp_service_set_program (self, g_value_get_string (value));
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@@ -96,31 +163,107 @@ ide_lsp_service_destroy (IdeObject *object)
IdeLspService *self = (IdeLspService *)object;
IdeLspServicePrivate *priv = ide_lsp_service_get_instance_private (self);
+ IDE_ENTRY;
+
ide_lsp_service_stop (self);
g_clear_object (&priv->supervisor);
g_clear_object (&priv->client);
IDE_OBJECT_CLASS (ide_lsp_service_parent_class)->destroy (object);
+
+ IDE_EXIT;
+}
+
+static IdeSubprocessLauncher *
+ide_lsp_service_real_create_launcher (IdeLspService *self,
+ IdePipeline *pipeline,
+ GSubprocessFlags flags)
+{
+ IdeLspServicePrivate *priv = ide_lsp_service_get_instance_private (self);
+ g_autoptr(IdeSubprocessLauncher) launcher = NULL;
+ g_autoptr(IdeContext) context = NULL;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_LSP_SERVICE (self));
+ g_assert (IDE_IS_PIPELINE (pipeline));
+
+ if (priv->program == NULL)
+ IDE_RETURN (NULL);
+
+ context = ide_object_ref_context (IDE_OBJECT (self));
+
+ /* First try in the build environment */
+ if (ide_pipeline_contains_program_in_path (pipeline, priv->program, NULL))
+ {
+ if ((launcher = ide_pipeline_create_launcher (pipeline, NULL)))
+ ide_subprocess_launcher_set_flags (launcher, flags);
+ }
+
+ /* Then try on the host if we find it there */
+ if (launcher == NULL)
+ {
+ IdeRuntimeManager *runtime_manager = ide_runtime_manager_from_context (context);
+ IdeRuntime *host = ide_runtime_manager_get_runtime (runtime_manager, "host");
+
+ if (ide_runtime_contains_program_in_path (host, priv->program, NULL))
+ {
+ if ((launcher = ide_runtime_create_launcher (host, NULL)))
+ ide_subprocess_launcher_set_flags (launcher, flags);
+ }
+ }
+
+ /* Finally fallback to Builder's execution runtime */
+ if (launcher == NULL)
+ {
+ g_autofree char *path = NULL;
+
+ if ((path = g_find_program_in_path (priv->program)))
+ launcher = ide_subprocess_launcher_new (flags);
+ }
+
+ if (launcher != NULL)
+ {
+ const char *srcdir = ide_pipeline_get_srcdir (pipeline);
+
+ ide_subprocess_launcher_set_cwd (launcher, srcdir);
+ ide_subprocess_launcher_push_argv (launcher, priv->program);
+ }
+
+ IDE_RETURN (g_steal_pointer (&launcher));
}
G_NORETURN static void
ide_lsp_service_real_configure_client (IdeLspService *self,
IdeLspClient *client)
{
+ g_assert (IDE_IS_LSP_SERVICE (self));
+ g_assert (IDE_IS_LSP_CLIENT (client));
+
g_assert_not_reached ();
}
static void
ide_lsp_service_real_configure_launcher (IdeLspService *self,
- IdeSubprocessLauncher *client)
+ IdePipeline *pipeline,
+ IdeSubprocessLauncher *launcher)
{
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_LSP_SERVICE (self));
+ g_assert (!pipeline || IDE_IS_PIPELINE (pipeline));
+ g_assert (IDE_IS_SUBPROCESS_LAUNCHER (launcher));
+
+ IDE_EXIT;
}
static void
ide_lsp_service_real_configure_supervisor (IdeLspService *self,
IdeSubprocessSupervisor *client)
{
+ IDE_ENTRY;
+ IDE_EXIT;
}
static void
@@ -135,6 +278,7 @@ ide_lsp_service_class_init (IdeLspServiceClass *klass)
ide_object_class->destroy = ide_lsp_service_destroy;
+ service_class->create_launcher = ide_lsp_service_real_create_launcher;
service_class->configure_client = ide_lsp_service_real_configure_client;
service_class->configure_launcher = ide_lsp_service_real_configure_launcher;
service_class->configure_supervisor = ide_lsp_service_real_configure_supervisor;
@@ -151,6 +295,20 @@ ide_lsp_service_class_init (IdeLspServiceClass *klass)
IDE_TYPE_LSP_CLIENT,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ /**
+ * IdeLspService:program:
+ *
+ * The "program" property contains the name of the executable to
+ * launch. If this is set, the create-launcher signal will use it
+ * to locate and execute the program if found.
+ */
+ properties [PROP_PROGRAM] =
+ g_param_spec_string ("program",
+ "Program",
+ "The program executable name",
+ NULL,
+ (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
/**
* IdeLspService:supervisor:
*
@@ -177,6 +335,31 @@ ide_lsp_service_class_init (IdeLspServiceClass *klass)
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, N_PROPS, properties);
+
+ /**
+ * IdeLspService::create-launcher:
+ * @self: an [class@LspService]
+ * @pipeline: a loaded [class@Pipeline]
+ * @flags: [enum@Gio.SubprocessFlags] to use for the launcher
+ *
+ * Creates the launcher to be used for the LSP.
+ *
+ * If you want to use a launcher on the host, this would be a good
+ * place to determine that.
+ *
+ * Returns: (transfer full) (nullable): a [class@SubprocessLauncher] or %NULL
+ */
+ signals [CREATE_LAUNCHER] =
+ g_signal_new ("create-launcher",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (IdeLspServiceClass, create_launcher),
+ g_signal_accumulator_first_wins, NULL,
+ NULL,
+ IDE_TYPE_SUBPROCESS_LAUNCHER,
+ 2,
+ IDE_TYPE_PIPELINE,
+ G_TYPE_SUBPROCESS_FLAGS);
}
static void
@@ -216,33 +399,43 @@ ide_lsp_service_set_inherit_stderr (IdeLspService *self,
{
IdeLspServicePrivate *priv = ide_lsp_service_get_instance_private (self);
+ IDE_ENTRY;
+
g_return_if_fail (IDE_IS_MAIN_THREAD ());
g_return_if_fail (IDE_IS_LSP_SERVICE (self));
- if (priv->inherit_stderr == !!inherit_stderr)
- return;
+ inherit_stderr = !!inherit_stderr;
- priv->inherit_stderr = !!inherit_stderr;
- g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_INHERIT_STDERR]);
+ if (priv->inherit_stderr != inherit_stderr)
+ {
+ priv->inherit_stderr = inherit_stderr;
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_INHERIT_STDERR]);
+ }
+
+ IDE_EXIT;
}
static void
-on_supervisor_spawned (IdeLspService *self,
- IdeSubprocess *subprocess,
- IdeSubprocessSupervisor *supervisor)
+on_supervisor_spawned_cb (IdeLspService *self,
+ IdeSubprocess *subprocess,
+ IdeSubprocessSupervisor *supervisor)
{
IdeLspServicePrivate *priv = ide_lsp_service_get_instance_private (self);
- IdeLspServiceClass *klass = IDE_LSP_SERVICE_GET_CLASS (self);
+ IdeLspServiceClass *klass;
g_autoptr(GIOStream) iostream = NULL;
g_autoptr(IdeLspClient) client = NULL;
g_autoptr(GInputStream) to_stdout = NULL;
g_autoptr(GOutputStream) to_stdin = NULL;
+ IDE_ENTRY;
+
g_assert (IDE_IS_MAIN_THREAD ());
g_assert (IDE_IS_LSP_SERVICE (self));
g_assert (IDE_IS_SUBPROCESS (subprocess));
g_assert (IDE_IS_SUBPROCESS_SUPERVISOR (supervisor));
+ klass = IDE_LSP_SERVICE_GET_CLASS (self);
+
to_stdin = ide_subprocess_get_stdin_pipe (subprocess);
to_stdout = ide_subprocess_get_stdout_pipe (subprocess);
iostream = g_simple_io_stream_new (to_stdout, to_stdin);
@@ -262,6 +455,8 @@ on_supervisor_spawned (IdeLspService *self,
priv->client = g_steal_pointer (&client);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_CLIENT]);
+
+ IDE_EXIT;
}
static void
@@ -269,109 +464,129 @@ ensure_started (IdeLspService *self,
IdeContext *context)
{
IdeLspServicePrivate *priv = ide_lsp_service_get_instance_private (self);
- IdeLspServiceClass *klass = IDE_LSP_SERVICE_GET_CLASS (self);
g_autoptr(IdeSubprocessLauncher) launcher = NULL;
- GSubprocessFlags flags;
- g_autoptr(GFile) workdir = NULL;
- g_autofree char *workdir_path = NULL;
g_autoptr(IdeSubprocessSupervisor) supervisor = NULL;
+ IdeBuildManager *build_manager;
+ IdeLspServiceClass *klass;
+ IdePipeline *pipeline = NULL;
+ GSubprocessFlags flags;
+
+ IDE_ENTRY;
g_assert (IDE_IS_MAIN_THREAD ());
g_assert (IDE_IS_LSP_SERVICE (self));
g_assert (IDE_IS_CONTEXT (context));
if (priv->has_started)
- return;
-
- priv->has_started = TRUE;
+ IDE_EXIT;
g_assert (priv->supervisor == NULL);
g_assert (priv->client == NULL);
+ klass = IDE_LSP_SERVICE_GET_CLASS (self);
+ build_manager = ide_build_manager_from_context (context);
+ pipeline = ide_build_manager_get_pipeline (build_manager);
+
+ /* Delay until pipeline is ready */
+ if (!ide_pipeline_is_ready (pipeline))
+ IDE_EXIT;
+
flags = G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE;
if (!priv->inherit_stderr)
flags |= G_SUBPROCESS_FLAGS_STDERR_SILENCE;
- launcher = ide_subprocess_launcher_new (flags);
-
- ide_subprocess_launcher_set_clear_env (launcher, FALSE);
- workdir = ide_context_ref_workdir (context);
- workdir_path = g_file_get_path (workdir);
- ide_subprocess_launcher_set_cwd (launcher, workdir_path);
+ /* Allow subclasses to control launcher creation */
+ g_signal_emit (self, signals [CREATE_LAUNCHER], 0, pipeline, flags, &launcher);
+ if (launcher == NULL)
+ IDE_EXIT;
- klass->configure_launcher (self, launcher);
+ klass->configure_launcher (self, pipeline, launcher);
supervisor = ide_subprocess_supervisor_new ();
ide_subprocess_supervisor_set_launcher (supervisor, launcher);
g_signal_connect_object (supervisor,
"spawned",
- G_CALLBACK (on_supervisor_spawned),
+ G_CALLBACK (on_supervisor_spawned_cb),
self,
G_CONNECT_SWAPPED);
- klass->configure_supervisor (self, supervisor);
+ priv->has_started = TRUE;
+ klass->configure_supervisor (self, supervisor);
ide_subprocess_supervisor_start (supervisor);
-
priv->supervisor = g_steal_pointer (&supervisor);
+
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SUPERVISOR]);
+
+ IDE_EXIT;
}
/**
- * ide_lsp_service_stop:
+ * ide_lsp_service_restart:
* @self: a [class@LspService]
*
- * Stops the service and its associated process, if any. This will set [property@LspService:client]
- * to %NULL.
+ * Restarts the service and its associated process.
*/
void
-ide_lsp_service_stop (IdeLspService *self)
+ide_lsp_service_restart (IdeLspService *self)
{
- gboolean notify_client = FALSE;
- gboolean notify_supervisor = FALSE;
- IdeLspServicePrivate *priv = ide_lsp_service_get_instance_private (self);
+ IdeContext *context;
+
+ IDE_ENTRY;
g_return_if_fail (IDE_IS_MAIN_THREAD ());
g_return_if_fail (IDE_IS_LSP_SERVICE (self));
+ g_return_if_fail (!ide_object_in_destruction (IDE_OBJECT (self)));
- if (priv->client != NULL)
- {
- ide_lsp_client_stop (priv->client);
- ide_object_destroy (IDE_OBJECT (priv->client));
- priv->client = NULL;
- notify_client = TRUE;
- }
+ ide_lsp_service_stop (self);
- if (priv->supervisor != NULL)
- {
- ide_subprocess_supervisor_stop (priv->supervisor);
- g_clear_object (&priv->supervisor);
- notify_supervisor = TRUE;
- }
+ if ((context = ide_object_get_context (IDE_OBJECT (self))))
+ ensure_started (self, context);
- priv->has_started = FALSE;
+ IDE_EXIT;
+}
- if (notify_client)
- g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_CLIENT]);
- if (notify_supervisor)
- g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SUPERVISOR]);
+static void
+on_pipeline_loaded_cb (IdeLspService *self,
+ IdePipeline *pipeline)
+{
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_LSP_SERVICE (self));
+ g_assert (IDE_IS_PIPELINE (pipeline));
+
+ ide_lsp_service_restart (self);
+
+ IDE_EXIT;
}
-/**
- * ide_lsp_service_restart:
- * @self: a [class@LspService]
- *
- * Restarts the service and its associated process.
- */
-void
-ide_lsp_service_restart (IdeLspService *self)
+static void
+on_notify_pipeline_cb (IdeLspService *self,
+ GParamSpec *pspec,
+ IdeBuildManager *build_manager)
{
- g_return_if_fail (IDE_IS_MAIN_THREAD ());
- g_return_if_fail (IDE_IS_LSP_SERVICE (self));
- g_return_if_fail (!ide_object_in_destruction (IDE_OBJECT (self)));
+ IdePipeline *pipeline;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_LSP_SERVICE (self));
+ g_assert (IDE_IS_BUILD_MANAGER (build_manager));
ide_lsp_service_stop (self);
- ensure_started (self, ide_object_get_context (IDE_OBJECT (self)));
+
+ if ((pipeline = ide_build_manager_get_pipeline (build_manager)))
+ {
+ if (!ide_pipeline_is_ready (pipeline))
+ g_signal_connect_object (pipeline,
+ "loaded",
+ G_CALLBACK (on_pipeline_loaded_cb),
+ self,
+ G_CONNECT_SWAPPED);
+ else
+ ide_lsp_service_restart (self);
+ }
+
+ IDE_EXIT;
}
/**
@@ -387,9 +602,10 @@ ide_lsp_service_class_bind_client (IdeLspServiceClass *klass,
IdeObject *provider)
{
IdeContext *context;
- g_autoptr(IdeLspService) service = NULL;
GParamSpec *pspec;
+ IDE_ENTRY;
+
g_return_if_fail (IDE_IS_MAIN_THREAD ());
g_return_if_fail (IDE_IS_LSP_SERVICE_CLASS (klass));
g_return_if_fail (IDE_IS_OBJECT (provider));
@@ -399,9 +615,59 @@ ide_lsp_service_class_bind_client (IdeLspServiceClass *klass,
context = ide_object_get_context (provider);
g_return_if_fail (IDE_IS_CONTEXT (context));
- service = ide_object_ensure_child_typed (IDE_OBJECT (context), G_OBJECT_CLASS_TYPE (klass));
- ensure_started (service, context);
+ /* If the context has a project (ie: not editor mode), then we
+ * want to track changes to the pipeline so we can reload the
+ * language server automatically.
+ */
+ if (ide_context_has_project (context))
+ {
+ IdeBuildManager *build_manager = ide_build_manager_from_context (context);
+ g_autoptr(IdeLspService) service = NULL;
+ gboolean do_notify = FALSE;
+
+ if (!(service = ide_object_get_child_typed (IDE_OBJECT (context), G_OBJECT_CLASS_TYPE (klass))))
+ {
+ service = ide_object_ensure_child_typed (IDE_OBJECT (context), G_OBJECT_CLASS_TYPE (klass));
+ g_signal_connect_object (build_manager,
+ "notify::pipeline",
+ G_CALLBACK (on_notify_pipeline_cb),
+ service,
+ G_CONNECT_SWAPPED);
+ do_notify = TRUE;
+ }
+
+ if (do_notify)
+ on_notify_pipeline_cb (service, NULL, build_manager);
+
+ g_object_bind_property (service, "client", provider, "client", G_BINDING_SYNC_CREATE);
+ }
+
+ IDE_EXIT;
+}
+
+const char *
+ide_lsp_service_get_program (IdeLspService *self)
+{
+ IdeLspServicePrivate *priv = ide_lsp_service_get_instance_private (self);
- g_object_bind_property (service, "client", provider, "client", G_BINDING_SYNC_CREATE);
+ g_return_val_if_fail (IDE_IS_LSP_SERVICE (self), NULL);
+
+ return priv->program;
+}
+
+void
+ide_lsp_service_set_program (IdeLspService *self,
+ const char *program)
+{
+ IdeLspServicePrivate *priv = ide_lsp_service_get_instance_private (self);
+
+ g_return_if_fail (IDE_IS_LSP_SERVICE (self));
+
+ if (g_strcmp0 (program, priv->program) != 0)
+ {
+ g_free (priv->program);
+ priv->program = g_strdup (program);
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_PROGRAM]);
+ }
}
diff --git a/src/libide/lsp/ide-lsp-service.h b/src/libide/lsp/ide-lsp-service.h
index 2b8654d76..48a469794 100644
--- a/src/libide/lsp/ide-lsp-service.h
+++ b/src/libide/lsp/ide-lsp-service.h
@@ -25,6 +25,8 @@
#endif
#include <libide-code.h>
+#include <libide-foundry.h>
+
#include "ide-lsp-client.h"
G_BEGIN_DECLS
@@ -38,27 +40,32 @@ struct _IdeLspServiceClass
{
IdeObjectClass parent_class;
- void (*configure_launcher) (IdeLspService *self,
- IdeSubprocessLauncher *launcher);
- void (*configure_supervisor) (IdeLspService *self,
- IdeSubprocessSupervisor *supervisor);
- void (*configure_client) (IdeLspService *self,
- IdeLspClient *client);
+ IdeSubprocessLauncher *(*create_launcher) (IdeLspService *self,
+ IdePipeline *pipeline,
+ GSubprocessFlags flags);
+ void (*configure_launcher) (IdeLspService *self,
+ IdePipeline *pipeline,
+ IdeSubprocessLauncher *launcher);
+ void (*configure_supervisor) (IdeLspService *self,
+ IdeSubprocessSupervisor *supervisor);
+ void (*configure_client) (IdeLspService *self,
+ IdeLspClient *client);
};
IDE_AVAILABLE_IN_42
-void ide_lsp_service_class_bind_client (IdeLspServiceClass *klass,
- IdeObject *provider);
-
+void ide_lsp_service_class_bind_client (IdeLspServiceClass *klass,
+ IdeObject *provider);
IDE_AVAILABLE_IN_42
-void ide_lsp_service_set_inherit_stderr (IdeLspService *self,
- gboolean dev_mode);
+void ide_lsp_service_set_inherit_stderr (IdeLspService *self,
+ gboolean inherit_stderr);
IDE_AVAILABLE_IN_42
-gboolean ide_lsp_service_get_inherit_stderr (IdeLspService *self);
-
+gboolean ide_lsp_service_get_inherit_stderr (IdeLspService *self);
+IDE_AVAILABLE_IN_42
+void ide_lsp_service_restart (IdeLspService *self);
IDE_AVAILABLE_IN_42
-void ide_lsp_service_stop (IdeLspService * self);
+const char *ide_lsp_service_get_program (IdeLspService *self);
IDE_AVAILABLE_IN_42
-void ide_lsp_service_restart (IdeLspService *self);
+void ide_lsp_service_set_program (IdeLspService *self,
+ const char *program);
G_END_DECLS
diff --git a/src/libide/lsp/meson.build b/src/libide/lsp/meson.build
index 7257f8bf7..c3e8af44e 100644
--- a/src/libide/lsp/meson.build
+++ b/src/libide/lsp/meson.build
@@ -94,6 +94,7 @@ libide_lsp_deps = [
libide_code_dep,
libide_core_dep,
libide_io_dep,
+ libide_foundry_dep,
libide_projects_dep,
libide_sourceview_dep,
libide_threading_dep,
diff --git a/src/plugins/blueprint/blueprint_plugin.py b/src/plugins/blueprint/blueprint_plugin.py
index 013357ef5..168a421e8 100644
--- a/src/plugins/blueprint/blueprint_plugin.py
+++ b/src/plugins/blueprint/blueprint_plugin.py
@@ -10,15 +10,15 @@ from gi.repository import GObject
from gi.repository import Ide
class BlueprintService(Ide.LspService):
- def do_constructed(self):
- self.set_inherit_stderr(True)
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.set_program('blueprint-compiler')
def do_configure_client(self, client):
client.add_language("blueprint")
- def do_configure_launcher(self, launcher):
- launcher.set_argv(["blueprint-compiler", "lsp"])
-
+ def do_configure_launcher(self, pipeline, launcher):
+ launcher.push_argv('lsp')
class BlueprintDiagnosticProvider(Ide.LspDiagnosticProvider, Ide.DiagnosticProvider):
def do_load(self):
diff --git a/src/plugins/jedi-language-server/jedi_language_server_plugin.py
b/src/plugins/jedi-language-server/jedi_language_server_plugin.py
index 69671b329..479c97888 100644
--- a/src/plugins/jedi-language-server/jedi_language_server_plugin.py
+++ b/src/plugins/jedi-language-server/jedi_language_server_plugin.py
@@ -27,11 +27,9 @@ from gi.repository import GObject
from gi.repository import Ide
class JediService(Ide.LspService):
- def do_constructed(self):
- self.set_inherit_stderr(True)
-
- def do_configure_launcher(self, launcher):
- launcher.push_argv("jedi-language-server")
+ def __init__(self, *args, **kwargs):
+ super().__init__(self, *args, **kwargs)
+ self.set_program('jedi-language-server')
def do_configure_client(self, client):
client.add_language('python')
@@ -46,7 +44,6 @@ class JediDiagnosticProvider(Ide.LspDiagnosticProvider, Ide.DiagnosticProvider):
class JediCompletionProvider(Ide.LspCompletionProvider, Ide.CompletionProvider):
def do_load(self, context):
- Ide.debug("load completion provider")
JediService.bind_client(self)
def do_get_priority(self, context):
diff --git a/src/plugins/ts-language-server/ts_language_server_plugin.py
b/src/plugins/ts-language-server/ts_language_server_plugin.py
index d3835fff2..567421684 100644
--- a/src/plugins/ts-language-server/ts_language_server_plugin.py
+++ b/src/plugins/ts-language-server/ts_language_server_plugin.py
@@ -28,12 +28,12 @@ from gi.repository import Ide
class TypescriptService(Ide.LspService):
- def do_constructed(self):
- self.set_inherit_stderr(True)
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.set_program('typescript-language-server')
- def do_configure_launcher(self, launcher):
- # this needs https://github.com/typescript-language-server/typescript-language-server installed on
the host
- launcher.set_argv(["typescript-language-server", "--stdio"])
+ def do_configure_launcher(self, pipeline, launcher):
+ launcher.push_argv('--stdio')
def do_configure_client(self, client):
client.add_language('javascript')
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]