From 7c9809eeb2708a9eba3c3cc48c9513e9892409f0 Mon Sep 17 00:00:00 2001
From: ath3 <45574139+ath3@users.noreply.github.com>
Date: Mon, 3 Oct 2022 17:02:49 +0200
Subject: [PATCH] Find workspace from document path (#3553)

---
 helix-lsp/src/client.rs          |  6 +++++-
 helix-lsp/src/lib.rs             | 15 ++++++++++++---
 helix-term/src/commands/typed.rs |  2 +-
 helix-view/src/editor.rs         |  2 +-
 4 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/helix-lsp/src/client.rs b/helix-lsp/src/client.rs
index 497ce80c..0b443ccf 100644
--- a/helix-lsp/src/client.rs
+++ b/helix-lsp/src/client.rs
@@ -49,6 +49,7 @@ impl Client {
         root_markers: &[String],
         id: usize,
         req_timeout: u64,
+        doc_path: Option<&std::path::PathBuf>,
     ) -> Result<(Self, UnboundedReceiver<(usize, Call)>, Arc<Notify>)> {
         // Resolve path to the binary
         let cmd = which::which(cmd).map_err(|err| anyhow::anyhow!(err))?;
@@ -72,7 +73,10 @@ impl Client {
         let (server_rx, server_tx, initialize_notify) =
             Transport::start(reader, writer, stderr, id);
 
-        let root_path = find_root(None, root_markers);
+        let root_path = find_root(
+            doc_path.and_then(|x| x.parent().and_then(|x| x.to_str())),
+            root_markers,
+        );
 
         let root_uri = lsp::Url::from_file_path(root_path.clone()).ok();
 
diff --git a/helix-lsp/src/lib.rs b/helix-lsp/src/lib.rs
index 98300a62..feeedc96 100644
--- a/helix-lsp/src/lib.rs
+++ b/helix-lsp/src/lib.rs
@@ -353,6 +353,7 @@ impl Registry {
     pub fn restart(
         &mut self,
         language_config: &LanguageConfiguration,
+        doc_path: Option<&std::path::PathBuf>,
     ) -> Result<Option<Arc<Client>>> {
         let config = match &language_config.language_server {
             Some(config) => config,
@@ -367,7 +368,8 @@ impl Registry {
                 // initialize a new client
                 let id = self.counter.fetch_add(1, Ordering::Relaxed);
 
-                let NewClientResult(client, incoming) = start_client(id, language_config, config)?;
+                let NewClientResult(client, incoming) =
+                    start_client(id, language_config, config, doc_path)?;
                 self.incoming.push(UnboundedReceiverStream::new(incoming));
 
                 let (_, old_client) = entry.insert((id, client.clone()));
@@ -381,7 +383,11 @@ impl Registry {
         }
     }
 
-    pub fn get(&mut self, language_config: &LanguageConfiguration) -> Result<Option<Arc<Client>>> {
+    pub fn get(
+        &mut self,
+        language_config: &LanguageConfiguration,
+        doc_path: Option<&std::path::PathBuf>,
+    ) -> Result<Option<Arc<Client>>> {
         let config = match &language_config.language_server {
             Some(config) => config,
             None => return Ok(None),
@@ -393,7 +399,8 @@ impl Registry {
                 // initialize a new client
                 let id = self.counter.fetch_add(1, Ordering::Relaxed);
 
-                let NewClientResult(client, incoming) = start_client(id, language_config, config)?;
+                let NewClientResult(client, incoming) =
+                    start_client(id, language_config, config, doc_path)?;
                 self.incoming.push(UnboundedReceiverStream::new(incoming));
 
                 entry.insert((id, client.clone()));
@@ -493,6 +500,7 @@ fn start_client(
     id: usize,
     config: &LanguageConfiguration,
     ls_config: &LanguageServerConfiguration,
+    doc_path: Option<&std::path::PathBuf>,
 ) -> Result<NewClientResult> {
     let (client, incoming, initialize_notify) = Client::start(
         &ls_config.command,
@@ -501,6 +509,7 @@ fn start_client(
         &config.roots,
         id,
         ls_config.timeout,
+        doc_path,
     )?;
 
     let client = Arc::new(client);
diff --git a/helix-term/src/commands/typed.rs b/helix-term/src/commands/typed.rs
index d5a368a2..c2c37291 100644
--- a/helix-term/src/commands/typed.rs
+++ b/helix-term/src/commands/typed.rs
@@ -1000,7 +1000,7 @@ fn lsp_restart(
         .context("LSP not defined for the current document")?;
 
     let scope = config.scope.clone();
-    cx.editor.language_servers.restart(config)?;
+    cx.editor.language_servers.restart(config, doc.path())?;
 
     // This collect is needed because refresh_language_server would need to re-borrow editor.
     let document_ids_to_refresh: Vec<DocumentId> = cx
diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs
index f3b0e26f..e144a830 100644
--- a/helix-view/src/editor.rs
+++ b/helix-view/src/editor.rs
@@ -868,7 +868,7 @@ impl Editor {
 
         // try to find a language server based on the language name
         let language_server = doc.language.as_ref().and_then(|language| {
-            ls.get(language)
+            ls.get(language, doc.path())
                 .map_err(|e| {
                     log::error!(
                         "Failed to initialize the LSP for `{}` {{ {} }}",