From 9c9a09cccb41c4ea2a3d06b32170876e77946ba1 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 19 Jan 2022 15:56:04 +0100 Subject: [PATCH] Replace `project_path` with `project_entry` in `workspace::{Item, ItemView}` --- crates/diagnostics/src/diagnostics.rs | 4 +- crates/editor/src/items.rs | 18 +++---- crates/project/src/project.rs | 8 ++++ crates/project/src/worktree.rs | 9 +++- crates/workspace/src/pane.rs | 30 ++++++------ crates/workspace/src/workspace.rs | 50 +++++++++++++------- crates/zed/src/zed.rs | 67 ++++++++++++++++++++------- 7 files changed, 122 insertions(+), 64 deletions(-) diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index 0cc4362a46..85b40acd8d 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -528,7 +528,7 @@ impl workspace::Item for ProjectDiagnostics { ProjectDiagnosticsEditor::new(handle, workspace.weak_handle(), workspace.settings(), cx) } - fn project_path(&self) -> Option { + fn project_entry(&self) -> Option { None } } @@ -544,7 +544,7 @@ impl workspace::ItemView for ProjectDiagnosticsEditor { "Project Diagnostics".to_string() } - fn project_path(&self, _: &AppContext) -> Option { + fn project_entry(&self, _: &AppContext) -> Option { None } diff --git a/crates/editor/src/items.rs b/crates/editor/src/items.rs index d3efb806c8..8158c5f6c4 100644 --- a/crates/editor/src/items.rs +++ b/crates/editor/src/items.rs @@ -6,7 +6,7 @@ use gpui::{ }; use language::{Bias, Buffer, Diagnostic, File as _}; use postage::watch; -use project::{File, ProjectPath, Worktree}; +use project::{File, ProjectEntry, ProjectPath, Worktree}; use std::fmt::Write; use std::path::Path; use std::rc::Rc; @@ -74,11 +74,8 @@ impl ItemHandle for BufferItemHandle { Box::new(WeakBufferItemHandle(self.0.downgrade())) } - fn project_path(&self, cx: &AppContext) -> Option { - File::from_dyn(self.0.read(cx).file()).map(|f| ProjectPath { - worktree_id: f.worktree_id(cx), - path: f.path().clone(), - }) + fn project_entry(&self, cx: &AppContext) -> Option { + File::from_dyn(self.0.read(cx).file()).and_then(|f| f.project_entry(cx)) } fn id(&self) -> usize { @@ -134,11 +131,8 @@ impl ItemView for Editor { } } - fn project_path(&self, cx: &AppContext) -> Option { - File::from_dyn(self.buffer().read(cx).file(cx)).map(|file| ProjectPath { - worktree_id: file.worktree_id(cx), - path: file.path().clone(), - }) + fn project_entry(&self, cx: &AppContext) -> Option { + File::from_dyn(self.buffer().read(cx).file(cx)).and_then(|file| file.project_entry(cx)) } fn clone_on_split(&self, cx: &mut ViewContext) -> Option @@ -163,7 +157,7 @@ impl ItemView for Editor { } fn can_save(&self, cx: &AppContext) -> bool { - self.project_path(cx).is_some() + self.project_entry(cx).is_some() } fn save(&mut self, cx: &mut ViewContext) -> Result>> { diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index a8b38a2bb2..310274239f 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -567,6 +567,14 @@ impl Project { } } + pub fn path_for_entry(&self, entry: ProjectEntry, cx: &AppContext) -> Option { + let worktree = self.worktree_for_id(entry.worktree_id, cx)?.read(cx); + Some(ProjectPath { + worktree_id: entry.worktree_id, + path: worktree.entry_for_id(entry.entry_id)?.path.clone(), + }) + } + pub fn is_running_disk_based_diagnostics(&self) -> bool { self.pending_disk_based_diagnostics > 0 } diff --git a/crates/project/src/worktree.rs b/crates/project/src/worktree.rs index c01e660eab..ee36d0bcad 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project/src/worktree.rs @@ -1,7 +1,7 @@ use super::{ fs::{self, Fs}, ignore::IgnoreStack, - DiagnosticSummary, + DiagnosticSummary, ProjectEntry, }; use ::ignore::gitignore::{Gitignore, GitignoreBuilder}; use anyhow::{anyhow, Context, Result}; @@ -2372,6 +2372,13 @@ impl File { pub fn worktree_id(&self, cx: &AppContext) -> WorktreeId { self.worktree.read(cx).id() } + + pub fn project_entry(&self, cx: &AppContext) -> Option { + self.entry_id.map(|entry_id| ProjectEntry { + worktree_id: self.worktree_id(cx), + entry_id, + }) + } } #[derive(Clone, Debug)] diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index 07d5ffee47..3944a5d49d 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -10,7 +10,7 @@ use gpui::{ Entity, MutableAppContext, Quad, RenderContext, Task, View, ViewContext, ViewHandle, }; use postage::watch; -use project::ProjectPath; +use project::ProjectEntry; use std::{any::Any, cell::RefCell, cmp, mem, rc::Rc}; use util::ResultExt; @@ -87,7 +87,7 @@ struct NavHistoryState { mode: NavigationMode, backward_stack: VecDeque, forward_stack: VecDeque, - paths_by_item: HashMap, + project_entries_by_item: HashMap, } #[derive(Copy, Clone)] @@ -148,10 +148,10 @@ impl Pane { ) -> Task<()> { let to_load = pane.update(cx, |pane, cx| { // Retrieve the weak item handle from the history. - let entry = pane.nav_history.pop(mode)?; + let nav_entry = pane.nav_history.pop(mode)?; // If the item is still present in this pane, then activate it. - if let Some(index) = entry + if let Some(index) = nav_entry .item_view .upgrade(cx) .and_then(|v| pane.index_for_item_view(v.as_ref())) @@ -164,7 +164,7 @@ impl Pane { pane.active_item_index = index; pane.focus_active_item(cx); - if let Some(data) = entry.data { + if let Some(data) = nav_entry.data { pane.active_item()?.navigate(data, cx); } cx.notify(); @@ -176,17 +176,17 @@ impl Pane { pane.nav_history .0 .borrow_mut() - .paths_by_item - .get(&entry.item_view.id()) + .project_entries_by_item + .get(&nav_entry.item_view.id()) .cloned() - .map(|project_path| (project_path, entry)) + .map(|project_entry| (project_entry, nav_entry)) } }); - if let Some((project_path, entry)) = to_load { + if let Some((project_entry, nav_entry)) = to_load { // If the item was no longer present, then load it again from its previous path. let pane = pane.downgrade(); - let task = workspace.load_path(project_path, cx); + let task = workspace.load_entry(project_entry, cx); cx.spawn(|workspace, mut cx| async move { let item = task.await; if let Some(pane) = cx.read(|cx| pane.upgrade(cx)) { @@ -196,7 +196,7 @@ impl Pane { let item_view = workspace.open_item_in_pane(item, &pane, cx); pane.update(cx, |p, _| p.nav_history.set_mode(NavigationMode::Normal)); - if let Some(data) = entry.data { + if let Some(data) = nav_entry.data { item_view.navigate(data, cx); } }); @@ -323,10 +323,12 @@ impl Pane { } let mut nav_history = self.nav_history.0.borrow_mut(); - if let Some(path) = item_view.project_path(cx) { - nav_history.paths_by_item.insert(item_view.id(), path); + if let Some(entry) = item_view.project_entry(cx) { + nav_history + .project_entries_by_item + .insert(item_view.id(), entry); } else { - nav_history.paths_by_item.remove(&item_view.id()); + nav_history.project_entries_by_item.remove(&item_view.id()); } item_ix += 1; diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index b5822d75e6..949c0193ea 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -27,7 +27,7 @@ pub use pane::*; pub use pane_group::*; use parking_lot::Mutex; use postage::{prelude::Stream, watch}; -use project::{fs, Fs, Project, ProjectPath, Worktree}; +use project::{fs, Fs, Project, ProjectEntry, ProjectPath, Worktree}; pub use settings::Settings; use sidebar::{Side, Sidebar, SidebarItemId, ToggleSidebarItem, ToggleSidebarItemFocus}; use status_bar::StatusBar; @@ -140,8 +140,7 @@ pub trait Item: Entity + Sized { nav_history: Rc, cx: &mut ViewContext, ) -> Self::View; - - fn project_path(&self) -> Option; + fn project_entry(&self) -> Option; } pub trait ItemView: View { @@ -151,7 +150,7 @@ pub trait ItemView: View { fn navigate(&mut self, _: Box, _: &mut ViewContext) {} fn item_handle(&self, cx: &AppContext) -> Self::ItemHandle; fn title(&self, cx: &AppContext) -> String; - fn project_path(&self, cx: &AppContext) -> Option; + fn project_entry(&self, cx: &AppContext) -> Option; fn clone_on_split(&self, _: &mut ViewContext) -> Option where Self: Sized, @@ -196,7 +195,7 @@ pub trait ItemHandle: Send + Sync { fn boxed_clone(&self) -> Box; fn downgrade(&self) -> Box; fn to_any(&self) -> AnyModelHandle; - fn project_path(&self, cx: &AppContext) -> Option; + fn project_entry(&self, cx: &AppContext) -> Option; } pub trait WeakItemHandle { @@ -207,7 +206,7 @@ pub trait WeakItemHandle { pub trait ItemViewHandle { fn item_handle(&self, cx: &AppContext) -> Box; fn title(&self, cx: &AppContext) -> String; - fn project_path(&self, cx: &AppContext) -> Option; + fn project_entry(&self, cx: &AppContext) -> Option; fn boxed_clone(&self) -> Box; fn clone_on_split(&self, cx: &mut MutableAppContext) -> Option>; fn added_to_pane(&mut self, cx: &mut ViewContext); @@ -262,8 +261,8 @@ impl ItemHandle for ModelHandle { self.clone().into() } - fn project_path(&self, cx: &AppContext) -> Option { - self.read(cx).project_path() + fn project_entry(&self, cx: &AppContext) -> Option { + self.read(cx).project_entry() } } @@ -294,8 +293,8 @@ impl ItemHandle for Box { self.as_ref().to_any() } - fn project_path(&self, cx: &AppContext) -> Option { - self.as_ref().project_path(cx) + fn project_entry(&self, cx: &AppContext) -> Option { + self.as_ref().project_entry(cx) } } @@ -332,8 +331,8 @@ impl ItemViewHandle for ViewHandle { self.read(cx).title(cx) } - fn project_path(&self, cx: &AppContext) -> Option { - self.read(cx).project_path(cx) + fn project_entry(&self, cx: &AppContext) -> Option { + self.read(cx).project_entry(cx) } fn boxed_clone(&self) -> Box { @@ -776,6 +775,18 @@ impl Workspace { }) } + pub fn load_entry( + &mut self, + path: ProjectEntry, + cx: &mut ViewContext, + ) -> Task>> { + if let Some(path) = self.project.read(cx).path_for_entry(path, cx) { + self.load_path(path, cx) + } else { + Task::ready(Err(anyhow!("entry does not exist"))) + } + } + pub fn load_path( &mut self, path: ProjectPath, @@ -805,10 +816,13 @@ impl Workspace { } fn item_for_path(&self, path: &ProjectPath, cx: &AppContext) -> Option> { - self.items - .iter() - .filter_map(|i| i.upgrade(cx)) - .find(|i| i.project_path(cx).as_ref() == Some(path)) + let project = self.project.read(cx); + self.items.iter().filter_map(|i| i.upgrade(cx)).find(|i| { + let item_path = i + .project_entry(cx) + .and_then(|entry| project.path_for_entry(entry, cx)); + item_path.as_ref() == Some(path) + }) } pub fn item_of_type(&self, cx: &AppContext) -> Option> { @@ -822,7 +836,9 @@ impl Workspace { } fn active_project_path(&self, cx: &ViewContext) -> Option { - self.active_item(cx).and_then(|item| item.project_path(cx)) + self.active_item(cx) + .and_then(|item| item.project_entry(cx)) + .and_then(|entry| self.project.read(cx).path_for_entry(entry, cx)) } pub fn save_active_item(&mut self, _: &Save, cx: &mut ViewContext) { diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index f5aeec861a..ac24bd9aea 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -268,9 +268,11 @@ mod tests { .await .unwrap(); cx.read(|cx| { - let pane = workspace.read(cx).active_pane().read(cx); + let workspace = workspace.read(cx); + let pane = workspace.active_pane().read(cx); + let entry = pane.active_item().unwrap().project_entry(cx).unwrap(); assert_eq!( - pane.active_item().unwrap().project_path(cx), + workspace.project().read(cx).path_for_entry(entry, cx), Some(file1.clone()) ); assert_eq!(pane.item_views().count(), 1); @@ -282,9 +284,11 @@ mod tests { .await .unwrap(); cx.read(|cx| { - let pane = workspace.read(cx).active_pane().read(cx); + let workspace = workspace.read(cx); + let pane = workspace.active_pane().read(cx); + let entry = pane.active_item().unwrap().project_entry(cx).unwrap(); assert_eq!( - pane.active_item().unwrap().project_path(cx), + workspace.project().read(cx).path_for_entry(entry, cx), Some(file2.clone()) ); assert_eq!(pane.item_views().count(), 2); @@ -298,9 +302,11 @@ mod tests { assert_eq!(entry_1.id(), entry_1b.id()); cx.read(|cx| { - let pane = workspace.read(cx).active_pane().read(cx); + let workspace = workspace.read(cx); + let pane = workspace.active_pane().read(cx); + let entry = pane.active_item().unwrap().project_entry(cx).unwrap(); assert_eq!( - pane.active_item().unwrap().project_path(cx), + workspace.project().read(cx).path_for_entry(entry, cx), Some(file1.clone()) ); assert_eq!(pane.item_views().count(), 2); @@ -315,13 +321,11 @@ mod tests { .await .unwrap(); - workspace.read_with(&cx, |w, cx| { + workspace.read_with(&cx, |workspace, cx| { + let pane = workspace.active_pane().read(cx); + let entry = pane.active_item().unwrap().project_entry(cx).unwrap(); assert_eq!( - w.active_pane() - .read(cx) - .active_item() - .unwrap() - .project_path(cx.as_ref()), + workspace.project().read(cx).path_for_entry(entry, cx), Some(file2.clone()) ); }); @@ -336,14 +340,22 @@ mod tests { t1.await.unwrap(); t2.await.unwrap(); cx.read(|cx| { - let pane = workspace.read(cx).active_pane().read(cx); + let workspace = workspace.read(cx); + let pane = workspace.active_pane().read(cx); + let entry = pane.active_item().unwrap().project_entry(cx).unwrap(); assert_eq!( - pane.active_item().unwrap().project_path(cx), + workspace.project().read(cx).path_for_entry(entry, cx), Some(file3.clone()) ); let pane_entries = pane .item_views() - .map(|i| i.project_path(cx).unwrap()) + .map(|i| { + workspace + .project() + .read(cx) + .path_for_entry(i.project_entry(cx).unwrap(), cx) + .unwrap() + }) .collect::>(); assert_eq!(pane_entries, &[file1, file2, file3]); }); @@ -666,8 +678,15 @@ mod tests { .await .unwrap(); cx.read(|cx| { + let workspace = workspace.read(cx); + let pane1_entry = pane_1 + .read(cx) + .active_item() + .unwrap() + .project_entry(cx) + .unwrap(); assert_eq!( - pane_1.read(cx).active_item().unwrap().project_path(cx), + workspace.project().read(cx).path_for_entry(pane1_entry, cx), Some(file1.clone()) ); }); @@ -682,7 +701,15 @@ mod tests { assert_ne!(pane_1, pane_2); let pane2_item = pane_2.read(cx).active_item().unwrap(); - assert_eq!(pane2_item.project_path(cx.as_ref()), Some(file1.clone())); + let pane2_entry = pane2_item.project_entry(cx).unwrap(); + assert_eq!( + workspace + .read(cx) + .project() + .read(cx) + .path_for_entry(pane2_entry, cx), + Some(file1.clone()) + ); cx.dispatch_action(window_id, vec![pane_2.id()], &workspace::CloseActiveItem); let workspace = workspace.read(cx); @@ -862,7 +889,11 @@ mod tests { let item = workspace.active_item(cx).unwrap(); let editor = item.to_any().downcast::().unwrap(); let selections = editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)); - (item.project_path(cx).unwrap(), selections[0].start) + let path = workspace + .project() + .read(cx) + .path_for_entry(item.project_entry(cx).unwrap(), cx); + (path.unwrap(), selections[0].start) }) } }