lsp: Fix wrong WorkspaceFolder when opening only file (#12129)

Thorsten Ball created

This fixes #11361 and #8764 by making sure we pass a directory as
`WorkspaceFolder` to the language server.

We already compute the `working_dir` correctly when
`self.root_path.is_file()`, but we didn't use it.

Release Notes:

- Fixed language servers (such as `gopls`) not starting up correctly
when opening a single file in Zed.
([#11361](https://github.com/zed-industries/zed/issues/11361) and
[#8764](https://github.com/zed-industries/zed/issues/8764)).

Change summary

crates/lsp/src/lsp.rs | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)

Detailed changes

crates/lsp/src/lsp.rs 🔗

@@ -79,6 +79,7 @@ pub struct LanguageServer {
     io_tasks: Mutex<Option<(Task<Option<()>>, Task<Option<()>>)>>,
     output_done_rx: Mutex<Option<barrier::Receiver>>,
     root_path: PathBuf,
+    working_dir: PathBuf,
     server: Arc<Mutex<Option<Child>>>,
 }
 
@@ -288,6 +289,7 @@ impl LanguageServer {
             stderr_capture,
             Some(server),
             root_path,
+            working_dir,
             code_action_kinds,
             cx,
             move |notification| {
@@ -322,6 +324,7 @@ impl LanguageServer {
         stderr_capture: Arc<Mutex<Option<String>>>,
         server: Option<Child>,
         root_path: &Path,
+        working_dir: &Path,
         code_action_kinds: Option<Vec<CodeActionKind>>,
         cx: AsyncAppContext,
         on_unhandled_notification: F,
@@ -393,6 +396,7 @@ impl LanguageServer {
             io_tasks: Mutex::new(Some((input_task, output_task))),
             output_done_rx: Mutex::new(Some(output_done_rx)),
             root_path: root_path.to_path_buf(),
+            working_dir: working_dir.to_path_buf(),
             server: Arc::new(Mutex::new(server)),
         }
     }
@@ -566,7 +570,7 @@ impl LanguageServer {
         options: Option<Value>,
         cx: &AppContext,
     ) -> Task<Result<Arc<Self>>> {
-        let root_uri = Url::from_file_path(&self.root_path).unwrap();
+        let root_uri = Url::from_file_path(&self.working_dir).unwrap();
         #[allow(deprecated)]
         let params = InitializeParams {
             process_id: None,
@@ -1171,6 +1175,7 @@ impl FakeLanguageServer {
             Arc::new(Mutex::new(None)),
             None,
             Path::new("/"),
+            Path::new("/"),
             None,
             cx.clone(),
             |_| {},
@@ -1187,6 +1192,7 @@ impl FakeLanguageServer {
                     Arc::new(Mutex::new(None)),
                     None,
                     Path::new("/"),
+                    Path::new("/"),
                     None,
                     cx,
                     move |msg| {