From 1e1b637b5084a6424eace8f6d3efba1bc25579d4 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 17 Feb 2025 11:20:19 -0800 Subject: [PATCH] Fix handling of empty blocks in BlockMap::chunks (#25031) Closes https://github.com/zed-industries/zed/issues/23391 Release Notes: - Fixed a bug that sometimes caused incorrect syntax highlighting when deploying the inline assistant. --- crates/editor/src/display_map.rs | 32 +++++++++++++++------- crates/editor/src/display_map/block_map.rs | 15 ++++++---- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/crates/editor/src/display_map.rs b/crates/editor/src/display_map.rs index c933b04cf5..7b6181310f 100644 --- a/crates/editor/src/display_map.rs +++ b/crates/editor/src/display_map.rs @@ -2070,18 +2070,30 @@ pub mod tests { ) }); - // Insert a block in the middle of a multi-line string literal + // Insert two blocks in the middle of a multi-line string literal. + // The second block has zero height. map.update(cx, |map, cx| { map.insert_blocks( - [BlockProperties { - placement: BlockPlacement::Below( - buffer_snapshot.anchor_before(Point::new(1, 0)), - ), - height: 1, - style: BlockStyle::Sticky, - render: Arc::new(|_| div().into_any()), - priority: 0, - }], + [ + BlockProperties { + placement: BlockPlacement::Below( + buffer_snapshot.anchor_before(Point::new(1, 0)), + ), + height: 1, + style: BlockStyle::Sticky, + render: Arc::new(|_| div().into_any()), + priority: 0, + }, + BlockProperties { + placement: BlockPlacement::Below( + buffer_snapshot.anchor_before(Point::new(2, 0)), + ), + height: 0, + style: BlockStyle::Sticky, + render: Arc::new(|_| div().into_any()), + priority: 0, + }, + ], cx, ) }); diff --git a/crates/editor/src/display_map/block_map.rs b/crates/editor/src/display_map/block_map.rs index b4bf81846e..5e788821c9 100644 --- a/crates/editor/src/display_map/block_map.rs +++ b/crates/editor/src/display_map/block_map.rs @@ -1721,6 +1721,7 @@ impl BlockSnapshot { impl<'a> BlockChunks<'a> { /// Go to the next transform fn advance(&mut self) { + self.input_chunk = Chunk::default(); self.transforms.next(&()); while let Some(transform) = self.transforms.item() { if transform @@ -1748,7 +1749,6 @@ impl<'a> BlockChunks<'a> { ); self.input_chunks.seek(start_input_row..end_input_row); } - self.input_chunk = Chunk::default(); } } } @@ -1812,9 +1812,6 @@ impl<'a> Iterator for BlockChunks<'a> { let (mut prefix, suffix) = self.input_chunk.text.split_at(prefix_bytes); self.input_chunk.text = suffix; - if self.output_row == transform_end { - self.advance(); - } if self.masked { // Not great for multibyte text because to keep cursor math correct we @@ -1824,10 +1821,16 @@ impl<'a> Iterator for BlockChunks<'a> { prefix = &BULLETS[..bullet_len]; } - Some(Chunk { + let chunk = Chunk { text: prefix, ..self.input_chunk.clone() - }) + }; + + if self.output_row == transform_end { + self.advance(); + } + + Some(chunk) } }