diff --git a/crates/collab/src/integration_tests.rs b/crates/collab/src/integration_tests.rs index a4c8386b13..7767b361c1 100644 --- a/crates/collab/src/integration_tests.rs +++ b/crates/collab/src/integration_tests.rs @@ -35,7 +35,7 @@ use project::{ use rand::prelude::*; use rpc::PeerId; use serde_json::json; -use settings::Settings; +use settings::{FormatOnSave, Settings}; use sqlx::types::time::OffsetDateTime; use std::{ cell::RefCell, @@ -1912,7 +1912,6 @@ async fn test_reloading_buffer_manually(cx_a: &mut TestAppContext, cx_b: &mut Te #[gpui::test(iterations = 10)] async fn test_formatting_buffer(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) { - cx_a.foreground().forbid_parking(); let mut server = TestServer::start(cx_a.foreground(), cx_a.background()).await; let client_a = server.create_client(cx_a, "user_a").await; let client_b = server.create_client(cx_b, "user_b").await; @@ -1932,11 +1931,15 @@ async fn test_formatting_buffer(cx_a: &mut TestAppContext, cx_b: &mut TestAppCon let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default()); client_a.language_registry.add(Arc::new(language)); + // Here we insert a fake tree with a directory that exists on disk. This is needed + // because later we'll invoke a command, which requires passing a working directory + // that points to a valid location on disk. + let directory = env::current_dir().unwrap(); client_a .fs - .insert_tree("/a", json!({ "a.rs": "let one = two" })) + .insert_tree(&directory, json!({ "a.rs": "let one = \"two\"" })) .await; - let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await; + let (project_a, worktree_id) = client_a.build_local_project(&directory, cx_a).await; let project_b = client_b.build_remote_project(&project_a, cx_a, cx_b).await; let buffer_b = cx_b @@ -1967,7 +1970,28 @@ async fn test_formatting_buffer(cx_a: &mut TestAppContext, cx_b: &mut TestAppCon .unwrap(); assert_eq!( buffer_b.read_with(cx_b, |buffer, _| buffer.text()), - "let honey = two" + "let honey = \"two\"" + ); + + // Ensure buffer can be formatted using an external command. Notice how the + // host's configuration is honored as opposed to using the guest's settings. + cx_a.update(|cx| { + cx.update_global(|settings: &mut Settings, _| { + settings.language_settings.format_on_save = Some(FormatOnSave::External { + command: "awk".to_string(), + arguments: vec!["{sub(/two/,\"{buffer_path}\")}1".to_string()], + }); + }); + }); + project_b + .update(cx_b, |project, cx| { + project.format(HashSet::from_iter([buffer_b.clone()]), true, cx) + }) + .await + .unwrap(); + assert_eq!( + buffer_b.read_with(cx_b, |buffer, _| buffer.text()), + format!("let honey = \"{}/a.rs\"\n", directory.to_str().unwrap()) ); } diff --git a/crates/project/src/fs.rs b/crates/project/src/fs.rs index 17d7264f1d..5c52801611 100644 --- a/crates/project/src/fs.rs +++ b/crates/project/src/fs.rs @@ -334,28 +334,6 @@ impl FakeFs { }) } - pub async fn insert_dir(&self, path: impl AsRef) { - let mut state = self.state.lock().await; - let path = path.as_ref(); - state.validate_path(path).unwrap(); - - let inode = state.next_inode; - state.next_inode += 1; - state.entries.insert( - path.to_path_buf(), - FakeFsEntry { - metadata: Metadata { - inode, - mtime: SystemTime::now(), - is_dir: true, - is_symlink: false, - }, - content: None, - }, - ); - state.emit_event(&[path]).await; - } - pub async fn insert_file(&self, path: impl AsRef, content: String) { let mut state = self.state.lock().await; let path = path.as_ref(); @@ -392,7 +370,7 @@ impl FakeFs { match tree { Object(map) => { - self.insert_dir(path).await; + self.create_dir(path).await.unwrap(); for (name, contents) in map { let mut path = PathBuf::from(path); path.push(name); @@ -400,7 +378,7 @@ impl FakeFs { } } Null => { - self.insert_dir(&path).await; + self.create_dir(&path).await.unwrap(); } String(contents) => { self.insert_file(&path, contents).await; diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index f88aee3d7c..56ccfaf9fe 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -554,7 +554,7 @@ mod tests { }); let save_task = workspace.update(cx, |workspace, cx| workspace.save_active_item(false, cx)); - app_state.fs.as_fake().insert_dir("/root").await; + app_state.fs.create_dir(Path::new("/root")).await.unwrap(); cx.simulate_new_path_selection(|_| Some(PathBuf::from("/root/the-new-name"))); save_task.await.unwrap(); editor.read_with(cx, |editor, cx| { @@ -680,14 +680,25 @@ mod tests { async fn test_open_paths(cx: &mut TestAppContext) { let app_state = init(cx); - let fs = app_state.fs.as_fake(); - fs.insert_dir("/dir1").await; - fs.insert_dir("/dir2").await; - fs.insert_dir("/dir3").await; - fs.insert_file("/dir1/a.txt", "".into()).await; - fs.insert_file("/dir2/b.txt", "".into()).await; - fs.insert_file("/dir3/c.txt", "".into()).await; - fs.insert_file("/d.txt", "".into()).await; + app_state + .fs + .as_fake() + .insert_tree( + "/", + json!({ + "dir1": { + "a.txt": "" + }, + "dir2": { + "b.txt": "" + }, + "dir3": { + "c.txt": "" + }, + "d.txt": "" + }), + ) + .await; let project = Project::test(app_state.fs.clone(), ["/dir1".as_ref()], cx).await; let (_, workspace) = cx.add_window(|cx| Workspace::new(project, cx)); @@ -891,7 +902,7 @@ mod tests { #[gpui::test] async fn test_open_and_save_new_file(cx: &mut TestAppContext) { let app_state = init(cx); - app_state.fs.as_fake().insert_dir("/root").await; + app_state.fs.create_dir(Path::new("/root")).await.unwrap(); let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await; project.update(cx, |project, _| project.languages().add(rust_lang())); @@ -980,7 +991,7 @@ mod tests { #[gpui::test] async fn test_setting_language_when_saving_as_single_file_worktree(cx: &mut TestAppContext) { let app_state = init(cx); - app_state.fs.as_fake().insert_dir("/root").await; + app_state.fs.create_dir(Path::new("/root")).await.unwrap(); let project = Project::test(app_state.fs.clone(), [], cx).await; project.update(cx, |project, _| project.languages().add(rust_lang()));