[gnome-builder] lsp: add search-path support to IdeLspService



commit 4859df583545247d0a0d49bfe32481fdbda4bf1c
Author: Christian Hergert <chergert redhat com>
Date:   Tue Dec 21 16:56:49 2021 -0800

    lsp: add search-path support to IdeLspService
    
    This allows locating a binary in an alternate path on the host system if
    we do not find it in the normal runtime locations.

 src/libide/lsp/ide-lsp-service.c | 105 ++++++++++++++++++++++++++++++++++-----
 src/libide/lsp/ide-lsp-service.h |  23 +++++----
 2 files changed, 107 insertions(+), 21 deletions(-)
---
diff --git a/src/libide/lsp/ide-lsp-service.c b/src/libide/lsp/ide-lsp-service.c
index ba8beb152..8d1f9b3c1 100644
--- a/src/libide/lsp/ide-lsp-service.c
+++ b/src/libide/lsp/ide-lsp-service.c
@@ -37,6 +37,7 @@ typedef struct
   IdeSubprocessSupervisor *supervisor;
   IdeLspClient *client;
   char *program;
+  char **search_path;
   guint has_started : 1;
   guint inherit_stderr : 1;
 } IdeLspServicePrivate;
@@ -48,6 +49,7 @@ enum {
   PROP_CLIENT,
   PROP_INHERIT_STDERR,
   PROP_PROGRAM,
+  PROP_SEARCH_PATH,
   PROP_SUPERVISOR,
   N_PROPS
 };
@@ -121,6 +123,10 @@ ide_lsp_service_get_property (GObject    *object,
       g_value_set_string (value, priv->program);
       break;
 
+    case PROP_SEARCH_PATH:
+      g_value_set_boxed (value, priv->search_path);
+      break;
+
     case PROP_SUPERVISOR:
       g_value_set_object (value, priv->supervisor);
       break;
@@ -152,6 +158,10 @@ ide_lsp_service_set_property (GObject      *object,
       ide_lsp_service_set_program (self, g_value_get_string (value));
       break;
 
+    case PROP_SEARCH_PATH:
+      ide_lsp_service_set_search_path (self, g_value_get_boxed (value));
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     }
@@ -169,6 +179,8 @@ ide_lsp_service_destroy (IdeObject *object)
 
   g_clear_object (&priv->supervisor);
   g_clear_object (&priv->client);
+  g_clear_pointer (&priv->program, g_free);
+  g_clear_pointer (&priv->search_path, g_strfreev);
 
   IDE_OBJECT_CLASS (ide_lsp_service_parent_class)->destroy (object);
 
@@ -183,6 +195,7 @@ ide_lsp_service_real_create_launcher (IdeLspService    *self,
   IdeLspServicePrivate *priv = ide_lsp_service_get_instance_private (self);
   g_autoptr(IdeSubprocessLauncher) launcher = NULL;
   g_autoptr(IdeContext) context = NULL;
+  const char *srcdir;
 
   IDE_ENTRY;
 
@@ -193,12 +206,18 @@ ide_lsp_service_real_create_launcher (IdeLspService    *self,
     IDE_RETURN (NULL);
 
   context = ide_object_ref_context (IDE_OBJECT (self));
+  srcdir = ide_pipeline_get_srcdir (pipeline);
 
   /* 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);
+        {
+          ide_subprocess_launcher_set_flags (launcher, flags);
+          ide_subprocess_launcher_push_argv (launcher, priv->program);
+          ide_subprocess_launcher_set_cwd (launcher, srcdir);
+          IDE_RETURN (g_steal_pointer (&launcher));
+        }
     }
 
   /* Then try on the host if we find it there */
@@ -210,7 +229,34 @@ ide_lsp_service_real_create_launcher (IdeLspService    *self,
       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);
+            {
+              ide_subprocess_launcher_set_flags (launcher, flags);
+              ide_subprocess_launcher_push_argv (launcher, priv->program);
+              ide_subprocess_launcher_set_cwd (launcher, srcdir);
+              IDE_RETURN (g_steal_pointer (&launcher));
+            }
+        }
+
+      /* If we didn't find it in the host, we might have an alternate
+       * search path we can try.
+       */
+      if (priv->search_path)
+        {
+          for (guint i = 0; priv->search_path[i]; i++)
+            {
+              g_autofree char *path = g_build_filename (priv->search_path[i], priv->program, NULL);
+
+              if (g_file_test (path, G_FILE_TEST_IS_EXECUTABLE))
+                {
+                  if ((launcher = ide_runtime_create_launcher (host, NULL)))
+                    {
+                      ide_subprocess_launcher_push_argv (launcher, path);
+                      ide_subprocess_launcher_set_flags (launcher, flags);
+                      ide_subprocess_launcher_set_cwd (launcher, srcdir);
+                      IDE_RETURN (g_steal_pointer (&launcher));
+                    }
+                }
+            }
         }
     }
 
@@ -220,18 +266,15 @@ ide_lsp_service_real_create_launcher (IdeLspService    *self,
       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);
+        {
+          launcher = ide_subprocess_launcher_new (flags);
+          ide_subprocess_launcher_push_argv (launcher, path);
+          ide_subprocess_launcher_set_cwd (launcher, srcdir);
+          IDE_RETURN (g_steal_pointer (&launcher));
+        }
     }
 
-  IDE_RETURN (g_steal_pointer (&launcher));
+  IDE_RETURN (NULL);
 }
 
 G_NORETURN static void
@@ -309,6 +352,18 @@ ide_lsp_service_class_init (IdeLspServiceClass *klass)
                          NULL,
                          (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
 
+  /**
+   * IdeLspService:search-path:
+   *
+   * An alternate search path to locate the program on the host.
+   */
+  properties [PROP_SEARCH_PATH] =
+    g_param_spec_boxed ("search-path",
+                        "Search Path",
+                        "Search Path",
+                        G_TYPE_STRV,
+                        (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
   /**
    * IdeLspService:supervisor:
    *
@@ -671,3 +726,29 @@ ide_lsp_service_set_program (IdeLspService *self,
       g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_PROGRAM]);
     }
 }
+
+const char * const *
+ide_lsp_service_get_search_path (IdeLspService *self)
+{
+  IdeLspServicePrivate *priv = ide_lsp_service_get_instance_private (self);
+
+  g_return_val_if_fail (IDE_IS_LSP_SERVICE (self), NULL);
+
+  return (const char * const *)priv->search_path;
+}
+
+void
+ide_lsp_service_set_search_path (IdeLspService      *self,
+                                 const char * const *search_path)
+{
+  IdeLspServicePrivate *priv = ide_lsp_service_get_instance_private (self);
+
+  g_return_if_fail (IDE_IS_LSP_SERVICE (self));
+
+  if ((const char * const *)priv->search_path == search_path)
+    return;
+
+  g_strfreev (priv->search_path);
+  priv->search_path = g_strdupv ((char **)search_path);
+  g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_SEARCH_PATH]);
+}
diff --git a/src/libide/lsp/ide-lsp-service.h b/src/libide/lsp/ide-lsp-service.h
index 48a469794..ff1fc8808 100644
--- a/src/libide/lsp/ide-lsp-service.h
+++ b/src/libide/lsp/ide-lsp-service.h
@@ -53,19 +53,24 @@ struct _IdeLspServiceClass
 };
 
 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            inherit_stderr);
+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);
+void                ide_lsp_service_restart            (IdeLspService      *self);
 IDE_AVAILABLE_IN_42
-const char *ide_lsp_service_get_program        (IdeLspService *self);
+const char         *ide_lsp_service_get_program        (IdeLspService      *self);
 IDE_AVAILABLE_IN_42
-void        ide_lsp_service_set_program        (IdeLspService      *self,
-                                                const char         *program);
+void                ide_lsp_service_set_program        (IdeLspService      *self,
+                                                        const char         *program);
+IDE_AVAILABLE_IN_42
+const char * const *ide_lsp_service_get_search_path    (IdeLspService      *self);
+IDE_AVAILABLE_IN_42
+void                ide_lsp_service_set_search_path    (IdeLspService      *self,
+                                                        const char * const *search_path);
 
 G_END_DECLS


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