Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions crates/project/src/search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@ impl SearchQuery {
match_full_paths: bool,
buffers: Option<Vec<Entity<Buffer>>>,
) -> Result<Self> {
let query = query.to_string();
let mut query = query.to_string();
text::LineEnding::normalize(&mut query);
if !case_sensitive && !query.is_ascii() {
// AhoCorasickBuilder doesn't support case-insensitive search with unicode characters
// Fallback to regex search as recommended by
Expand Down Expand Up @@ -189,7 +190,8 @@ impl SearchQuery {
match_full_paths: bool,
buffers: Option<Vec<Entity<Buffer>>>,
) -> Result<Self> {
let query = query.to_string();
let mut query = query.to_string();
text::LineEnding::normalize(&mut query);
let inner = SearchInputs {
query: Arc::from(query.as_str()),
files_to_include,
Expand Down Expand Up @@ -402,6 +404,7 @@ impl SearchQuery {
let mut text = String::new();
if query_str.contains('\n') {
reader.read_to_string(&mut text)?;
text::LineEnding::normalize(&mut text);
Ok(search.is_match(&text))
} else {
let mut bytes_read = 0;
Expand All @@ -425,6 +428,7 @@ impl SearchQuery {
let mut text = String::new();
if *multiline {
reader.read_to_string(&mut text)?;
text::LineEnding::normalize(&mut text);
Ok(regex.is_match(&text)?)
} else {
let mut bytes_read = 0;
Expand Down
68 changes: 68 additions & 0 deletions crates/project/tests/integration/project_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7427,6 +7427,74 @@ async fn test_search(cx: &mut gpui::TestAppContext) {
);
}

#[gpui::test]
async fn test_search_multiline_crlf(cx: &mut gpui::TestAppContext) {
init_test(cx);

let fs = FakeFs::new(cx.executor());
fs.insert_tree(
path!("/dir"),
json!({
"crlf.rs": "alpha\r\nbeta\r\ngamma",
"lf.rs": "alpha\nbeta\ngamma",
}),
)
.await;
let project = Project::test(fs.clone(), [path!("/dir").as_ref()], cx).await;

// A query with CRLF line endings should match buffers regardless of their
// on-disk line endings (buffers always store normalized `\n`).
assert_eq!(
search(
&project,
SearchQuery::text(
"alpha\r\nbeta",
false,
true,
false,
Default::default(),
Default::default(),
false,
None,
)
.unwrap(),
cx
)
.await
.unwrap(),
HashMap::from_iter([
(path!("dir/crlf.rs").to_string(), vec![0..10]),
(path!("dir/lf.rs").to_string(), vec![0..10]),
])
);

// The reverse: a query with LF line endings should match a file that is
// stored with CRLF line endings on disk.
assert_eq!(
search(
&project,
SearchQuery::text(
"alpha\nbeta",
false,
true,
false,
Default::default(),
Default::default(),
false,
None,
)
.unwrap(),
cx
)
.await
.unwrap(),
HashMap::from_iter([
(path!("dir/crlf.rs").to_string(), vec![0..10]),
(path!("dir/lf.rs").to_string(), vec![0..10]),
])
);
}

#[gpui::test]
async fn test_search_with_inclusions(cx: &mut gpui::TestAppContext) {
init_test(cx);
Expand Down
Loading