1use project::search::SearchQuery;
2use text::Rope;
3use util::{
4 paths::{PathMatcher, PathStyle},
5 rel_path::RelPath,
6};
7
8#[test]
9fn path_matcher_creation_for_valid_paths() {
10 for valid_path in [
11 "file",
12 "Cargo.toml",
13 ".DS_Store",
14 "~/dir/another_dir/",
15 "./dir/file",
16 "dir/[a-z].txt",
17 ] {
18 let path_matcher = PathMatcher::new(&[valid_path.to_owned()], PathStyle::local())
19 .unwrap_or_else(|e| panic!("Valid path {valid_path} should be accepted, but got: {e}"));
20 assert!(
21 path_matcher.is_match(&RelPath::new(valid_path.as_ref(), PathStyle::local()).unwrap()),
22 "Path matcher for valid path {valid_path} should match itself"
23 )
24 }
25}
26
27#[test]
28fn path_matcher_creation_for_globs() {
29 for invalid_glob in ["dir/[].txt", "dir/[a-z.txt", "dir/{file"] {
30 match PathMatcher::new(&[invalid_glob.to_owned()], PathStyle::local()) {
31 Ok(_) => panic!("Invalid glob {invalid_glob} should not be accepted"),
32 Err(_expected) => {}
33 }
34 }
35
36 for valid_glob in [
37 "dir/?ile",
38 "dir/*.txt",
39 "dir/**/file",
40 "dir/[a-z].txt",
41 "{dir,file}",
42 ] {
43 match PathMatcher::new(&[valid_glob.to_owned()], PathStyle::local()) {
44 Ok(_expected) => {}
45 Err(e) => panic!("Valid glob should be accepted, but got: {e}"),
46 }
47 }
48}
49
50#[test]
51fn test_case_sensitive_pattern_items() {
52 let case_sensitive = false;
53 let search_query = SearchQuery::regex(
54 "test\\C",
55 false,
56 case_sensitive,
57 false,
58 false,
59 Default::default(),
60 Default::default(),
61 false,
62 None,
63 )
64 .expect("Should be able to create a regex SearchQuery");
65
66 assert_eq!(
67 search_query.case_sensitive(),
68 true,
69 "Case sensitivity should be enabled when \\C pattern item is present in the query."
70 );
71
72 let case_sensitive = true;
73 let search_query = SearchQuery::regex(
74 "test\\c",
75 true,
76 case_sensitive,
77 false,
78 false,
79 Default::default(),
80 Default::default(),
81 false,
82 None,
83 )
84 .expect("Should be able to create a regex SearchQuery");
85
86 assert_eq!(
87 search_query.case_sensitive(),
88 false,
89 "Case sensitivity should be disabled when \\c pattern item is present, even if initially set to true."
90 );
91
92 let case_sensitive = false;
93 let search_query = SearchQuery::regex(
94 "test\\c\\C",
95 false,
96 case_sensitive,
97 false,
98 false,
99 Default::default(),
100 Default::default(),
101 false,
102 None,
103 )
104 .expect("Should be able to create a regex SearchQuery");
105
106 assert_eq!(
107 search_query.case_sensitive(),
108 true,
109 "Case sensitivity should be enabled when \\C is the last pattern item, even after a \\c."
110 );
111
112 let case_sensitive = false;
113 let search_query = SearchQuery::regex(
114 "tests\\\\C",
115 false,
116 case_sensitive,
117 false,
118 false,
119 Default::default(),
120 Default::default(),
121 false,
122 None,
123 )
124 .expect("Should be able to create a regex SearchQuery");
125
126 assert_eq!(
127 search_query.case_sensitive(),
128 false,
129 "Case sensitivity should not be enabled when \\C pattern item is preceded by a backslash."
130 );
131}
132
133#[gpui::test]
134async fn test_multiline_regex(cx: &mut gpui::TestAppContext) {
135 let search_query = SearchQuery::regex(
136 "^hello$\n",
137 false,
138 false,
139 false,
140 false,
141 Default::default(),
142 Default::default(),
143 false,
144 None,
145 )
146 .expect("Should be able to create a regex SearchQuery");
147
148 use language::Buffer;
149 let text = Rope::from("hello\nworld\nhello\nworld");
150 let snapshot = cx
151 .update(|app| Buffer::build_snapshot(text, None, None, app))
152 .await;
153
154 let results = search_query.search(&snapshot, None).await;
155 assert_eq!(results, vec![0..6, 12..18]);
156}