diff --git a/crates/editor/src/display_map.rs b/crates/editor/src/display_map.rs index 5f86b46843..a37b4abe38 100644 --- a/crates/editor/src/display_map.rs +++ b/crates/editor/src/display_map.rs @@ -1911,6 +1911,67 @@ pub mod tests { ); } + #[gpui::test] + fn test_inlays_with_newlines_after_blocks(cx: &mut gpui::TestAppContext) { + cx.update(|cx| init_test(cx, |_| {})); + + let buffer = cx.new(|cx| Buffer::local("a", cx)); + let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx)); + let buffer_snapshot = buffer.read_with(cx, |buffer, cx| buffer.snapshot(cx)); + + let font_size = px(14.0); + let map = cx.new(|cx| { + DisplayMap::new( + buffer.clone(), + font("Helvetica"), + font_size, + None, + true, + 1, + 1, + 1, + FoldPlaceholder::test(), + cx, + ) + }); + + map.update(cx, |map, cx| { + map.insert_blocks( + [BlockProperties { + placement: BlockPlacement::Above( + buffer_snapshot.anchor_before(Point::new(0, 0)), + ), + height: 2, + style: BlockStyle::Sticky, + render: Arc::new(|_| div().into_any()), + priority: 0, + }], + cx, + ); + }); + map.update(cx, |m, cx| assert_eq!(m.snapshot(cx).text(), "\n\na")); + + map.update(cx, |map, cx| { + map.splice_inlays( + &[], + vec![Inlay { + id: InlayId::InlineCompletion(0), + position: buffer_snapshot.anchor_after(0), + text: "\n".into(), + }], + cx, + ); + }); + map.update(cx, |m, cx| assert_eq!(m.snapshot(cx).text(), "\n\n\na")); + + // Regression test: updating the display map does not crash when a + // block is immediately followed by a multi-line inlay. + buffer.update(cx, |buffer, cx| { + buffer.edit([(1..1, "b")], None, cx); + }); + map.update(cx, |m, cx| assert_eq!(m.snapshot(cx).text(), "\n\n\nab")); + } + #[gpui::test] async fn test_chunks(cx: &mut gpui::TestAppContext) { let text = r#" diff --git a/crates/editor/src/display_map/block_map.rs b/crates/editor/src/display_map/block_map.rs index 5e788821c9..3a8de4fcc7 100644 --- a/crates/editor/src/display_map/block_map.rs +++ b/crates/editor/src/display_map/block_map.rs @@ -638,10 +638,13 @@ impl BlockMap { self.custom_blocks[start_block_ix..end_block_ix] .iter() .filter_map(|block| { - Some(( - block.placement.to_wrap_row(wrap_snapshot)?, - Block::Custom(block.clone()), - )) + let placement = block.placement.to_wrap_row(wrap_snapshot)?; + if let BlockPlacement::Above(row) = placement { + if row < new_start { + return None; + } + } + Some((placement, Block::Custom(block.clone()))) }), );