diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 0a5649bdb24bf141da369e7481d3a0b9d7ec5bdb..8eb18f6c3bfa0f21f756243c0e5b1c6984de6253 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -4864,7 +4864,7 @@ impl Editor { let text = match &self.active_inline_completion.as_ref()?.completion { InlineCompletion::Edit(edits) => { - inline_completion_edit_text(&editor_snapshot, edits, cx) + inline_completion_edit_text(&editor_snapshot, edits, true, cx) } InlineCompletion::Move(target) => { let target_point = @@ -14630,6 +14630,7 @@ pub fn diagnostic_block_renderer( fn inline_completion_edit_text( editor_snapshot: &EditorSnapshot, edits: &Vec<(Range, String)>, + include_deletions: bool, cx: &WindowContext, ) -> InlineCompletionText { let edit_start = edits @@ -14653,12 +14654,24 @@ fn inline_completion_edit_text( offset = old_offset_range.end; let start = text.len(); - text.push_str(new_text); + let color = if include_deletions && new_text.is_empty() { + text.extend( + editor_snapshot + .buffer_snapshot + .chunks(old_offset_range.start..offset, false) + .map(|chunk| chunk.text), + ); + cx.theme().status().deleted_background + } else { + text.push_str(new_text); + cx.theme().status().created_background + }; let end = text.len(); + highlights.push(( start..end, HighlightStyle { - background_color: Some(cx.theme().status().created_background), + background_color: Some(color), ..Default::default() }, )); diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index 47bee57b58fa7c1faecd076dd9879a4d2e6301f5..4882d8c217dfd17853a06232f5a64ec526b6a022 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -14367,7 +14367,7 @@ async fn test_multi_buffer_with_single_excerpt_folding(cx: &mut gpui::TestAppCon fn test_inline_completion_text(cx: &mut TestAppContext) { init_test(cx, |_| {}); - // Test case 1: Simple insertion + // Simple insertion { let window = cx.add_window(|cx| { let buffer = MultiBuffer::build_simple("Hello, world!", cx); @@ -14383,7 +14383,7 @@ fn test_inline_completion_text(cx: &mut TestAppContext) { let edits = vec![(edit_range, " beautiful".to_string())]; let InlineCompletionText::Edit { text, highlights } = - inline_completion_edit_text(&snapshot, &edits, cx) + inline_completion_edit_text(&snapshot, &edits, false, cx) else { panic!("Failed to generate inline completion text"); }; @@ -14399,7 +14399,7 @@ fn test_inline_completion_text(cx: &mut TestAppContext) { .unwrap(); } - // Test case 2: Replacement + // Replacement { let window = cx.add_window(|cx| { let buffer = MultiBuffer::build_simple("This is a test.", cx); @@ -14417,7 +14417,7 @@ fn test_inline_completion_text(cx: &mut TestAppContext) { )]; let InlineCompletionText::Edit { text, highlights } = - inline_completion_edit_text(&snapshot, &edits, cx) + inline_completion_edit_text(&snapshot, &edits, false, cx) else { panic!("Failed to generate inline completion text"); }; @@ -14433,7 +14433,7 @@ fn test_inline_completion_text(cx: &mut TestAppContext) { .unwrap(); } - // Test case 3: Multiple edits + // Multiple edits { let window = cx.add_window(|cx| { let buffer = MultiBuffer::build_simple("Hello, world!", cx); @@ -14458,7 +14458,7 @@ fn test_inline_completion_text(cx: &mut TestAppContext) { ]; let InlineCompletionText::Edit { text, highlights } = - inline_completion_edit_text(&snapshot, &edits, cx) + inline_completion_edit_text(&snapshot, &edits, false, cx) else { panic!("Failed to generate inline completion text"); }; @@ -14479,7 +14479,7 @@ fn test_inline_completion_text(cx: &mut TestAppContext) { .unwrap(); } - // Test case 4: Multiple lines with edits + // Multiple lines with edits { let window = cx.add_window(|cx| { let buffer = @@ -14510,7 +14510,7 @@ fn test_inline_completion_text(cx: &mut TestAppContext) { ]; let InlineCompletionText::Edit { text, highlights } = - inline_completion_edit_text(&snapshot, &edits, cx) + inline_completion_edit_text(&snapshot, &edits, false, cx) else { panic!("Failed to generate inline completion text"); }; @@ -14532,6 +14532,75 @@ fn test_inline_completion_text(cx: &mut TestAppContext) { } } +#[gpui::test] +fn test_inline_completion_text_with_deletions(cx: &mut TestAppContext) { + init_test(cx, |_| {}); + + // Deletion + { + let window = cx.add_window(|cx| { + let buffer = MultiBuffer::build_simple("Hello, world!", cx); + Editor::new(EditorMode::Full, buffer, None, true, cx) + }); + let cx = &mut VisualTestContext::from_window(*window, cx); + + window + .update(cx, |editor, cx| { + let snapshot = editor.snapshot(cx); + let edit_range = snapshot.buffer_snapshot.anchor_after(Point::new(0, 5)) + ..snapshot.buffer_snapshot.anchor_before(Point::new(0, 11)); + let edits = vec![(edit_range, "".to_string())]; + + let InlineCompletionText::Edit { text, highlights } = + inline_completion_edit_text(&snapshot, &edits, true, cx) + else { + panic!("Failed to generate inline completion text"); + }; + + assert_eq!(text, "Hello, world!"); + assert_eq!(highlights.len(), 1); + assert_eq!(highlights[0].0, 5..11); + assert_eq!( + highlights[0].1.background_color, + Some(cx.theme().status().deleted_background) + ); + }) + .unwrap(); + } + + // Insertion + { + let window = cx.add_window(|cx| { + let buffer = MultiBuffer::build_simple("Hello, world!", cx); + Editor::new(EditorMode::Full, buffer, None, true, cx) + }); + let cx = &mut VisualTestContext::from_window(*window, cx); + + window + .update(cx, |editor, cx| { + let snapshot = editor.snapshot(cx); + let edit_range = snapshot.buffer_snapshot.anchor_after(Point::new(0, 6)) + ..snapshot.buffer_snapshot.anchor_before(Point::new(0, 6)); + let edits = vec![(edit_range, " digital".to_string())]; + + let InlineCompletionText::Edit { text, highlights } = + inline_completion_edit_text(&snapshot, &edits, true, cx) + else { + panic!("Failed to generate inline completion text"); + }; + + assert_eq!(text, "Hello, digital world!"); + assert_eq!(highlights.len(), 1); + assert_eq!(highlights[0].0, 6..14); + assert_eq!( + highlights[0].1.background_color, + Some(cx.theme().status().created_background) + ); + }) + .unwrap(); + } +} + fn empty_range(row: usize, column: usize) -> Range { let point = DisplayPoint::new(DisplayRow(row as u32), column as u32); point..point diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 1daaacbcb389fb25d48d79ec3e570a2a673e1c4b..343102b99edf2a361e9a2286f1088072d2e04369 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -3221,7 +3221,7 @@ impl EditorElement { } let crate::InlineCompletionText::Edit { text, highlights } = - crate::inline_completion_edit_text(editor_snapshot, edits, cx) + crate::inline_completion_edit_text(editor_snapshot, edits, false, cx) else { return None; };