Remove worktree_path from File struct

Nathan Sobo created

Change summary

crates/editor/src/items.rs     |  2 
crates/language/src/buffer.rs  | 18 ++++++++--------
crates/project/src/project.rs  | 10 ++------
crates/project/src/worktree.rs | 38 ++++++++++++++---------------------
crates/rpc/proto/zed.proto     |  7 ++++++
5 files changed, 35 insertions(+), 40 deletions(-)

Detailed changes

crates/editor/src/items.rs 🔗

@@ -126,7 +126,7 @@ impl ItemView for Editor {
             .buffer()
             .read(cx)
             .file(cx)
-            .and_then(|file| file.file_name());
+            .and_then(|file| file.file_name(cx));
         if let Some(name) = filename {
             name.to_string_lossy().into()
         } else {

crates/language/src/buffer.rs 🔗

@@ -162,15 +162,15 @@ pub trait File {
     fn path(&self) -> &Arc<Path>;
 
     /// Returns the absolute path of this file.
-    fn abs_path(&self) -> Option<PathBuf>;
+    fn abs_path(&self, cx: &AppContext) -> Option<PathBuf>;
 
     /// Returns the path of this file relative to the worktree's parent directory (this means it
     /// includes the name of the worktree's root folder).
-    fn full_path(&self) -> PathBuf;
+    fn full_path(&self, cx: &AppContext) -> PathBuf;
 
     /// Returns the last component of this handle's absolute path. If this handle refers to the root
     /// of its worktree, then this method will return the name of the worktree itself.
-    fn file_name(&self) -> Option<OsString>;
+    fn file_name(&self, cx: &AppContext) -> Option<OsString>;
 
     fn is_deleted(&self) -> bool;
 
@@ -457,7 +457,7 @@ impl Buffer {
 
         if let Some(LanguageServerState { server, .. }) = self.language_server.as_ref() {
             let server = server.clone();
-            let abs_path = file.abs_path().unwrap();
+            let abs_path = file.abs_path(cx).unwrap();
             let version = self.version();
             cx.spawn(|this, mut cx| async move {
                 let edits = server
@@ -619,7 +619,7 @@ impl Buffer {
             None
         };
 
-        self.update_language_server();
+        self.update_language_server(cx);
     }
 
     pub fn did_save(
@@ -643,7 +643,7 @@ impl Buffer {
                             lsp::DidSaveTextDocumentParams {
                                 text_document: lsp::TextDocumentIdentifier {
                                     uri: lsp::Url::from_file_path(
-                                        self.file.as_ref().unwrap().abs_path().unwrap(),
+                                        self.file.as_ref().unwrap().abs_path(cx).unwrap(),
                                     )
                                     .unwrap(),
                                 },
@@ -1226,7 +1226,7 @@ impl Buffer {
         self.set_active_selections(Arc::from([]), cx);
     }
 
-    fn update_language_server(&mut self) {
+    fn update_language_server(&mut self, cx: &AppContext) {
         let language_server = if let Some(language_server) = self.language_server.as_mut() {
             language_server
         } else {
@@ -1236,7 +1236,7 @@ impl Buffer {
             .file
             .as_ref()
             .map_or(Path::new("/").to_path_buf(), |file| {
-                file.abs_path().unwrap()
+                file.abs_path(cx).unwrap()
             });
 
         let version = post_inc(&mut language_server.next_version);
@@ -1381,7 +1381,7 @@ impl Buffer {
         }
 
         self.reparse(cx);
-        self.update_language_server();
+        self.update_language_server(cx);
 
         cx.emit(Event::Edited);
         if !was_dirty {

crates/project/src/project.rs 🔗

@@ -624,7 +624,7 @@ impl Project {
     ) -> Option<()> {
         let (path, full_path) = {
             let file = buffer.read(cx).file()?;
-            (file.path().clone(), file.full_path())
+            (file.path().clone(), file.full_path(cx))
         };
 
         // If the buffer has a language, set it and start/assign the language server
@@ -938,7 +938,7 @@ impl Project {
         let buffer_abs_path;
         if let Some(file) = File::from_dyn(buffer.file()) {
             worktree = file.worktree.clone();
-            buffer_abs_path = file.abs_path();
+            buffer_abs_path = file.abs_path(cx);
         } else {
             return Task::ready(Err(anyhow!("buffer does not belong to any worktree")));
         };
@@ -1168,7 +1168,6 @@ impl Project {
     ) {
         let local = worktree_handle.read(cx).is_local();
         let snapshot = worktree_handle.read(cx).snapshot();
-        let worktree_path = snapshot.abs_path();
         let mut buffers_to_delete = Vec::new();
         for (buffer_id, buffer) in &self.open_buffers {
             if let OpenBuffer::Loaded(buffer) = buffer {
@@ -1185,7 +1184,6 @@ impl Project {
                             {
                                 File {
                                     is_local: local,
-                                    worktree_path: worktree_path.clone(),
                                     entry_id: Some(entry.id),
                                     mtime: entry.mtime,
                                     path: entry.path.clone(),
@@ -1196,7 +1194,6 @@ impl Project {
                             {
                                 File {
                                     is_local: local,
-                                    worktree_path: worktree_path.clone(),
                                     entry_id: Some(entry.id),
                                     mtime: entry.mtime,
                                     path: entry.path.clone(),
@@ -1205,7 +1202,6 @@ impl Project {
                             } else {
                                 File {
                                     is_local: local,
-                                    worktree_path: worktree_path.clone(),
                                     entry_id: None,
                                     path: old_file.path().clone(),
                                     mtime: old_file.mtime(),
@@ -2185,7 +2181,7 @@ mod tests {
         cx.update(|cx| {
             let target_buffer = definition.target_buffer.read(cx);
             assert_eq!(
-                target_buffer.file().unwrap().abs_path(),
+                target_buffer.file().unwrap().abs_path(cx),
                 Some(dir.path().join("a.rs"))
             );
             assert_eq!(definition.target_range.to_offset(target_buffer), 9..10);

crates/project/src/worktree.rs 🔗

@@ -631,7 +631,6 @@ impl LocalWorktree {
     fn load(&self, path: &Path, cx: &mut ModelContext<Worktree>) -> Task<Result<(File, String)>> {
         let handle = cx.handle();
         let path = Arc::from(path);
-        let worktree_path = self.abs_path.clone();
         let abs_path = self.absolutize(&path);
         let background_snapshot = self.background_snapshot.clone();
         let fs = self.fs.clone();
@@ -644,7 +643,6 @@ impl LocalWorktree {
                 File {
                     entry_id: Some(entry.id),
                     worktree: handle,
-                    worktree_path,
                     path: entry.path,
                     mtime: entry.mtime,
                     is_local: true,
@@ -664,19 +662,16 @@ impl LocalWorktree {
         let text = buffer.as_rope().clone();
         let version = buffer.version();
         let save = self.save(path, text, cx);
-        cx.spawn(|this, mut cx| async move {
+        let handle = cx.handle();
+        cx.as_mut().spawn(|mut cx| async move {
             let entry = save.await?;
-            let file = this.update(&mut cx, |this, cx| {
-                let this = this.as_local_mut().unwrap();
-                File {
-                    entry_id: Some(entry.id),
-                    worktree: cx.handle(),
-                    worktree_path: this.abs_path.clone(),
-                    path: entry.path,
-                    mtime: entry.mtime,
-                    is_local: true,
-                }
-            });
+            let file = File {
+                entry_id: Some(entry.id),
+                worktree: handle,
+                path: entry.path,
+                mtime: entry.mtime,
+                is_local: true,
+            };
 
             buffer_handle.update(&mut cx, |buffer, cx| {
                 buffer.did_save(version, file.mtime, Some(Box::new(file)), cx);
@@ -811,7 +806,6 @@ impl RemoteWorktree {
         let replica_id = self.replica_id;
         let project_id = self.project_id;
         let remote_worktree_id = self.id();
-        let root_path = self.snapshot.abs_path.clone();
         let path: Arc<Path> = Arc::from(path);
         let path_string = path.to_string_lossy().to_string();
         cx.spawn_weak(move |this, mut cx| async move {
@@ -834,7 +828,6 @@ impl RemoteWorktree {
             let file = File {
                 entry_id: Some(entry.id),
                 worktree: this.clone(),
-                worktree_path: root_path,
                 path: entry.path,
                 mtime: entry.mtime,
                 is_local: false,
@@ -1354,7 +1347,6 @@ pub struct File {
     pub path: Arc<Path>,
     pub mtime: SystemTime,
     pub(crate) entry_id: Option<usize>,
-    pub(crate) worktree_path: Arc<Path>,
     pub(crate) is_local: bool,
 }
 
@@ -1367,17 +1359,17 @@ impl language::File for File {
         &self.path
     }
 
-    fn abs_path(&self) -> Option<PathBuf> {
+    fn abs_path(&self, cx: &AppContext) -> Option<PathBuf> {
         if self.is_local {
-            Some(self.worktree_path.join(&self.path))
+            Some(self.worktree.read(cx).abs_path().join(&self.path))
         } else {
             None
         }
     }
 
-    fn full_path(&self) -> PathBuf {
+    fn full_path(&self, cx: &AppContext) -> PathBuf {
         let mut full_path = PathBuf::new();
-        if let Some(worktree_name) = self.worktree_path.file_name() {
+        if let Some(worktree_name) = self.worktree.read(cx).abs_path().file_name() {
             full_path.push(worktree_name);
         }
         full_path.push(&self.path);
@@ -1386,10 +1378,10 @@ impl language::File for File {
 
     /// Returns the last component of this handle's absolute path. If this handle refers to the root
     /// of its worktree, then this method will return the name of the worktree itself.
-    fn file_name<'a>(&'a self) -> Option<OsString> {
+    fn file_name<'a>(&'a self, cx: &AppContext) -> Option<OsString> {
         self.path
             .file_name()
-            .or_else(|| self.worktree_path.file_name())
+            .or_else(|| self.worktree.read(cx).abs_path().file_name())
             .map(Into::into)
     }
 

crates/rpc/proto/zed.proto 🔗

@@ -270,6 +270,13 @@ message Worktree {
     bool weak = 5;
 }
 
+message File {
+    uint64 worktree_id = 1;
+    uint64 entry_id = 2;
+    string path = 3;
+    Timestamp mtime = 4;
+}
+
 message Entry {
     uint64 id = 1;
     bool is_dir = 2;