elixir: Respect LSP settings for Lexical (#14655)

Marshall Bowers created

This PR updates the Elixir extension with support for reading the LSP
settings when using Lexical as the language server.

Release Notes:

- N/A

Change summary

extensions/elixir/src/elixir.rs                   |  6 +
extensions/elixir/src/language_servers/lexical.rs | 39 ++++++++++++++--
2 files changed, 38 insertions(+), 7 deletions(-)

Detailed changes

extensions/elixir/src/elixir.rs 🔗

@@ -47,10 +47,12 @@ impl zed::Extension for ElixirExtension {
             }
             Lexical::LANGUAGE_SERVER_ID => {
                 let lexical = self.lexical.get_or_insert_with(|| Lexical::new());
+                let lexical_binary =
+                    lexical.language_server_binary(language_server_id, worktree)?;
 
                 Ok(zed::Command {
-                    command: lexical.language_server_binary_path(language_server_id, worktree)?,
-                    args: vec![],
+                    command: lexical_binary.path,
+                    args: lexical_binary.args.unwrap_or_default(),
                     env: Default::default(),
                 })
             }

extensions/elixir/src/language_servers/lexical.rs 🔗

@@ -2,8 +2,14 @@ use std::fs;
 
 use zed::lsp::{Completion, CompletionKind, Symbol};
 use zed::{CodeLabel, CodeLabelSpan, LanguageServerId};
+use zed_extension_api::settings::LspSettings;
 use zed_extension_api::{self as zed, Result};
 
+pub struct LexicalBinary {
+    pub path: String,
+    pub args: Option<Vec<String>>,
+}
+
 pub struct Lexical {
     cached_binary_path: Option<String>,
 }
@@ -17,18 +23,38 @@ impl Lexical {
         }
     }
 
-    pub fn language_server_binary_path(
+    pub fn language_server_binary(
         &mut self,
         language_server_id: &LanguageServerId,
         worktree: &zed::Worktree,
-    ) -> Result<String> {
+    ) -> Result<LexicalBinary> {
+        let binary_settings = LspSettings::for_worktree("lexical", worktree)
+            .ok()
+            .and_then(|lsp_settings| lsp_settings.binary);
+        let binary_args = binary_settings
+            .as_ref()
+            .and_then(|binary_settings| binary_settings.arguments.clone());
+
+        if let Some(path) = binary_settings.and_then(|binary_settings| binary_settings.path) {
+            return Ok(LexicalBinary {
+                path,
+                args: binary_args,
+            });
+        }
+
         if let Some(path) = worktree.which("lexical") {
-            return Ok(path);
+            return Ok(LexicalBinary {
+                path,
+                args: binary_args,
+            });
         }
 
         if let Some(path) = &self.cached_binary_path {
             if fs::metadata(path).map_or(false, |stat| stat.is_file()) {
-                return Ok(path.clone());
+                return Ok(LexicalBinary {
+                    path: path.clone(),
+                    args: binary_args,
+                });
             }
         }
 
@@ -79,7 +105,10 @@ impl Lexical {
         }
 
         self.cached_binary_path = Some(binary_path.clone());
-        Ok(binary_path)
+        Ok(LexicalBinary {
+            path: binary_path,
+            args: binary_args,
+        })
     }
 
     pub fn label_for_completion(&self, completion: Completion) -> Option<CodeLabel> {