From 834d50f0db0b6427c5c8fae61e4b903b136b112e Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Wed, 16 Oct 2024 18:12:36 +0300 Subject: [PATCH] Properly open worktrees when cmd-clicking in terminal or on inlay hints (#19280) * uses the state that's synced, to fetch the language server name * uses proper, canonicalized path when creating a remote ssh worktree, otherwise `~/foo/something` stays unexpanded Release Notes: - N/A --- crates/editor/src/editor.rs | 18 +++---- crates/project/src/lsp_store.rs | 55 +++++++++++--------- crates/project/src/project.rs | 11 ---- crates/project/src/worktree_store.rs | 2 +- crates/proto/proto/zed.proto | 1 + crates/remote_server/src/headless_project.rs | 3 +- 6 files changed, 43 insertions(+), 47 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 5e33b38dac..378ccb905d 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -96,7 +96,9 @@ use language::{ CursorShape, Diagnostic, Documentation, IndentKind, IndentSize, Language, OffsetRangeExt, Point, Selection, SelectionGoal, TransactionId, }; -use language::{point_to_lsp, BufferRow, CharClassifier, Runnable, RunnableRange}; +use language::{ + point_to_lsp, BufferRow, CharClassifier, LanguageServerName, Runnable, RunnableRange, +}; use linked_editing_ranges::refresh_linked_ranges; pub use proposed_changes_editor::{ ProposedChangesBuffer, ProposedChangesEditor, ProposedChangesEditorToolbar, @@ -9893,21 +9895,19 @@ impl Editor { &self, lsp_location: lsp::Location, server_id: LanguageServerId, - cx: &mut ViewContext, + cx: &mut ViewContext, ) -> Task>> { let Some(project) = self.project.clone() else { return Task::Ready(Some(Ok(None))); }; cx.spawn(move |editor, mut cx| async move { - let location_task = editor.update(&mut cx, |editor, cx| { + let location_task = editor.update(&mut cx, |_, cx| { project.update(cx, |project, cx| { - let language_server_name = - editor.buffer.read(cx).as_singleton().and_then(|buffer| { - project - .language_server_for_buffer(buffer.read(cx), server_id, cx) - .map(|(lsp_adapter, _)| lsp_adapter.name.clone()) - }); + let language_server_name = project + .language_server_statuses(cx) + .find(|(id, _)| server_id == *id) + .map(|(_, status)| LanguageServerName::from(status.name.as_str())); language_server_name.map(|language_server_name| { project.open_local_buffer_via_lsp( lsp_location.uri.clone(), diff --git a/crates/project/src/lsp_store.rs b/crates/project/src/lsp_store.rs index d72f631bdc..61f959259d 100644 --- a/crates/project/src/lsp_store.rs +++ b/crates/project/src/lsp_store.rs @@ -3503,7 +3503,7 @@ impl LspStore { language_server_name: LanguageServerName, cx: &mut ModelContext, ) -> Task>> { - cx.spawn(move |this, mut cx| async move { + cx.spawn(move |lsp_store, mut cx| async move { // Escape percent-encoded string. let current_scheme = abs_path.scheme().to_owned(); let _ = abs_path.set_scheme("file"); @@ -3512,9 +3512,9 @@ impl LspStore { .to_file_path() .map_err(|_| anyhow!("can't convert URI to path"))?; let p = abs_path.clone(); - let yarn_worktree = this - .update(&mut cx, move |this, cx| { - this.as_local().unwrap().yarn.update(cx, |_, cx| { + let yarn_worktree = lsp_store + .update(&mut cx, move |lsp_store, cx| match lsp_store.as_local() { + Some(local_lsp_store) => local_lsp_store.yarn.update(cx, |_, cx| { cx.spawn(|this, mut cx| async move { let t = this .update(&mut cx, |this, cx| { @@ -3523,7 +3523,8 @@ impl LspStore { .ok()?; t.await }) - }) + }), + None => Task::ready(None), })? .await; let (worktree_root_target, known_relative_path) = @@ -3533,8 +3534,8 @@ impl LspStore { (Arc::::from(abs_path.as_path()), None) }; let (worktree, relative_path) = if let Some(result) = - this.update(&mut cx, |this, cx| { - this.worktree_store.update(cx, |worktree_store, cx| { + lsp_store.update(&mut cx, |lsp_store, cx| { + lsp_store.worktree_store.update(cx, |worktree_store, cx| { worktree_store.find_worktree(&worktree_root_target, cx) }) })? { @@ -3542,22 +3543,25 @@ impl LspStore { known_relative_path.unwrap_or_else(|| Arc::::from(result.1)); (result.0, relative_path) } else { - let worktree = this - .update(&mut cx, |this, cx| { - this.worktree_store.update(cx, |worktree_store, cx| { + let worktree = lsp_store + .update(&mut cx, |lsp_store, cx| { + lsp_store.worktree_store.update(cx, |worktree_store, cx| { worktree_store.create_worktree(&worktree_root_target, false, cx) }) })? .await?; - this.update(&mut cx, |this, cx| { - this.register_language_server( - worktree.read(cx).id(), - language_server_name, - language_server_id, - ) - }) - .ok(); - let worktree_root = worktree.update(&mut cx, |this, _| this.abs_path())?; + if worktree.update(&mut cx, |worktree, _| worktree.is_local())? { + lsp_store + .update(&mut cx, |lsp_store, cx| { + lsp_store.register_language_server( + worktree.read(cx).id(), + language_server_name, + language_server_id, + ) + }) + .ok(); + } + let worktree_root = worktree.update(&mut cx, |worktree, _| worktree.abs_path())?; let relative_path = if let Some(known_path) = known_relative_path { known_path } else { @@ -3569,12 +3573,13 @@ impl LspStore { worktree_id: worktree.update(&mut cx, |worktree, _| worktree.id())?, path: relative_path, }; - this.update(&mut cx, |this, cx| { - this.buffer_store().update(cx, |buffer_store, cx| { - buffer_store.open_buffer(project_path, cx) - }) - })? - .await + lsp_store + .update(&mut cx, |lsp_store, cx| { + lsp_store.buffer_store().update(cx, |buffer_store, cx| { + buffer_store.open_buffer(project_path, cx) + }) + })? + .await }) } diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index d26ee3a211..03074fb6a6 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -3979,17 +3979,6 @@ impl Project { .read(cx) .language_servers_for_buffer(buffer, cx) } - - pub fn language_server_for_buffer<'a>( - &'a self, - buffer: &'a Buffer, - server_id: LanguageServerId, - cx: &'a AppContext, - ) -> Option<(&'a Arc, &'a Arc)> { - self.lsp_store - .read(cx) - .language_server_for_buffer(buffer, server_id, cx) - } } fn deserialize_code_actions(code_actions: &HashMap) -> Vec { diff --git a/crates/project/src/worktree_store.rs b/crates/project/src/worktree_store.rs index 55eb0108e2..c49d3b062e 100644 --- a/crates/project/src/worktree_store.rs +++ b/crates/project/src/worktree_store.rs @@ -280,7 +280,7 @@ impl WorktreeStore { id: response.worktree_id, root_name, visible, - abs_path, + abs_path: response.canonicalized_path, }, client, cx, diff --git a/crates/proto/proto/zed.proto b/crates/proto/proto/zed.proto index fbd1cf4215..750aa924b4 100644 --- a/crates/proto/proto/zed.proto +++ b/crates/proto/proto/zed.proto @@ -2464,6 +2464,7 @@ message AddWorktree { message AddWorktreeResponse { uint64 worktree_id = 1; + string canonicalized_path = 2; } message UpdateUserSettings { diff --git a/crates/remote_server/src/headless_project.rs b/crates/remote_server/src/headless_project.rs index f17c27a03c..e6eddac1d0 100644 --- a/crates/remote_server/src/headless_project.rs +++ b/crates/remote_server/src/headless_project.rs @@ -275,7 +275,7 @@ impl HeadlessProject { let worktree = this .update(&mut cx.clone(), |this, _| { Worktree::local( - Arc::from(canonicalized), + Arc::from(canonicalized.as_path()), message.payload.visible, this.fs.clone(), this.next_entry_id.clone(), @@ -287,6 +287,7 @@ impl HeadlessProject { let response = this.update(&mut cx, |_, cx| { worktree.update(cx, |worktree, _| proto::AddWorktreeResponse { worktree_id: worktree.id().to_proto(), + canonicalized_path: canonicalized.to_string_lossy().to_string(), }) })?;