diff --git a/Cargo.lock b/Cargo.lock index 881acc3f45..10893df3d0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5683,7 +5683,7 @@ checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9" [[package]] name = "zed" -version = "0.9.0" +version = "0.11.0" dependencies = [ "anyhow", "async-recursion", diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index aa917461c1..42230c6d1b 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -11,7 +11,7 @@ use gpui::{ }; use language::{Bias, Buffer, Diagnostic, DiagnosticEntry, Point}; use postage::watch; -use project::{Project, ProjectPath}; +use project::{Project, ProjectPath, WorktreeId}; use std::{cmp::Ordering, ops::Range, path::Path, sync::Arc}; use util::TryFutureExt; use workspace::Workspace; @@ -45,7 +45,7 @@ struct ProjectDiagnosticsEditor { editor: ViewHandle, excerpts: ModelHandle, path_states: Vec<(Arc, Vec)>, - paths_to_update: HashMap>, + paths_to_update: HashMap>, build_settings: BuildSettings, } diff --git a/crates/editor/src/items.rs b/crates/editor/src/items.rs index d88315fff7..29acf348a8 100644 --- a/crates/editor/src/items.rs +++ b/crates/editor/src/items.rs @@ -7,7 +7,7 @@ use gpui::{ }; use language::{Diagnostic, File as _}; use postage::watch; -use project::{ProjectPath, Worktree}; +use project::{File, ProjectPath, Worktree}; use std::fmt::Write; use std::path::Path; use text::{Point, Selection}; @@ -66,8 +66,8 @@ impl ItemHandle for BufferItemHandle { } fn project_path(&self, cx: &AppContext) -> Option { - self.0.read(cx).file(cx).map(|f| ProjectPath { - worktree_id: f.worktree_id(), + File::from_dyn(self.0.read(cx).file(cx)).map(|f| ProjectPath { + worktree_id: f.worktree_id(cx), path: f.path().clone(), }) } @@ -111,8 +111,8 @@ impl ItemView for Editor { } fn project_path(&self, cx: &AppContext) -> Option { - self.buffer().read(cx).file(cx).map(|file| ProjectPath { - worktree_id: file.worktree_id(), + File::from_dyn(self.buffer().read(cx).file(cx)).map(|file| ProjectPath { + worktree_id: file.worktree_id(cx), path: file.path().clone(), }) } diff --git a/crates/editor/src/multi_buffer.rs b/crates/editor/src/multi_buffer.rs index e96b8200f7..7e71855236 100644 --- a/crates/editor/src/multi_buffer.rs +++ b/crates/editor/src/multi_buffer.rs @@ -68,6 +68,7 @@ struct BufferState { buffer: ModelHandle, last_version: clock::Global, last_parse_count: usize, + last_selections_update_count: usize, last_diagnostics_update_count: usize, excerpts: Vec, _subscriptions: [gpui::Subscription; 2], @@ -637,6 +638,7 @@ impl MultiBuffer { .or_insert_with(|| BufferState { last_version: buffer_snapshot.version().clone(), last_parse_count: buffer_snapshot.parse_count(), + last_selections_update_count: buffer_snapshot.selections_update_count(), last_diagnostics_update_count: buffer_snapshot.diagnostics_update_count(), excerpts: Default::default(), _subscriptions: [ @@ -799,15 +801,23 @@ impl MultiBuffer { let buffer = buffer_state.buffer.read(cx); let version = buffer.version(); let parse_count = buffer.parse_count(); + let selections_update_count = buffer.selections_update_count(); let diagnostics_update_count = buffer.diagnostics_update_count(); let buffer_edited = version.gt(&buffer_state.last_version); let buffer_reparsed = parse_count > buffer_state.last_parse_count; + let buffer_selections_updated = + selections_update_count > buffer_state.last_selections_update_count; let buffer_diagnostics_updated = diagnostics_update_count > buffer_state.last_diagnostics_update_count; - if buffer_edited || buffer_reparsed || buffer_diagnostics_updated { + if buffer_edited + || buffer_reparsed + || buffer_selections_updated + || buffer_diagnostics_updated + { buffer_state.last_version = version; buffer_state.last_parse_count = parse_count; + buffer_state.last_selections_update_count = selections_update_count; buffer_state.last_diagnostics_update_count = diagnostics_update_count; excerpts_to_edit.extend( buffer_state diff --git a/crates/file_finder/src/file_finder.rs b/crates/file_finder/src/file_finder.rs index 87d02ea31f..c973551f8d 100644 --- a/crates/file_finder/src/file_finder.rs +++ b/crates/file_finder/src/file_finder.rs @@ -12,7 +12,7 @@ use gpui::{ ViewContext, ViewHandle, WeakViewHandle, }; use postage::watch; -use project::{Project, ProjectPath}; +use project::{Project, ProjectPath, WorktreeId}; use std::{ cmp, path::Path, @@ -195,7 +195,7 @@ impl FileFinder { .with_style(style.container); let action = Select(ProjectPath { - worktree_id: path_match.worktree_id, + worktree_id: WorktreeId::from_usize(path_match.worktree_id), path: path_match.path.clone(), }); EventHandler::new(container.boxed()) @@ -370,7 +370,7 @@ impl FileFinder { fn confirm(&mut self, _: &Confirm, cx: &mut ViewContext) { if let Some(m) = self.matches.get(self.selected_index()) { cx.emit(Event::Selected(ProjectPath { - worktree_id: m.worktree_id, + worktree_id: WorktreeId::from_usize(m.worktree_id), path: m.path.clone(), })); } diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index a23631a577..aedbd9381a 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -67,6 +67,7 @@ pub struct Buffer { parse_count: usize, remote_selections: TreeMap]>>, diagnostics: DiagnosticSet, + selections_update_count: usize, diagnostics_update_count: usize, language_server: Option, deferred_ops: OperationQueue, @@ -80,6 +81,7 @@ pub struct BufferSnapshot { diagnostics: DiagnosticSet, remote_selections: TreeMap]>>, diagnostics_update_count: usize, + selections_update_count: usize, is_parsing: bool, language: Option>, parse_count: usize, @@ -148,10 +150,6 @@ pub enum Event { } pub trait File { - fn worktree_id(&self) -> usize; - - fn entry_id(&self) -> Option; - fn mtime(&self) -> SystemTime; /// Returns the path of this file relative to the worktree's root directory. @@ -184,8 +182,6 @@ pub trait File { fn buffer_removed(&self, buffer_id: u64, cx: &mut MutableAppContext); - fn boxed_clone(&self) -> Box; - fn as_any(&self) -> &dyn Any; } @@ -366,6 +362,7 @@ impl Buffer { pending_autoindent: Default::default(), language: None, remote_selections: Default::default(), + selections_update_count: 0, diagnostics: Default::default(), diagnostics_update_count: 0, language_server: None, @@ -385,6 +382,7 @@ impl Buffer { is_parsing: self.parsing_in_background, language: self.language.clone(), parse_count: self.parse_count, + selections_update_count: self.selections_update_count, } } @@ -610,6 +608,10 @@ impl Buffer { self.parse_count } + pub fn selections_update_count(&self) -> usize { + self.selections_update_count + } + pub fn diagnostics_update_count(&self) -> usize { self.diagnostics_update_count } @@ -1079,8 +1081,6 @@ impl Buffer { cx: &mut ModelContext, ) { let lamport_timestamp = self.text.lamport_clock.tick(); - self.remote_selections - .insert(self.text.replica_id(), selections.clone()); self.send_operation( Operation::UpdateSelections { replica_id: self.text.replica_id(), @@ -1348,6 +1348,7 @@ impl Buffer { } => { self.remote_selections.insert(replica_id, selections); self.text.lamport_clock.observe(lamport_timestamp); + self.selections_update_count += 1; } Operation::RemoveSelections { replica_id, @@ -1355,6 +1356,7 @@ impl Buffer { } => { self.remote_selections.remove(&replica_id); self.text.lamport_clock.observe(lamport_timestamp); + self.selections_update_count += 1; } } } @@ -1760,6 +1762,10 @@ impl BufferSnapshot { pub fn parse_count(&self) -> usize { self.parse_count } + + pub fn selections_update_count(&self) -> usize { + self.selections_update_count + } } impl Clone for BufferSnapshot { @@ -1769,6 +1775,7 @@ impl Clone for BufferSnapshot { tree: self.tree.clone(), remote_selections: self.remote_selections.clone(), diagnostics: self.diagnostics.clone(), + selections_update_count: self.selections_update_count, diagnostics_update_count: self.diagnostics_update_count, is_parsing: self.is_parsing, language: self.language.clone(), diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index acabca0033..c05e0c8f4a 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -59,14 +59,14 @@ pub struct Collaborator { #[derive(Debug)] pub enum Event { ActiveEntryChanged(Option), - WorktreeRemoved(usize), - DiskBasedDiagnosticsUpdated { worktree_id: usize }, + WorktreeRemoved(WorktreeId), + DiskBasedDiagnosticsUpdated { worktree_id: WorktreeId }, DiagnosticsUpdated(ProjectPath), } #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct ProjectPath { - pub worktree_id: usize, + pub worktree_id: WorktreeId, pub path: Arc, } @@ -105,7 +105,7 @@ impl DiagnosticSummary { #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub struct ProjectEntry { - pub worktree_id: usize, + pub worktree_id: WorktreeId, pub entry_id: usize, } @@ -321,7 +321,11 @@ impl Project { &self.worktrees } - pub fn worktree_for_id(&self, id: usize, cx: &AppContext) -> Option> { + pub fn worktree_for_id( + &self, + id: WorktreeId, + cx: &AppContext, + ) -> Option> { self.worktrees .iter() .find(|worktree| worktree.read(cx).id() == id) @@ -479,13 +483,13 @@ impl Project { cx.subscribe(&worktree, |_, worktree, event, cx| match event { worktree::Event::DiagnosticsUpdated(path) => { cx.emit(Event::DiagnosticsUpdated(ProjectPath { - worktree_id: worktree.id(), + worktree_id: worktree.read(cx).id(), path: path.clone(), })); } worktree::Event::DiskBasedDiagnosticsUpdated => { cx.emit(Event::DiskBasedDiagnosticsUpdated { - worktree_id: worktree.id(), + worktree_id: worktree.read(cx).id(), }); } }) @@ -514,9 +518,9 @@ impl Project { cx: &'a AppContext, ) -> impl Iterator + 'a { self.worktrees.iter().flat_map(move |worktree| { + let worktree = worktree.read(cx); let worktree_id = worktree.id(); worktree - .read(cx) .diagnostic_summaries() .map(move |(path, summary)| (ProjectPath { worktree_id, path }, summary)) }) @@ -634,9 +638,9 @@ impl Project { _: Arc, cx: &mut ModelContext, ) -> Result<()> { - self.worktrees.retain(|worktree| { - worktree.read(cx).as_remote().unwrap().remote_id() != envelope.payload.worktree_id - }); + let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id); + self.worktrees + .retain(|worktree| worktree.read(cx).as_remote().unwrap().id() != worktree_id); cx.notify(); Ok(()) } @@ -647,7 +651,8 @@ impl Project { _: Arc, cx: &mut ModelContext, ) -> Result<()> { - if let Some(worktree) = self.worktree_for_id(envelope.payload.worktree_id as usize, cx) { + let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id); + if let Some(worktree) = self.worktree_for_id(worktree_id, cx) { worktree.update(cx, |worktree, cx| { let worktree = worktree.as_remote_mut().unwrap(); worktree.update_from_remote(envelope, cx) @@ -662,7 +667,8 @@ impl Project { _: Arc, cx: &mut ModelContext, ) -> Result<()> { - if let Some(worktree) = self.worktree_for_id(envelope.payload.worktree_id as usize, cx) { + let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id); + if let Some(worktree) = self.worktree_for_id(worktree_id, cx) { worktree.update(cx, |worktree, cx| { worktree.handle_update_buffer(envelope, cx) })?; @@ -676,7 +682,8 @@ impl Project { rpc: Arc, cx: &mut ModelContext, ) -> Result<()> { - if let Some(worktree) = self.worktree_for_id(envelope.payload.worktree_id as usize, cx) { + let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id); + if let Some(worktree) = self.worktree_for_id(worktree_id, cx) { worktree.update(cx, |worktree, cx| { worktree.handle_save_buffer(envelope, rpc, cx) })?; @@ -690,7 +697,8 @@ impl Project { rpc: Arc, cx: &mut ModelContext, ) -> anyhow::Result<()> { - if let Some(worktree) = self.worktree_for_id(envelope.payload.worktree_id as usize, cx) { + let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id); + if let Some(worktree) = self.worktree_for_id(worktree_id, cx) { return worktree.update(cx, |worktree, cx| { worktree.handle_open_buffer(envelope, rpc, cx) }); @@ -705,7 +713,8 @@ impl Project { rpc: Arc, cx: &mut ModelContext, ) -> anyhow::Result<()> { - if let Some(worktree) = self.worktree_for_id(envelope.payload.worktree_id as usize, cx) { + let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id); + if let Some(worktree) = self.worktree_for_id(worktree_id, cx) { worktree.update(cx, |worktree, cx| { worktree.handle_close_buffer(envelope, rpc, cx) })?; @@ -719,7 +728,8 @@ impl Project { _: Arc, cx: &mut ModelContext, ) -> Result<()> { - if let Some(worktree) = self.worktree_for_id(envelope.payload.worktree_id as usize, cx) { + let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id); + if let Some(worktree) = self.worktree_for_id(worktree_id, cx) { worktree.update(cx, |worktree, cx| { worktree.handle_buffer_saved(envelope, cx) })?; @@ -772,7 +782,7 @@ impl<'a> PathMatchCandidateSet<'a> for CandidateSet { type Candidates = CandidateSetIter<'a>; fn id(&self) -> usize { - self.snapshot.id() + self.snapshot.id().to_usize() } fn len(&self) -> usize { diff --git a/crates/project/src/worktree.rs b/crates/project/src/worktree.rs index c74a2dc62f..030e55deae 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project/src/worktree.rs @@ -59,6 +59,9 @@ enum ScanState { Err(Arc), } +#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] +pub struct WorktreeId(usize); + pub enum Worktree { Local(LocalWorktree), Remote(RemoteWorktree), @@ -170,7 +173,7 @@ impl Worktree { let worktree = cx.update(|cx| { cx.add_model(|cx: &mut ModelContext| { let snapshot = Snapshot { - id: remote_id as usize, + id: WorktreeId(remote_id as usize), scan_id: 0, abs_path: Path::new("").into(), root_name, @@ -213,7 +216,6 @@ impl Worktree { Worktree::Remote(RemoteWorktree { project_id: project_remote_id, - remote_id, replica_id, snapshot, snapshot_rx, @@ -618,9 +620,9 @@ impl Worktree { for (buffer_id, buffer) in open_buffers { if let Some(buffer) = buffer.upgrade(cx) { buffer.update(cx, |buffer, cx| { - if let Some(old_file) = buffer.file() { + if let Some(old_file) = File::from_dyn(buffer.file()) { let new_file = if let Some(entry) = old_file - .entry_id() + .entry_id .and_then(|entry_id| self.entry_for_id(entry_id)) { File { @@ -789,16 +791,13 @@ impl Worktree { cx: &mut ModelContext, ) { if let Some((project_id, worktree_id, rpc)) = match self { - Worktree::Local(worktree) => worktree.share.as_ref().map(|share| { - ( - share.project_id, - worktree.id() as u64, - worktree.client.clone(), - ) - }), + Worktree::Local(worktree) => worktree + .share + .as_ref() + .map(|share| (share.project_id, worktree.id(), worktree.client.clone())), Worktree::Remote(worktree) => Some(( worktree.project_id, - worktree.remote_id, + worktree.snapshot.id(), worktree.client.clone(), )), } { @@ -806,7 +805,7 @@ impl Worktree { if let Err(error) = rpc .request(proto::UpdateBuffer { project_id, - worktree_id, + worktree_id: worktree_id.0 as u64, buffer_id, operations: vec![language::proto::serialize_operation(&operation)], }) @@ -827,9 +826,33 @@ impl Worktree { } } +impl WorktreeId { + pub fn from_usize(handle_id: usize) -> Self { + Self(handle_id) + } + + pub(crate) fn from_proto(id: u64) -> Self { + Self(id as usize) + } + + pub fn to_proto(&self) -> u64 { + self.0 as u64 + } + + pub fn to_usize(&self) -> usize { + self.0 + } +} + +impl fmt::Display for WorktreeId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + #[derive(Clone)] pub struct Snapshot { - id: usize, + id: WorktreeId, scan_id: usize, abs_path: Arc, root_name: String, @@ -870,7 +893,6 @@ struct ShareState { pub struct RemoteWorktree { project_id: u64, - remote_id: u64, snapshot: Snapshot, snapshot_rx: watch::Receiver, client: Arc, @@ -926,7 +948,7 @@ impl LocalWorktree { let (mut last_scan_state_tx, last_scan_state_rx) = watch::channel_with(ScanState::Scanning); let tree = cx.add_model(move |cx: &mut ModelContext| { let mut snapshot = Snapshot { - id: cx.model_id(), + id: WorktreeId::from_usize(cx.model_id()), scan_id: 0, abs_path, root_name: root_name.clone(), @@ -1114,12 +1136,12 @@ impl LocalWorktree { path: &Path, cx: &mut ModelContext, ) -> Option> { - let worktree_id = self.id(); + let handle = cx.handle(); let mut result = None; self.open_buffers.retain(|_buffer_id, buffer| { - if let Some(buffer) = buffer.upgrade(cx.as_ref()) { - if let Some(file) = buffer.read(cx.as_ref()).file() { - if file.worktree_id() == worktree_id && file.path().as_ref() == path { + if let Some(buffer) = buffer.upgrade(cx) { + if let Some(file) = File::from_dyn(buffer.read(cx).file()) { + if file.worktree == handle && file.path().as_ref() == path { result = Some(buffer); } } @@ -1422,6 +1444,14 @@ impl Deref for LocalWorktree { } } +impl Deref for RemoteWorktree { + type Target = Snapshot; + + fn deref(&self) -> &Self::Target { + &self.snapshot + } +} + impl fmt::Debug for LocalWorktree { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.snapshot.fmt(f) @@ -1429,10 +1459,6 @@ impl fmt::Debug for LocalWorktree { } impl RemoteWorktree { - pub fn remote_id(&self) -> u64 { - self.remote_id - } - fn get_open_buffer( &mut self, path: &Path, @@ -1442,8 +1468,8 @@ impl RemoteWorktree { let mut existing_buffer = None; self.open_buffers.retain(|_buffer_id, buffer| { if let Some(buffer) = buffer.upgrade(cx.as_ref()) { - if let Some(file) = buffer.read(cx.as_ref()).file() { - if file.worktree_id() == handle.id() && file.path().as_ref() == path { + if let Some(file) = File::from_dyn(buffer.read(cx).file()) { + if file.worktree == handle && file.path().as_ref() == path { existing_buffer = Some(buffer); } } @@ -1463,7 +1489,7 @@ impl RemoteWorktree { let rpc = self.client.clone(); let replica_id = self.replica_id; let project_id = self.project_id; - let remote_worktree_id = self.remote_id; + let remote_worktree_id = self.id(); let root_path = self.snapshot.abs_path.clone(); let path: Arc = Arc::from(path); let path_string = path.to_string_lossy().to_string(); @@ -1476,7 +1502,7 @@ impl RemoteWorktree { let response = rpc .request(proto::OpenBuffer { project_id, - worktree_id: remote_worktree_id as u64, + worktree_id: remote_worktree_id.to_proto(), path: path_string, }) .await?; @@ -1571,14 +1597,14 @@ impl RemoteBuffer { } impl Snapshot { - pub fn id(&self) -> usize { + pub fn id(&self) -> WorktreeId { self.id } pub fn to_proto(&self) -> proto::Worktree { let root_name = self.root_name.clone(); proto::Worktree { - id: self.id as u64, + id: self.id.0 as u64, root_name, entries: self .entries_by_path @@ -1954,14 +1980,6 @@ pub struct File { } impl language::File for File { - fn worktree_id(&self) -> usize { - self.worktree.id() - } - - fn entry_id(&self) -> Option { - self.entry_id - } - fn mtime(&self) -> SystemTime { self.mtime } @@ -2007,7 +2025,7 @@ impl language::File for File { version: clock::Global, cx: &mut MutableAppContext, ) -> Task> { - let worktree_id = self.worktree.read(cx).id() as u64; + let worktree_id = self.worktree.read(cx).id().to_proto(); self.worktree.update(cx, |worktree, cx| match worktree { Worktree::Local(worktree) => { let rpc = worktree.client.clone(); @@ -2070,7 +2088,7 @@ impl language::File for File { self.worktree.update(cx, |worktree, cx| { if let Worktree::Remote(worktree) = worktree { let project_id = worktree.project_id; - let worktree_id = worktree.remote_id; + let worktree_id = worktree.id().to_proto(); let rpc = worktree.client.clone(); cx.background() .spawn(async move { @@ -2090,15 +2108,21 @@ impl language::File for File { }); } - fn boxed_clone(&self) -> Box { - Box::new(self.clone()) - } - fn as_any(&self) -> &dyn Any { self } } +impl File { + pub fn from_dyn(file: Option<&dyn language::File>) -> Option<&Self> { + file.and_then(|f| f.as_any().downcast_ref()) + } + + pub fn worktree_id(&self, cx: &AppContext) -> WorktreeId { + self.worktree.read(cx).id() + } +} + #[derive(Clone, Debug)] pub struct Entry { pub id: usize, @@ -4031,7 +4055,7 @@ mod tests { let fs = Arc::new(RealFs); let next_entry_id = Arc::new(AtomicUsize::new(0)); let mut initial_snapshot = Snapshot { - id: 0, + id: WorktreeId::from_usize(0), scan_id: 0, abs_path: root_dir.path().into(), entries_by_path: Default::default(), diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index 041806034a..9ced3fbeb0 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -14,7 +14,7 @@ use gpui::{ ViewContext, ViewHandle, WeakViewHandle, }; use postage::watch; -use project::{Project, ProjectEntry, ProjectPath, Worktree}; +use project::{Project, ProjectEntry, ProjectPath, Worktree, WorktreeId}; use std::{ collections::{hash_map, HashMap}, ffi::OsStr, @@ -26,7 +26,7 @@ pub struct ProjectPanel { project: ModelHandle, list: UniformListState, visible_entries: Vec>, - expanded_dir_ids: HashMap>, + expanded_dir_ids: HashMap>, selection: Option, settings: watch::Receiver, handle: WeakViewHandle, @@ -34,7 +34,7 @@ pub struct ProjectPanel { #[derive(Copy, Clone)] struct Selection { - worktree_id: usize, + worktree_id: WorktreeId, entry_id: usize, index: usize, } @@ -67,7 +67,10 @@ pub fn init(cx: &mut MutableAppContext) { } pub enum Event { - OpenedEntry { worktree_id: usize, entry_id: usize }, + OpenedEntry { + worktree_id: WorktreeId, + entry_id: usize, + }, } impl ProjectPanel { @@ -114,16 +117,16 @@ impl ProjectPanel { this }); cx.subscribe(&project_panel, move |workspace, _, event, cx| match event { - Event::OpenedEntry { + &Event::OpenedEntry { worktree_id, entry_id, } => { - if let Some(worktree) = project.read(cx).worktree_for_id(*worktree_id, cx) { - if let Some(entry) = worktree.read(cx).entry_for_id(*entry_id) { + if let Some(worktree) = project.read(cx).worktree_for_id(worktree_id, cx) { + if let Some(entry) = worktree.read(cx).entry_for_id(entry_id) { workspace .open_entry( ProjectPath { - worktree_id: worktree.id(), + worktree_id, path: entry.path.clone(), }, cx, @@ -259,8 +262,8 @@ impl ProjectPanel { fn select_first(&mut self, cx: &mut ViewContext) { if let Some(worktree) = self.project.read(cx).worktrees().first() { - let worktree_id = worktree.id(); let worktree = worktree.read(cx); + let worktree_id = worktree.id(); if let Some(root_entry) = worktree.root_entry() { self.selection = Some(Selection { worktree_id, @@ -313,7 +316,7 @@ impl ProjectPanel { fn update_visible_entries( &mut self, - new_selected_entry: Option<(usize, usize)>, + new_selected_entry: Option<(WorktreeId, usize)>, cx: &mut ViewContext, ) { let worktrees = self.project.read(cx).worktrees(); @@ -322,7 +325,7 @@ impl ProjectPanel { let mut entry_ix = 0; for worktree in worktrees { let snapshot = worktree.read(cx).snapshot(); - let worktree_id = worktree.id(); + let worktree_id = snapshot.id(); let expanded_dir_ids = match self.expanded_dir_ids.entry(worktree_id) { hash_map::Entry::Occupied(e) => e.into_mut(), @@ -342,7 +345,7 @@ impl ProjectPanel { while let Some(item) = entry_iter.entry() { visible_worktree_entries.push(entry_iter.offset()); if let Some(new_selected_entry) = new_selected_entry { - if new_selected_entry == (worktree.id(), item.id) { + if new_selected_entry == (worktree_id, item.id) { self.selection = Some(Selection { worktree_id, entry_id: item.id, @@ -371,7 +374,12 @@ impl ProjectPanel { } } - fn expand_entry(&mut self, worktree_id: usize, entry_id: usize, cx: &mut ViewContext) { + fn expand_entry( + &mut self, + worktree_id: WorktreeId, + entry_id: usize, + cx: &mut ViewContext, + ) { let project = self.project.read(cx); if let Some((worktree, expanded_dir_ids)) = project .worktree_for_id(worktree_id, cx) @@ -417,12 +425,12 @@ impl ProjectPanel { let end_ix = range.end.min(ix + visible_worktree_entries.len()); let worktree = &worktrees[worktree_ix]; + let snapshot = worktree.read(cx).snapshot(); let expanded_entry_ids = self .expanded_dir_ids - .get(&worktree.id()) + .get(&snapshot.id()) .map(Vec::as_slice) .unwrap_or(&[]); - let snapshot = worktree.read(cx).snapshot(); let root_name = OsStr::new(snapshot.root_name()); let mut cursor = snapshot.entries(false); @@ -439,11 +447,11 @@ impl ProjectPanel { is_dir: entry.is_dir(), is_expanded: expanded_entry_ids.binary_search(&entry.id).is_ok(), is_selected: self.selection.map_or(false, |e| { - e.worktree_id == worktree.id() && e.entry_id == entry.id + e.worktree_id == snapshot.id() && e.entry_id == entry.id }), }; let entry = ProjectEntry { - worktree_id: worktree.id(), + worktree_id: snapshot.id(), entry_id: entry.id, }; callback(entry, details, cx); @@ -461,7 +469,7 @@ impl ProjectPanel { ) -> ElementBox { let is_dir = details.is_dir; MouseEventHandler::new::( - (entry.worktree_id, entry.entry_id), + (entry.worktree_id.to_usize(), entry.entry_id), cx, |state, _| { let style = match (details.is_selected, state.hovered) { @@ -516,7 +524,7 @@ impl ProjectPanel { if is_dir { cx.dispatch_action(ToggleExpanded(entry)) } else { - cx.dispatch_action(Open(entry)) + cx.dispatch_action(Open(dbg!(entry))) } }) .with_cursor_style(CursorStyle::PointingHand) diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index b45d292cf2..69a7004c44 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -619,10 +619,10 @@ impl Workspace { cx: &mut ViewContext, ) -> Task> { let entry = self.worktree_for_abs_path(abs_path, cx); - cx.spawn(|_, _| async move { + cx.spawn(|_, cx| async move { let (worktree, path) = entry.await?; Ok(ProjectPath { - worktree_id: worktree.id(), + worktree_id: worktree.read_with(&cx, |t, _| t.id()), path: path.into(), }) }) @@ -1252,7 +1252,7 @@ impl WorkspaceHandle for ViewHandle { .worktrees(cx) .iter() .flat_map(|worktree| { - let worktree_id = worktree.id(); + let worktree_id = worktree.read(cx).id(); worktree.read(cx).files(true, 0).map(move |f| ProjectPath { worktree_id, path: f.path.clone(), diff --git a/crates/zed/Cargo.toml b/crates/zed/Cargo.toml index b520eee0b6..11f77774eb 100644 --- a/crates/zed/Cargo.toml +++ b/crates/zed/Cargo.toml @@ -3,7 +3,7 @@ authors = ["Nathan Sobo "] description = "The fast, collaborative code editor." edition = "2018" name = "zed" -version = "0.9.0" +version = "0.11.0" [lib] name = "zed" diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 04a6fc8495..1483982b60 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -556,7 +556,7 @@ mod tests { workspace .open_entry( ProjectPath { - worktree_id: worktree.id(), + worktree_id: worktree.read(cx).id(), path: Path::new("the-new-name.rs").into(), }, cx,