From 9cc82212b52f068a95b361d5c90a9a043d8eafbd Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Fri, 13 Jun 2025 00:32:29 -0600 Subject: [PATCH] Remove `separator!` macro and make `path!` handle relative paths (#32527) Release Notes: - N/A --- .../src/context_picker/completion_provider.rs | 18 +- .../src/file_command.rs | 41 ++- crates/collab/src/tests/integration_tests.rs | 104 +++---- .../remote_editing_collaboration_tests.rs | 4 +- crates/file_finder/src/file_finder_tests.rs | 4 +- crates/project/src/project_tests.rs | 105 ++++--- .../project_panel/src/project_panel_tests.rs | 276 +++++++++--------- .../remote_server/src/remote_editing_tests.rs | 4 +- crates/semantic_index/src/semantic_index.rs | 4 +- crates/tasks_ui/src/tasks_ui.rs | 6 +- crates/util/src/util.rs | 46 +-- crates/util_macros/src/util_macros.rs | 25 +- crates/zed/src/zed.rs | 8 +- 13 files changed, 302 insertions(+), 343 deletions(-) diff --git a/crates/agent/src/context_picker/completion_provider.rs b/crates/agent/src/context_picker/completion_provider.rs index 3745c1cb9a..9ceb960ec7 100644 --- a/crates/agent/src/context_picker/completion_provider.rs +++ b/crates/agent/src/context_picker/completion_provider.rs @@ -1066,7 +1066,7 @@ mod tests { use serde_json::json; use settings::SettingsStore; use std::{ops::Deref, rc::Rc}; - use util::{path, separator}; + use util::path; use workspace::{AppState, Item}; #[test] @@ -1217,14 +1217,14 @@ mod tests { let mut cx = VisualTestContext::from_window(*window.deref(), cx); let paths = vec![ - separator!("a/one.txt"), - separator!("a/two.txt"), - separator!("a/three.txt"), - separator!("a/four.txt"), - separator!("b/five.txt"), - separator!("b/six.txt"), - separator!("b/seven.txt"), - separator!("b/eight.txt"), + path!("a/one.txt"), + path!("a/two.txt"), + path!("a/three.txt"), + path!("a/four.txt"), + path!("b/five.txt"), + path!("b/six.txt"), + path!("b/seven.txt"), + path!("b/eight.txt"), ]; let mut opened_editors = Vec::new(); diff --git a/crates/assistant_slash_commands/src/file_command.rs b/crates/assistant_slash_commands/src/file_command.rs index 45465f8bb1..c913ccc0f1 100644 --- a/crates/assistant_slash_commands/src/file_command.rs +++ b/crates/assistant_slash_commands/src/file_command.rs @@ -582,7 +582,7 @@ mod test { use serde_json::json; use settings::SettingsStore; use smol::stream::StreamExt; - use util::{path, separator}; + use util::path; use super::collect_files; @@ -627,7 +627,7 @@ mod test { .await .unwrap(); - assert!(result_1.text.starts_with(separator!("root/dir"))); + assert!(result_1.text.starts_with(path!("root/dir"))); // 4 files + 2 directories assert_eq!(result_1.sections.len(), 6); @@ -643,7 +643,7 @@ mod test { cx.update(|cx| collect_files(project.clone(), &["root/dir*".to_string()], cx).boxed()); let result = SlashCommandOutput::from_event_stream(result).await.unwrap(); - assert!(result.text.starts_with(separator!("root/dir"))); + assert!(result.text.starts_with(path!("root/dir"))); // 5 files + 2 directories assert_eq!(result.sections.len(), 7); @@ -691,24 +691,20 @@ mod test { .unwrap(); // Sanity check - assert!(result.text.starts_with(separator!("zed/assets/themes\n"))); + assert!(result.text.starts_with(path!("zed/assets/themes\n"))); assert_eq!(result.sections.len(), 7); // Ensure that full file paths are included in the real output assert!( result .text - .contains(separator!("zed/assets/themes/andromeda/LICENSE")) + .contains(path!("zed/assets/themes/andromeda/LICENSE")) ); + assert!(result.text.contains(path!("zed/assets/themes/ayu/LICENSE"))); assert!( result .text - .contains(separator!("zed/assets/themes/ayu/LICENSE")) - ); - assert!( - result - .text - .contains(separator!("zed/assets/themes/summercamp/LICENSE")) + .contains(path!("zed/assets/themes/summercamp/LICENSE")) ); assert_eq!(result.sections[5].label, "summercamp"); @@ -716,17 +712,17 @@ mod test { // Ensure that things are in descending order, with properly relativized paths assert_eq!( result.sections[0].label, - separator!("zed/assets/themes/andromeda/LICENSE") + path!("zed/assets/themes/andromeda/LICENSE") ); assert_eq!(result.sections[1].label, "andromeda"); assert_eq!( result.sections[2].label, - separator!("zed/assets/themes/ayu/LICENSE") + path!("zed/assets/themes/ayu/LICENSE") ); assert_eq!(result.sections[3].label, "ayu"); assert_eq!( result.sections[4].label, - separator!("zed/assets/themes/summercamp/LICENSE") + path!("zed/assets/themes/summercamp/LICENSE") ); // Ensure that the project lasts until after the last await @@ -767,31 +763,28 @@ mod test { .await .unwrap(); - assert!(result.text.starts_with(separator!("zed/assets/themes\n"))); - assert_eq!( - result.sections[0].label, - separator!("zed/assets/themes/LICENSE") - ); + assert!(result.text.starts_with(path!("zed/assets/themes\n"))); + assert_eq!(result.sections[0].label, path!("zed/assets/themes/LICENSE")); assert_eq!( result.sections[1].label, - separator!("zed/assets/themes/summercamp/LICENSE") + path!("zed/assets/themes/summercamp/LICENSE") ); assert_eq!( result.sections[2].label, - separator!("zed/assets/themes/summercamp/subdir/LICENSE") + path!("zed/assets/themes/summercamp/subdir/LICENSE") ); assert_eq!( result.sections[3].label, - separator!("zed/assets/themes/summercamp/subdir/subsubdir/LICENSE") + path!("zed/assets/themes/summercamp/subdir/subsubdir/LICENSE") ); assert_eq!(result.sections[4].label, "subsubdir"); assert_eq!(result.sections[5].label, "subdir"); assert_eq!(result.sections[6].label, "summercamp"); - assert_eq!(result.sections[7].label, separator!("zed/assets/themes")); + assert_eq!(result.sections[7].label, path!("zed/assets/themes")); assert_eq!( result.text, - separator!( + path!( "zed/assets/themes\n```zed/assets/themes/LICENSE\n1\n```\n\nsummercamp\n```zed/assets/themes/summercamp/LICENSE\n1\n```\n\nsubdir\n```zed/assets/themes/summercamp/subdir/LICENSE\n1\n```\n\nsubsubdir\n```zed/assets/themes/summercamp/subdir/subsubdir/LICENSE\n3\n```\n\n" ) ); diff --git a/crates/collab/src/tests/integration_tests.rs b/crates/collab/src/tests/integration_tests.rs index 548fa85f63..f3a5d45f65 100644 --- a/crates/collab/src/tests/integration_tests.rs +++ b/crates/collab/src/tests/integration_tests.rs @@ -51,7 +51,7 @@ use std::{ time::Duration, }; use unindent::Unindent as _; -use util::{path, separator, uri}; +use util::{path, uri}; use workspace::Pane; #[ctor::ctor] @@ -1676,13 +1676,13 @@ async fn test_project_reconnect( .map(|p| p.to_str().unwrap()) .collect::>(), vec![ - separator!("a.txt"), - separator!("b.txt"), - separator!("subdir2"), - separator!("subdir2/f.txt"), - separator!("subdir2/g.txt"), - separator!("subdir2/h.txt"), - separator!("subdir2/i.txt") + path!("a.txt"), + path!("b.txt"), + path!("subdir2"), + path!("subdir2/f.txt"), + path!("subdir2/g.txt"), + path!("subdir2/h.txt"), + path!("subdir2/i.txt") ] ); assert!(worktree_a3.read(cx).has_update_observer()); @@ -1709,13 +1709,13 @@ async fn test_project_reconnect( .map(|p| p.to_str().unwrap()) .collect::>(), vec![ - separator!("a.txt"), - separator!("b.txt"), - separator!("subdir2"), - separator!("subdir2/f.txt"), - separator!("subdir2/g.txt"), - separator!("subdir2/h.txt"), - separator!("subdir2/i.txt") + path!("a.txt"), + path!("b.txt"), + path!("subdir2"), + path!("subdir2/f.txt"), + path!("subdir2/g.txt"), + path!("subdir2/h.txt"), + path!("subdir2/i.txt") ] ); assert!(project.worktree_for_id(worktree2_id, cx).is_none()); @@ -1806,13 +1806,13 @@ async fn test_project_reconnect( .map(|p| p.to_str().unwrap()) .collect::>(), vec![ - separator!("a.txt"), - separator!("b.txt"), - separator!("subdir2"), - separator!("subdir2/f.txt"), - separator!("subdir2/g.txt"), - separator!("subdir2/h.txt"), - separator!("subdir2/j.txt") + path!("a.txt"), + path!("b.txt"), + path!("subdir2"), + path!("subdir2/f.txt"), + path!("subdir2/g.txt"), + path!("subdir2/h.txt"), + path!("subdir2/j.txt") ] ); assert!(project.worktree_for_id(worktree2_id, cx).is_none()); @@ -3315,13 +3315,13 @@ async fn test_fs_operations( .map(|p| p.to_string_lossy()) .collect::>(), [ - separator!("DIR"), - separator!("DIR/SUBDIR"), - separator!("DIR/SUBDIR/f.txt"), - separator!("DIR/e.txt"), - separator!("a.txt"), - separator!("b.txt"), - separator!("d.txt") + path!("DIR"), + path!("DIR/SUBDIR"), + path!("DIR/SUBDIR/f.txt"), + path!("DIR/e.txt"), + path!("a.txt"), + path!("b.txt"), + path!("d.txt") ] ); }); @@ -3333,13 +3333,13 @@ async fn test_fs_operations( .map(|p| p.to_string_lossy()) .collect::>(), [ - separator!("DIR"), - separator!("DIR/SUBDIR"), - separator!("DIR/SUBDIR/f.txt"), - separator!("DIR/e.txt"), - separator!("a.txt"), - separator!("b.txt"), - separator!("d.txt") + path!("DIR"), + path!("DIR/SUBDIR"), + path!("DIR/SUBDIR/f.txt"), + path!("DIR/e.txt"), + path!("a.txt"), + path!("b.txt"), + path!("d.txt") ] ); }); @@ -3359,14 +3359,14 @@ async fn test_fs_operations( .map(|p| p.to_string_lossy()) .collect::>(), [ - separator!("DIR"), - separator!("DIR/SUBDIR"), - separator!("DIR/SUBDIR/f.txt"), - separator!("DIR/e.txt"), - separator!("a.txt"), - separator!("b.txt"), - separator!("d.txt"), - separator!("f.txt") + path!("DIR"), + path!("DIR/SUBDIR"), + path!("DIR/SUBDIR/f.txt"), + path!("DIR/e.txt"), + path!("a.txt"), + path!("b.txt"), + path!("d.txt"), + path!("f.txt") ] ); }); @@ -3378,14 +3378,14 @@ async fn test_fs_operations( .map(|p| p.to_string_lossy()) .collect::>(), [ - separator!("DIR"), - separator!("DIR/SUBDIR"), - separator!("DIR/SUBDIR/f.txt"), - separator!("DIR/e.txt"), - separator!("a.txt"), - separator!("b.txt"), - separator!("d.txt"), - separator!("f.txt") + path!("DIR"), + path!("DIR/SUBDIR"), + path!("DIR/SUBDIR/f.txt"), + path!("DIR/e.txt"), + path!("a.txt"), + path!("b.txt"), + path!("d.txt"), + path!("f.txt") ] ); }); diff --git a/crates/collab/src/tests/remote_editing_collaboration_tests.rs b/crates/collab/src/tests/remote_editing_collaboration_tests.rs index a263b29808..217273a387 100644 --- a/crates/collab/src/tests/remote_editing_collaboration_tests.rs +++ b/crates/collab/src/tests/remote_editing_collaboration_tests.rs @@ -30,7 +30,7 @@ use rpc::proto; use serde_json::json; use settings::SettingsStore; use std::{path::Path, sync::Arc}; -use util::{path, separator}; +use util::path; #[gpui::test(iterations = 10)] async fn test_sharing_an_ssh_remote_project( @@ -198,7 +198,7 @@ async fn test_sharing_an_ssh_remote_project( .path() .to_string_lossy() .to_string(), - separator!("src/renamed.rs").to_string() + path!("src/renamed.rs").to_string() ); }); } diff --git a/crates/file_finder/src/file_finder_tests.rs b/crates/file_finder/src/file_finder_tests.rs index b0ac6e60f5..dbb6d45f91 100644 --- a/crates/file_finder/src/file_finder_tests.rs +++ b/crates/file_finder/src/file_finder_tests.rs @@ -209,7 +209,7 @@ async fn test_matching_paths(cx: &mut TestAppContext) { "bandana", "./bandana", ".\\bandana", - util::separator!("a/bandana"), + util::path!("a/bandana"), "b/bandana", "b\\bandana", " bandana", @@ -230,7 +230,7 @@ async fn test_matching_paths(cx: &mut TestAppContext) { assert_eq!( picker.delegate.matches.len(), // existence of CreateNew option depends on whether path already exists - if bandana_query == util::separator!("a/bandana") { + if bandana_query == util::path!("a/bandana") { 1 } else { 2 diff --git a/crates/project/src/project_tests.rs b/crates/project/src/project_tests.rs index 9e8cac2f81..fc41d79ad0 100644 --- a/crates/project/src/project_tests.rs +++ b/crates/project/src/project_tests.rs @@ -42,7 +42,6 @@ use unindent::Unindent as _; use util::{ TryFutureExt as _, assert_set_eq, maybe, path, paths::PathMatcher, - separator, test::{TempTree, marked_text_offsets}, uri, }; @@ -375,7 +374,7 @@ async fn test_managing_project_specific_settings(cx: &mut gpui::TestAppContext) ( TaskSourceKind::Worktree { id: worktree_id, - directory_in_worktree: PathBuf::from(separator!("b/.zed")), + directory_in_worktree: PathBuf::from(path!("b/.zed")), id_base: if cfg!(windows) { "local worktree tasks from directory \"b\\\\.zed\"".into() } else { @@ -460,7 +459,7 @@ async fn test_managing_project_specific_settings(cx: &mut gpui::TestAppContext) ( TaskSourceKind::Worktree { id: worktree_id, - directory_in_worktree: PathBuf::from(separator!("b/.zed")), + directory_in_worktree: PathBuf::from(path!("b/.zed")), id_base: if cfg!(windows) { "local worktree tasks from directory \"b\\\\.zed\"".into() } else { @@ -575,7 +574,7 @@ async fn test_fallback_to_single_worktree_tasks(cx: &mut gpui::TestAppContext) { vec![( TaskSourceKind::Worktree { id: worktree_id, - directory_in_worktree: PathBuf::from(separator!(".zed")), + directory_in_worktree: PathBuf::from(path!(".zed")), id_base: if cfg!(windows) { "local worktree tasks from directory \".zed\"".into() } else { @@ -3987,12 +3986,12 @@ async fn test_rescan_and_remote_updates(cx: &mut gpui::TestAppContext) { .collect::>(), vec![ "a", - separator!("a/file1"), - separator!("a/file2.new"), + path!("a/file1"), + path!("a/file2.new"), "b", "d", - separator!("d/file3"), - separator!("d/file4"), + path!("d/file3"), + path!("d/file4"), ] ); }); @@ -4055,12 +4054,12 @@ async fn test_rescan_and_remote_updates(cx: &mut gpui::TestAppContext) { .collect::>(), vec![ "a", - separator!("a/file1"), - separator!("a/file2.new"), + path!("a/file1"), + path!("a/file2.new"), "b", "d", - separator!("d/file3"), - separator!("d/file4"), + path!("d/file3"), + path!("d/file4"), ] ); }); @@ -5055,8 +5054,8 @@ async fn test_search(cx: &mut gpui::TestAppContext) { .await .unwrap(), HashMap::from_iter([ - (separator!("dir/two.rs").to_string(), vec![6..9]), - (separator!("dir/three.rs").to_string(), vec![37..40]) + (path!("dir/two.rs").to_string(), vec![6..9]), + (path!("dir/three.rs").to_string(), vec![37..40]) ]) ); @@ -5090,9 +5089,9 @@ async fn test_search(cx: &mut gpui::TestAppContext) { .await .unwrap(), HashMap::from_iter([ - (separator!("dir/two.rs").to_string(), vec![6..9]), - (separator!("dir/three.rs").to_string(), vec![37..40]), - (separator!("dir/four.rs").to_string(), vec![25..28, 36..39]) + (path!("dir/two.rs").to_string(), vec![6..9]), + (path!("dir/three.rs").to_string(), vec![37..40]), + (path!("dir/four.rs").to_string(), vec![25..28, 36..39]) ]) ); } @@ -5157,8 +5156,8 @@ async fn test_search_with_inclusions(cx: &mut gpui::TestAppContext) { .await .unwrap(), HashMap::from_iter([ - (separator!("dir/one.rs").to_string(), vec![8..12]), - (separator!("dir/two.rs").to_string(), vec![8..12]), + (path!("dir/one.rs").to_string(), vec![8..12]), + (path!("dir/two.rs").to_string(), vec![8..12]), ]), "Rust only search should give only Rust files" ); @@ -5182,8 +5181,8 @@ async fn test_search_with_inclusions(cx: &mut gpui::TestAppContext) { .await .unwrap(), HashMap::from_iter([ - (separator!("dir/one.ts").to_string(), vec![14..18]), - (separator!("dir/two.ts").to_string(), vec![14..18]), + (path!("dir/one.ts").to_string(), vec![14..18]), + (path!("dir/two.ts").to_string(), vec![14..18]), ]), "TypeScript only search should give only TypeScript files, even if other inclusions don't match anything" ); @@ -5208,10 +5207,10 @@ async fn test_search_with_inclusions(cx: &mut gpui::TestAppContext) { .await .unwrap(), HashMap::from_iter([ - (separator!("dir/two.ts").to_string(), vec![14..18]), - (separator!("dir/one.rs").to_string(), vec![8..12]), - (separator!("dir/one.ts").to_string(), vec![14..18]), - (separator!("dir/two.rs").to_string(), vec![8..12]), + (path!("dir/two.ts").to_string(), vec![14..18]), + (path!("dir/one.rs").to_string(), vec![8..12]), + (path!("dir/one.ts").to_string(), vec![14..18]), + (path!("dir/two.rs").to_string(), vec![8..12]), ]), "Rust and typescript search should give both Rust and TypeScript files, even if other inclusions don't match anything" ); @@ -5255,10 +5254,10 @@ async fn test_search_with_exclusions(cx: &mut gpui::TestAppContext) { .await .unwrap(), HashMap::from_iter([ - (separator!("dir/one.rs").to_string(), vec![8..12]), - (separator!("dir/one.ts").to_string(), vec![14..18]), - (separator!("dir/two.rs").to_string(), vec![8..12]), - (separator!("dir/two.ts").to_string(), vec![14..18]), + (path!("dir/one.rs").to_string(), vec![8..12]), + (path!("dir/one.ts").to_string(), vec![14..18]), + (path!("dir/two.rs").to_string(), vec![8..12]), + (path!("dir/two.ts").to_string(), vec![14..18]), ]), "If no exclusions match, all files should be returned" ); @@ -5282,8 +5281,8 @@ async fn test_search_with_exclusions(cx: &mut gpui::TestAppContext) { .await .unwrap(), HashMap::from_iter([ - (separator!("dir/one.ts").to_string(), vec![14..18]), - (separator!("dir/two.ts").to_string(), vec![14..18]), + (path!("dir/one.ts").to_string(), vec![14..18]), + (path!("dir/two.ts").to_string(), vec![14..18]), ]), "Rust exclusion search should give only TypeScript files" ); @@ -5307,8 +5306,8 @@ async fn test_search_with_exclusions(cx: &mut gpui::TestAppContext) { .await .unwrap(), HashMap::from_iter([ - (separator!("dir/one.rs").to_string(), vec![8..12]), - (separator!("dir/two.rs").to_string(), vec![8..12]), + (path!("dir/one.rs").to_string(), vec![8..12]), + (path!("dir/two.rs").to_string(), vec![8..12]), ]), "TypeScript exclusion search should give only Rust files, even if other exclusions don't match anything" ); @@ -5441,8 +5440,8 @@ async fn test_search_with_exclusions_and_inclusions(cx: &mut gpui::TestAppContex .await .unwrap(), HashMap::from_iter([ - (separator!("dir/one.ts").to_string(), vec![14..18]), - (separator!("dir/two.ts").to_string(), vec![14..18]), + (path!("dir/one.ts").to_string(), vec![14..18]), + (path!("dir/two.ts").to_string(), vec![14..18]), ]), "Non-intersecting TypeScript inclusions and Rust exclusions should return TypeScript files" ); @@ -5495,7 +5494,7 @@ async fn test_search_multiple_worktrees_with_inclusions(cx: &mut gpui::TestAppCo ) .await .unwrap(), - HashMap::from_iter([(separator!("worktree-a/haystack.rs").to_string(), vec![3..9])]), + HashMap::from_iter([(path!("worktree-a/haystack.rs").to_string(), vec![3..9])]), "should only return results from included worktree" ); assert_eq!( @@ -5516,7 +5515,7 @@ async fn test_search_multiple_worktrees_with_inclusions(cx: &mut gpui::TestAppCo ) .await .unwrap(), - HashMap::from_iter([(separator!("worktree-b/haystack.rs").to_string(), vec![3..9])]), + HashMap::from_iter([(path!("worktree-b/haystack.rs").to_string(), vec![3..9])]), "should only return results from included worktree" ); @@ -5539,8 +5538,8 @@ async fn test_search_multiple_worktrees_with_inclusions(cx: &mut gpui::TestAppCo .await .unwrap(), HashMap::from_iter([ - (separator!("worktree-a/haystack.ts").to_string(), vec![3..9]), - (separator!("worktree-b/haystack.ts").to_string(), vec![3..9]) + (path!("worktree-a/haystack.ts").to_string(), vec![3..9]), + (path!("worktree-b/haystack.ts").to_string(), vec![3..9]) ]), "should return results from both worktrees" ); @@ -5594,7 +5593,7 @@ async fn test_search_in_gitignored_dirs(cx: &mut gpui::TestAppContext) { ) .await .unwrap(), - HashMap::from_iter([(separator!("dir/package.json").to_string(), vec![8..11])]), + HashMap::from_iter([(path!("dir/package.json").to_string(), vec![8..11])]), "Only one non-ignored file should have the query" ); @@ -5618,22 +5617,22 @@ async fn test_search_in_gitignored_dirs(cx: &mut gpui::TestAppContext) { .await .unwrap(), HashMap::from_iter([ - (separator!("dir/package.json").to_string(), vec![8..11]), - (separator!("dir/target/index.txt").to_string(), vec![6..9]), + (path!("dir/package.json").to_string(), vec![8..11]), + (path!("dir/target/index.txt").to_string(), vec![6..9]), ( - separator!("dir/node_modules/prettier/package.json").to_string(), + path!("dir/node_modules/prettier/package.json").to_string(), vec![9..12] ), ( - separator!("dir/node_modules/prettier/index.ts").to_string(), + path!("dir/node_modules/prettier/index.ts").to_string(), vec![15..18] ), ( - separator!("dir/node_modules/eslint/index.ts").to_string(), + path!("dir/node_modules/eslint/index.ts").to_string(), vec![13..16] ), ( - separator!("dir/node_modules/eslint/package.json").to_string(), + path!("dir/node_modules/eslint/package.json").to_string(), vec![8..11] ), ]), @@ -5662,7 +5661,7 @@ async fn test_search_in_gitignored_dirs(cx: &mut gpui::TestAppContext) { .await .unwrap(), HashMap::from_iter([( - separator!("dir/node_modules/prettier/package.json").to_string(), + path!("dir/node_modules/prettier/package.json").to_string(), vec![9..12] )]), "With search including ignored prettier directory and excluding TS files, only one file should be found" @@ -5701,8 +5700,8 @@ async fn test_search_with_unicode(cx: &mut gpui::TestAppContext) { .await .unwrap(), HashMap::from_iter([ - (separator!("dir/one.rs").to_string(), vec![17..29]), - (separator!("dir/three.rs").to_string(), vec![3..15]), + (path!("dir/one.rs").to_string(), vec![17..29]), + (path!("dir/three.rs").to_string(), vec![3..15]), ]) ); @@ -5725,9 +5724,9 @@ async fn test_search_with_unicode(cx: &mut gpui::TestAppContext) { .await .unwrap(), HashMap::from_iter([ - (separator!("dir/one.rs").to_string(), vec![3..15, 17..29]), - (separator!("dir/two.rs").to_string(), vec![3..15]), - (separator!("dir/three.rs").to_string(), vec![3..15]), + (path!("dir/one.rs").to_string(), vec![3..15, 17..29]), + (path!("dir/two.rs").to_string(), vec![3..15]), + (path!("dir/three.rs").to_string(), vec![3..15]), ]) ); @@ -5749,7 +5748,7 @@ async fn test_search_with_unicode(cx: &mut gpui::TestAppContext) { ) .await .unwrap(), - HashMap::from_iter([(separator!("dir/two.rs").to_string(), vec![3..16]),]) + HashMap::from_iter([(path!("dir/two.rs").to_string(), vec![3..16]),]) ); } diff --git a/crates/project_panel/src/project_panel_tests.rs b/crates/project_panel/src/project_panel_tests.rs index 9604755d1e..7699256bc9 100644 --- a/crates/project_panel/src/project_panel_tests.rs +++ b/crates/project_panel/src/project_panel_tests.rs @@ -6,7 +6,7 @@ use project::{FakeFs, WorktreeSettings}; use serde_json::json; use settings::SettingsStore; use std::path::{Path, PathBuf}; -use util::{path, separator}; +use util::path; use workspace::{ AppState, Pane, item::{Item, ProjectItem}, @@ -332,10 +332,10 @@ async fn test_auto_collapse_dir_paths(cx: &mut gpui::TestAppContext) { assert_eq!( visible_entries_as_strings(&panel, 0..10, cx), &[ - separator!("v root1"), - separator!(" > dir_1/nested_dir_1/nested_dir_2/nested_dir_3"), - separator!("v root2"), - separator!(" > dir_2"), + "v root1", + " > dir_1/nested_dir_1/nested_dir_2/nested_dir_3", + "v root2", + " > dir_2", ] ); @@ -347,14 +347,14 @@ async fn test_auto_collapse_dir_paths(cx: &mut gpui::TestAppContext) { assert_eq!( visible_entries_as_strings(&panel, 0..10, cx), &[ - separator!("v root1"), - separator!(" v dir_1/nested_dir_1/nested_dir_2/nested_dir_3 <== selected"), - separator!(" > nested_dir_4/nested_dir_5"), - separator!(" file_a.java"), - separator!(" file_b.java"), - separator!(" file_c.java"), - separator!("v root2"), - separator!(" > dir_2"), + "v root1", + " v dir_1/nested_dir_1/nested_dir_2/nested_dir_3 <== selected", + " > nested_dir_4/nested_dir_5", + " file_a.java", + " file_b.java", + " file_c.java", + "v root2", + " > dir_2", ] ); @@ -366,31 +366,31 @@ async fn test_auto_collapse_dir_paths(cx: &mut gpui::TestAppContext) { assert_eq!( visible_entries_as_strings(&panel, 0..10, cx), &[ - separator!("v root1"), - separator!(" v dir_1/nested_dir_1/nested_dir_2/nested_dir_3"), - separator!(" v nested_dir_4/nested_dir_5 <== selected"), - separator!(" file_d.java"), - separator!(" file_a.java"), - separator!(" file_b.java"), - separator!(" file_c.java"), - separator!("v root2"), - separator!(" > dir_2"), + "v root1", + " v dir_1/nested_dir_1/nested_dir_2/nested_dir_3", + " v nested_dir_4/nested_dir_5 <== selected", + " file_d.java", + " file_a.java", + " file_b.java", + " file_c.java", + "v root2", + " > dir_2", ] ); toggle_expand_dir(&panel, "root2/dir_2", cx); assert_eq!( visible_entries_as_strings(&panel, 0..10, cx), &[ - separator!("v root1"), - separator!(" v dir_1/nested_dir_1/nested_dir_2/nested_dir_3"), - separator!(" v nested_dir_4/nested_dir_5"), - separator!(" file_d.java"), - separator!(" file_a.java"), - separator!(" file_b.java"), - separator!(" file_c.java"), - separator!("v root2"), - separator!(" v dir_2 <== selected"), - separator!(" file_1.java"), + "v root1", + " v dir_1/nested_dir_1/nested_dir_2/nested_dir_3", + " v nested_dir_4/nested_dir_5", + " file_d.java", + " file_a.java", + " file_b.java", + " file_c.java", + "v root2", + " v dir_2 <== selected", + " file_1.java", ] ); @@ -414,7 +414,7 @@ async fn test_auto_collapse_dir_paths(cx: &mut gpui::TestAppContext) { let panel = workspace.update(cx, ProjectPanel::new).unwrap(); assert_eq!( visible_entries_as_strings(&panel, 0..10, cx), - &[separator!("> dir_1/nested_dir_1/nested_dir_2/nested_dir_3")], + &["> dir_1/nested_dir_1/nested_dir_2/nested_dir_3"], "Single worktree with hide_root=true should hide root and show auto-folded paths" ); @@ -426,11 +426,11 @@ async fn test_auto_collapse_dir_paths(cx: &mut gpui::TestAppContext) { assert_eq!( visible_entries_as_strings(&panel, 0..10, cx), &[ - separator!("v dir_1/nested_dir_1/nested_dir_2/nested_dir_3 <== selected"), - separator!(" > nested_dir_4/nested_dir_5"), - separator!(" file_a.java"), - separator!(" file_b.java"), - separator!(" file_c.java"), + "v dir_1/nested_dir_1/nested_dir_2/nested_dir_3 <== selected", + " > nested_dir_4/nested_dir_5", + " file_a.java", + " file_b.java", + " file_c.java", ], "Expanded auto-folded path with hidden root should show contents without root prefix" ); @@ -443,12 +443,12 @@ async fn test_auto_collapse_dir_paths(cx: &mut gpui::TestAppContext) { assert_eq!( visible_entries_as_strings(&panel, 0..10, cx), &[ - separator!("v dir_1/nested_dir_1/nested_dir_2/nested_dir_3"), - separator!(" v nested_dir_4/nested_dir_5 <== selected"), - separator!(" file_d.java"), - separator!(" file_a.java"), - separator!(" file_b.java"), - separator!(" file_c.java"), + "v dir_1/nested_dir_1/nested_dir_2/nested_dir_3", + " v nested_dir_4/nested_dir_5 <== selected", + " file_d.java", + " file_a.java", + " file_b.java", + " file_c.java", ], "Nested expansion with hidden root should maintain proper indentation" ); @@ -4917,12 +4917,12 @@ async fn test_expand_all_for_entry(cx: &mut gpui::TestAppContext) { assert_eq!( visible_entries_as_strings(&panel, 0..20, cx), &[ - separator!("v root"), - separator!(" v dir1 <== selected"), - separator!(" > empty1/empty2/empty3"), - separator!(" > ignored_dir"), - separator!(" > subdir1"), - separator!(" .gitignore"), + "v root", + " v dir1 <== selected", + " > empty1/empty2/empty3", + " > ignored_dir", + " > subdir1", + " .gitignore", ], "Should show first level with auto-folded dirs and ignored dir visible" ); @@ -4939,18 +4939,18 @@ async fn test_expand_all_for_entry(cx: &mut gpui::TestAppContext) { assert_eq!( visible_entries_as_strings(&panel, 0..20, cx), &[ - separator!("v root"), - separator!(" v dir1 <== selected"), - separator!(" v empty1"), - separator!(" v empty2"), - separator!(" v empty3"), - separator!(" file.txt"), - separator!(" > ignored_dir"), - separator!(" v subdir1"), - separator!(" > ignored_nested"), - separator!(" file1.txt"), - separator!(" file2.txt"), - separator!(" .gitignore"), + "v root", + " v dir1 <== selected", + " v empty1", + " v empty2", + " v empty3", + " file.txt", + " > ignored_dir", + " v subdir1", + " > ignored_nested", + " file1.txt", + " file2.txt", + " .gitignore", ], "After expand_all with auto-fold: should not expand ignored_dir, should expand folded dirs, and should not expand ignored_nested" ); @@ -4975,12 +4975,12 @@ async fn test_expand_all_for_entry(cx: &mut gpui::TestAppContext) { assert_eq!( visible_entries_as_strings(&panel, 0..20, cx), &[ - separator!("v root"), - separator!(" v dir1 <== selected"), - separator!(" > empty1"), - separator!(" > ignored_dir"), - separator!(" > subdir1"), - separator!(" .gitignore"), + "v root", + " v dir1 <== selected", + " > empty1", + " > ignored_dir", + " > subdir1", + " .gitignore", ], "With auto-fold disabled: should show all directories separately" ); @@ -4997,18 +4997,18 @@ async fn test_expand_all_for_entry(cx: &mut gpui::TestAppContext) { assert_eq!( visible_entries_as_strings(&panel, 0..20, cx), &[ - separator!("v root"), - separator!(" v dir1 <== selected"), - separator!(" v empty1"), - separator!(" v empty2"), - separator!(" v empty3"), - separator!(" file.txt"), - separator!(" > ignored_dir"), - separator!(" v subdir1"), - separator!(" > ignored_nested"), - separator!(" file1.txt"), - separator!(" file2.txt"), - separator!(" .gitignore"), + "v root", + " v dir1 <== selected", + " v empty1", + " v empty2", + " v empty3", + " file.txt", + " > ignored_dir", + " v subdir1", + " > ignored_nested", + " file1.txt", + " file2.txt", + " .gitignore", ], "After expand_all without auto-fold: should expand all dirs normally, \ expand ignored_dir itself but not its subdirs, and not expand ignored_nested" @@ -5027,20 +5027,20 @@ async fn test_expand_all_for_entry(cx: &mut gpui::TestAppContext) { assert_eq!( visible_entries_as_strings(&panel, 0..20, cx), &[ - separator!("v root"), - separator!(" v dir1 <== selected"), - separator!(" v empty1"), - separator!(" v empty2"), - separator!(" v empty3"), - separator!(" file.txt"), - separator!(" v ignored_dir"), - separator!(" v subdir"), - separator!(" deep_file.txt"), - separator!(" v subdir1"), - separator!(" > ignored_nested"), - separator!(" file1.txt"), - separator!(" file2.txt"), - separator!(" .gitignore"), + "v root", + " v dir1 <== selected", + " v empty1", + " v empty2", + " v empty3", + " file.txt", + " v ignored_dir", + " v subdir", + " deep_file.txt", + " v subdir1", + " > ignored_nested", + " file1.txt", + " file2.txt", + " .gitignore", ], "After expand_all on ignored_dir: should expand all contents of the ignored directory" ); @@ -5090,15 +5090,15 @@ async fn test_collapse_all_for_entry(cx: &mut gpui::TestAppContext) { assert_eq!( visible_entries_as_strings(&panel, 0..20, cx), &[ - separator!("v root"), - separator!(" v dir1"), - separator!(" v subdir1"), - separator!(" v nested1"), - separator!(" file1.txt"), - separator!(" file2.txt"), - separator!(" v subdir2 <== selected"), - separator!(" file4.txt"), - separator!(" > dir2"), + "v root", + " v dir1", + " v subdir1", + " v nested1", + " file1.txt", + " file2.txt", + " v subdir2 <== selected", + " file4.txt", + " > dir2", ], "Initial state with everything expanded" ); @@ -5140,13 +5140,13 @@ async fn test_collapse_all_for_entry(cx: &mut gpui::TestAppContext) { assert_eq!( visible_entries_as_strings(&panel, 0..20, cx), &[ - separator!("v root"), - separator!(" v dir1"), - separator!(" v subdir1/nested1 <== selected"), - separator!(" file1.txt"), - separator!(" file2.txt"), - separator!(" > subdir2"), - separator!(" > dir2/single_file"), + "v root", + " v dir1", + " v subdir1/nested1 <== selected", + " file1.txt", + " file2.txt", + " > subdir2", + " > dir2/single_file", ], "Initial state with some dirs expanded" ); @@ -5163,11 +5163,11 @@ async fn test_collapse_all_for_entry(cx: &mut gpui::TestAppContext) { assert_eq!( visible_entries_as_strings(&panel, 0..20, cx), &[ - separator!("v root"), - separator!(" v dir1 <== selected"), - separator!(" > subdir1/nested1"), - separator!(" > subdir2"), - separator!(" > dir2/single_file"), + "v root", + " v dir1 <== selected", + " > subdir1/nested1", + " > subdir2", + " > dir2/single_file", ], "Subdirs should be collapsed and folded with auto-fold enabled" ); @@ -5195,14 +5195,14 @@ async fn test_collapse_all_for_entry(cx: &mut gpui::TestAppContext) { assert_eq!( visible_entries_as_strings(&panel, 0..20, cx), &[ - separator!("v root"), - separator!(" v dir1"), - separator!(" v subdir1"), - separator!(" v nested1 <== selected"), - separator!(" file1.txt"), - separator!(" file2.txt"), - separator!(" > subdir2"), - separator!(" > dir2"), + "v root", + " v dir1", + " v subdir1", + " v nested1 <== selected", + " file1.txt", + " file2.txt", + " > subdir2", + " > dir2", ], "Initial state with some dirs expanded and auto-fold disabled" ); @@ -5219,11 +5219,11 @@ async fn test_collapse_all_for_entry(cx: &mut gpui::TestAppContext) { assert_eq!( visible_entries_as_strings(&panel, 0..20, cx), &[ - separator!("v root"), - separator!(" v dir1 <== selected"), - separator!(" > subdir1"), - separator!(" > subdir2"), - separator!(" > dir2"), + "v root", + " v dir1 <== selected", + " > subdir1", + " > subdir2", + " > dir2", ], "Subdirs should be collapsed but not folded with auto-fold disabled" ); @@ -5261,8 +5261,8 @@ async fn test_create_entries_without_selection(cx: &mut gpui::TestAppContext) { assert_eq!( visible_entries_as_strings(&panel, 0..20, cx), &[ - separator!("v root"), - separator!(" > dir1"), + "v root", + " > dir1", ], "Initial state with nothing selected" ); @@ -5287,9 +5287,9 @@ async fn test_create_entries_without_selection(cx: &mut gpui::TestAppContext) { assert_eq!( visible_entries_as_strings(&panel, 0..20, cx), &[ - separator!("v root"), - separator!(" > dir1"), - separator!(" hello_from_no_selections <== selected <== marked"), + "v root", + " > dir1", + " hello_from_no_selections <== selected <== marked", ], "A new file is created under the root directory" ); @@ -5911,12 +5911,16 @@ fn visible_entries_as_strings( } else { " " }; + #[cfg(windows)] + let filename = details.filename.replace("\\", "/"); + #[cfg(not(windows))] + let filename = details.filename; let name = if details.is_editing { - format!("[EDITOR: '{}']", details.filename) + format!("[EDITOR: '{}']", filename) } else if details.is_processing { - format!("[PROCESSING: '{}']", details.filename) + format!("[PROCESSING: '{}']", filename) } else { - details.filename.clone() + filename }; let selected = if details.is_selected { " <== selected" diff --git a/crates/remote_server/src/remote_editing_tests.rs b/crates/remote_server/src/remote_editing_tests.rs index 1b54337a8d..81b98d953f 100644 --- a/crates/remote_server/src/remote_editing_tests.rs +++ b/crates/remote_server/src/remote_editing_tests.rs @@ -33,7 +33,7 @@ use std::{ }; #[cfg(not(windows))] use unindent::Unindent as _; -use util::{path, separator}; +use util::path; #[gpui::test] async fn test_basic_remote_editing(cx: &mut TestAppContext, server_cx: &mut TestAppContext) { @@ -218,7 +218,7 @@ async fn test_remote_project_search(cx: &mut TestAppContext, server_cx: &mut Tes buffer.update(&mut cx, |buffer, cx| { assert_eq!( buffer.file().unwrap().full_path(cx).to_string_lossy(), - separator!("project1/README.md") + path!("project1/README.md") ) }); diff --git a/crates/semantic_index/src/semantic_index.rs b/crates/semantic_index/src/semantic_index.rs index d3dcc488e1..a9cc08382b 100644 --- a/crates/semantic_index/src/semantic_index.rs +++ b/crates/semantic_index/src/semantic_index.rs @@ -277,7 +277,7 @@ mod tests { use settings::SettingsStore; use smol::channel; use std::{future, path::Path, sync::Arc}; - use util::separator; + use util::path; fn init_test(cx: &mut TestAppContext) { zlog::init_test(); @@ -422,7 +422,7 @@ mod tests { assert_eq!( search_result.path.to_string_lossy(), - separator!("fixture/needle.md") + path!("fixture/needle.md") ); let content = cx diff --git a/crates/tasks_ui/src/tasks_ui.rs b/crates/tasks_ui/src/tasks_ui.rs index f0131b52a0..acdc7d0298 100644 --- a/crates/tasks_ui/src/tasks_ui.rs +++ b/crates/tasks_ui/src/tasks_ui.rs @@ -400,7 +400,7 @@ mod tests { use serde_json::json; use task::{TaskContext, TaskVariables, VariableName}; use ui::VisualContext; - use util::{path, separator}; + use util::path; use workspace::{AppState, Workspace}; use crate::task_contexts; @@ -524,7 +524,7 @@ mod tests { task_variables: TaskVariables::from_iter([ (VariableName::File, path!("/dir/rust/b.rs").into()), (VariableName::Filename, "b.rs".into()), - (VariableName::RelativeFile, separator!("rust/b.rs").into()), + (VariableName::RelativeFile, path!("rust/b.rs").into()), (VariableName::RelativeDir, "rust".into()), (VariableName::Dirname, path!("/dir/rust").into()), (VariableName::Stem, "b".into()), @@ -556,7 +556,7 @@ mod tests { task_variables: TaskVariables::from_iter([ (VariableName::File, path!("/dir/rust/b.rs").into()), (VariableName::Filename, "b.rs".into()), - (VariableName::RelativeFile, separator!("rust/b.rs").into()), + (VariableName::RelativeFile, path!("rust/b.rs").into()), (VariableName::RelativeDir, "rust".into()), (VariableName::Dirname, path!("/dir/rust").into()), (VariableName::Stem, "b".into()), diff --git a/crates/util/src/util.rs b/crates/util/src/util.rs index b450e4900f..d24e40641f 100644 --- a/crates/util/src/util.rs +++ b/crates/util/src/util.rs @@ -30,7 +30,7 @@ use unicase::UniCase; pub use take_until::*; #[cfg(any(test, feature = "test-support"))] -pub use util_macros::{line_endings, separator, uri}; +pub use util_macros::{line_endings, path, uri}; #[macro_export] macro_rules! debug_panic { @@ -44,50 +44,6 @@ macro_rules! debug_panic { }; } -/// A macro to add "C:" to the beginning of a path literal on Windows, and replace all -/// the separator from `/` to `\`. -/// But on non-Windows platforms, it will return the path literal as is. -/// -/// # Examples -/// ```rust -/// use util::path; -/// -/// let path = path!("/Users/user/file.txt"); -/// #[cfg(target_os = "windows")] -/// assert_eq!(path, "C:\\Users\\user\\file.txt"); -/// #[cfg(not(target_os = "windows"))] -/// assert_eq!(path, "/Users/user/file.txt"); -/// ``` -#[cfg(all(any(test, feature = "test-support"), target_os = "windows"))] -#[macro_export] -macro_rules! path { - ($path:literal) => { - concat!("C:", util::separator!($path)) - }; -} - -/// A macro to add "C:" to the beginning of a path literal on Windows, and replace all -/// the separator from `/` to `\`. -/// But on non-Windows platforms, it will return the path literal as is. -/// -/// # Examples -/// ```rust -/// use util::path; -/// -/// let path = path!("/Users/user/file.txt"); -/// #[cfg(target_os = "windows")] -/// assert_eq!(path, "C:\\Users\\user\\file.txt"); -/// #[cfg(not(target_os = "windows"))] -/// assert_eq!(path, "/Users/user/file.txt"); -/// ``` -#[cfg(all(any(test, feature = "test-support"), not(target_os = "windows")))] -#[macro_export] -macro_rules! path { - ($path:literal) => { - $path - }; -} - pub fn truncate(s: &str, max_chars: usize) -> &str { match s.char_indices().nth(max_chars) { None => s, diff --git a/crates/util_macros/src/util_macros.rs b/crates/util_macros/src/util_macros.rs index ebe3517d56..9d0b06ab10 100644 --- a/crates/util_macros/src/util_macros.rs +++ b/crates/util_macros/src/util_macros.rs @@ -4,25 +4,32 @@ use proc_macro::TokenStream; use quote::quote; use syn::{LitStr, parse_macro_input}; -/// This macro replaces the path separator `/` with `\` for Windows. -/// But if the target OS is not Windows, the path is returned as is. +/// A macro used in tests for cross-platform path string literals in tests. On Windows it replaces +/// `/` with `\\` and adds `C:` to the beginning of absolute paths. On other platforms, the path is +/// returned unmodified. /// /// # Example /// ```rust -/// # use util_macros::separator; -/// let path = separator!("path/to/file"); +/// use util_macros::path; +/// +/// let path = path!("/Users/user/file.txt"); /// #[cfg(target_os = "windows")] -/// assert_eq!(path, "path\\to\\file"); +/// assert_eq!(path, "C:\\Users\\user\\file.txt"); /// #[cfg(not(target_os = "windows"))] -/// assert_eq!(path, "path/to/file"); +/// assert_eq!(path, "/Users/user/file.txt"); /// ``` #[proc_macro] -pub fn separator(input: TokenStream) -> TokenStream { +pub fn path(input: TokenStream) -> TokenStream { let path = parse_macro_input!(input as LitStr); - let path = path.value(); + let mut path = path.value(); #[cfg(target_os = "windows")] - let path = path.replace("/", "\\"); + { + path = path.replace("/", "\\"); + if path.starts_with("\\") { + path = format!("C:{}", path); + } + } TokenStream::from(quote! { #path diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 684af46695..b70647e5a8 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -1760,7 +1760,7 @@ mod tests { time::Duration, }; use theme::{ThemeRegistry, ThemeSettings}; - use util::{path, separator}; + use util::path; use workspace::{ NewFile, OpenOptions, OpenVisible, SERIALIZATION_THROTTLE_TIME, SaveIntent, SplitDirection, WorkspaceHandle, @@ -2864,8 +2864,8 @@ mod tests { opened_paths, vec![ None, - Some(separator!(".git/HEAD").to_string()), - Some(separator!("excluded_dir/file").to_string()), + Some(path!(".git/HEAD").to_string()), + Some(path!("excluded_dir/file").to_string()), ], "Excluded files should get opened, excluded dir should not get opened" ); @@ -2891,7 +2891,7 @@ mod tests { opened_buffer_paths.sort(); assert_eq!( opened_buffer_paths, - vec![separator!(".git/HEAD").to_string(), separator!("excluded_dir/file").to_string()], + vec![path!(".git/HEAD").to_string(), path!("excluded_dir/file").to_string()], "Despite not being present in the worktrees, buffers for excluded files are opened and added to the pane" ); });