From 563baf682eaf92e29cf50de5c9992eb13db5ff4c Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 3 Mar 2025 22:18:27 -0800 Subject: [PATCH] Disable diff hunks for untracked files, even w/ no newline at eof (#25980) This fixes an issue where diff hunks were shown for untracked files, but only if the files did not end with a newline. Release Notes: - N/A --- crates/buffer_diff/src/buffer_diff.rs | 31 ++++++++++--------- crates/editor/src/editor.rs | 27 +++++++--------- crates/multi_buffer/src/multi_buffer.rs | 15 +++------ crates/multi_buffer/src/multi_buffer_tests.rs | 2 +- 4 files changed, 34 insertions(+), 41 deletions(-) diff --git a/crates/buffer_diff/src/buffer_diff.rs b/crates/buffer_diff/src/buffer_diff.rs index 84423255358ffe261e877124c573630b878ff9fe..837d50899c9d8be4951e104fc2556df1b770eab7 100644 --- a/crates/buffer_diff/src/buffer_diff.rs +++ b/crates/buffer_diff/src/buffer_diff.rs @@ -56,8 +56,8 @@ pub enum DiffHunkSecondaryStatus { /// A diff hunk resolved to rows in the buffer. #[derive(Debug, Clone, PartialEq, Eq)] pub struct DiffHunk { - /// The buffer range, expressed in terms of rows. - pub row_range: Range, + /// The buffer range as points. + pub range: Range, /// The range in the buffer to which this hunk corresponds. pub buffer_range: Range, /// The range in the buffer's diff base text to which this hunk corresponds. @@ -362,6 +362,7 @@ impl BufferDiffInner { pending_hunks = secondary.pending_hunks.clone(); } + let max_point = buffer.max_point(); let mut summaries = buffer.summaries_for_anchors_with_payload::(anchor_iter); iter::from_fn(move || loop { let (start_point, (start_anchor, start_base)) = summaries.next()?; @@ -371,7 +372,7 @@ impl BufferDiffInner { continue; } - if end_point.column > 0 { + if end_point.column > 0 && end_point < max_point { end_point.row += 1; end_point.column = 0; end_anchor = buffer.anchor_before(end_point); @@ -416,7 +417,7 @@ impl BufferDiffInner { } return Some(DiffHunk { - row_range: start_point.row..end_point.row, + range: start_point..end_point, diff_base_byte_range: start_base..end_base, buffer_range: start_anchor..end_anchor, secondary_status, @@ -442,14 +443,9 @@ impl BufferDiffInner { let hunk = cursor.item()?; let range = hunk.buffer_range.to_point(buffer); - let end_row = if range.end.column > 0 { - range.end.row + 1 - } else { - range.end.row - }; Some(DiffHunk { - row_range: range.start.row..end_row, + range, diff_base_byte_range: hunk.diff_base_byte_range.clone(), buffer_range: hunk.buffer_range.clone(), // The secondary status is not used by callers of this method. @@ -1136,12 +1132,10 @@ pub fn assert_hunks( let actual_hunks = diff_hunks .map(|hunk| { ( - hunk.row_range.clone(), + hunk.range.clone(), &diff_base[hunk.diff_base_byte_range.clone()], buffer - .text_for_range( - Point::new(hunk.row_range.start, 0)..Point::new(hunk.row_range.end, 0), - ) + .text_for_range(hunk.range.clone()) .collect::(), hunk.status(), ) @@ -1150,7 +1144,14 @@ pub fn assert_hunks( let expected_hunks: Vec<_> = expected_hunks .iter() - .map(|(r, s, h, status)| (r.clone(), *s, h.to_string(), *status)) + .map(|(r, old_text, new_text, status)| { + ( + Point::new(r.start, 0)..Point::new(r.end, 0), + *old_text, + new_text.to_string(), + *status, + ) + }) .collect(); assert_eq!(actual_hunks, expected_hunks); diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 240117e2504b93658c285288b8419be52f40beee..965e8a1123ab9f00d31bfc16e2ce19d1a1582e48 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -13733,7 +13733,7 @@ impl Editor { buffer_range: hunk.buffer_range, diff_base_byte_range: hunk.diff_base_byte_range, secondary_status: hunk.secondary_status, - row_range: 0..0, // unused + range: Point::zero()..Point::zero(), // unused }) .collect::>(), &buffer_snapshot, @@ -16041,9 +16041,9 @@ impl Editor { if let Some(buffer) = multi_buffer.buffer(buffer_id) { buffer.update(cx, |buffer, cx| { buffer.edit( - changes.into_iter().map(|(range, text)| { - (range, text.to_string().map(Arc::::from)) - }), + changes + .into_iter() + .map(|(range, text)| (range, text.to_string())), None, cx, ); @@ -17161,17 +17161,14 @@ impl EditorSnapshot { for hunk in self.buffer_snapshot.diff_hunks_in_range( Point::new(query_rows.start.0, 0)..Point::new(query_rows.end.0, 0), ) { - // Deleted hunk is an empty row range, no caret can be placed there and Zed allows to revert it - // when the caret is just above or just below the deleted hunk. - let allow_adjacent = hunk.status().is_deleted(); - let related_to_selection = if allow_adjacent { - hunk.row_range.overlaps(&query_rows) - || hunk.row_range.start == query_rows.end - || hunk.row_range.end == query_rows.start - } else { - hunk.row_range.overlaps(&query_rows) - }; - if related_to_selection { + // Include deleted hunks that are adjacent to the query range, because + // otherwise they would be missed. + let mut intersects_range = hunk.row_range.overlaps(&query_rows); + if hunk.status().is_deleted() { + intersects_range |= hunk.row_range.start == query_rows.end; + intersects_range |= hunk.row_range.end == query_rows.start; + } + if intersects_range { if !processed_buffer_rows .entry(hunk.buffer_id) .or_default() diff --git a/crates/multi_buffer/src/multi_buffer.rs b/crates/multi_buffer/src/multi_buffer.rs index d789546a62d65d23b0fef7bb1752a0aec79c1fdf..964342ba1bd73d143139b5cc0f1e9248af02cc07 100644 --- a/crates/multi_buffer/src/multi_buffer.rs +++ b/crates/multi_buffer/src/multi_buffer.rs @@ -3498,17 +3498,12 @@ impl MultiBufferSnapshot { if hunk.is_created_file() && !self.all_diff_hunks_expanded { return None; } - Some(( - Point::new(hunk.row_range.start, 0)..Point::new(hunk.row_range.end, 0), - hunk, - )) + Some((hunk.range.clone(), hunk)) }), ) }) .filter_map(move |(range, hunk, excerpt)| { - if range.start != range.end - && range.end == query_range.start - && !hunk.row_range.is_empty() + if range.start != range.end && range.end == query_range.start && !hunk.range.is_empty() { return None; } @@ -3841,12 +3836,12 @@ impl MultiBufferSnapshot { &excerpt.buffer, ) { let hunk_range = hunk.buffer_range.to_offset(&excerpt.buffer); - if hunk.row_range.end >= buffer_end_row { + if hunk.range.end >= Point::new(buffer_end_row, 0) { continue; } - let hunk_start = Point::new(hunk.row_range.start, 0); - let hunk_end = Point::new(hunk.row_range.end, 0); + let hunk_start = hunk.range.start; + let hunk_end = hunk.range.end; cursor.seek_to_buffer_position_in_current_excerpt(&DimensionPair { key: hunk_range.start, diff --git a/crates/multi_buffer/src/multi_buffer_tests.rs b/crates/multi_buffer/src/multi_buffer_tests.rs index 194a1758b2d77a236a6672edc181d8b803c03441..d0e34e198074182f4583275296f9a18dcfcbf8aa 100644 --- a/crates/multi_buffer/src/multi_buffer_tests.rs +++ b/crates/multi_buffer/src/multi_buffer_tests.rs @@ -2274,7 +2274,7 @@ impl ReferenceMultibuffer { } if !hunk.buffer_range.start.is_valid(&buffer) { - log::trace!("skipping hunk with deleted start: {:?}", hunk.row_range); + log::trace!("skipping hunk with deleted start: {:?}", hunk.range); continue; }