editor: Correctly handle blocks spanning more than 128 rows (#42172)

Release Notes:

- Fixed block rendering for blocks spanning more than 128 rows
This commit is contained in:
Lukas Wirth
2025-11-07 08:46:57 +00:00
committed by GitHub
parent f89bb2f0d2
commit d4ec55b183
3 changed files with 38 additions and 23 deletions
+17 -16
View File
@@ -25,29 +25,25 @@ mod crease_map;
mod custom_highlights;
mod fold_map;
mod inlay_map;
pub(crate) mod invisibles;
mod invisibles;
mod tab_map;
mod wrap_map;
use crate::{
EditorStyle, RowExt, hover_links::InlayHighlight, inlays::Inlay, movement::TextLayoutDetails,
};
pub use crate::display_map::{fold_map::FoldMap, inlay_map::InlayMap, tab_map::TabMap};
pub use block_map::{
Block, BlockChunks as DisplayChunks, BlockContext, BlockId, BlockMap, BlockPlacement,
BlockPoint, BlockProperties, BlockRows, BlockStyle, CustomBlockId, EditorMargins, RenderBlock,
StickyHeaderExcerpt,
};
use block_map::{BlockRow, BlockSnapshot};
use collections::{HashMap, HashSet};
pub use crease_map::*;
use fold_map::FoldSnapshot;
pub use fold_map::{
ChunkRenderer, ChunkRendererContext, ChunkRendererId, Fold, FoldId, FoldPlaceholder, FoldPoint,
};
use gpui::{App, Context, Entity, Font, HighlightStyle, LineLayout, Pixels, UnderlineStyle};
use inlay_map::InlaySnapshot;
pub use inlay_map::{InlayOffset, InlayPoint};
pub use invisibles::{is_invisible, replacement};
use collections::{HashMap, HashSet};
use gpui::{App, Context, Entity, Font, HighlightStyle, LineLayout, Pixels, UnderlineStyle};
use language::{
OffsetUtf16, Point, Subscription as BufferSubscription, language_settings::language_settings,
};
@@ -58,6 +54,10 @@ use multi_buffer::{
use project::InlayId;
use project::project_settings::DiagnosticSeverity;
use serde::Deserialize;
use sum_tree::{Bias, TreeMap};
use text::{BufferId, LineIndent};
use ui::{SharedString, px};
use unicode_segmentation::UnicodeSegmentation;
use std::{
any::TypeId,
@@ -68,14 +68,15 @@ use std::{
ops::{Add, Range, Sub},
sync::Arc,
};
use sum_tree::{Bias, TreeMap};
use tab_map::TabSnapshot;
use text::{BufferId, LineIndent};
use ui::{SharedString, px};
use unicode_segmentation::UnicodeSegmentation;
use wrap_map::{WrapMap, WrapSnapshot};
pub use crate::display_map::{fold_map::FoldMap, inlay_map::InlayMap, tab_map::TabMap};
use crate::{
EditorStyle, RowExt, hover_links::InlayHighlight, inlays::Inlay, movement::TextLayoutDetails,
};
use block_map::{BlockRow, BlockSnapshot};
use fold_map::FoldSnapshot;
use inlay_map::InlaySnapshot;
use tab_map::TabSnapshot;
use wrap_map::{WrapMap, WrapSnapshot};
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum FoldStatus {
+20 -6
View File
@@ -453,6 +453,7 @@ pub struct BlockChunks<'a> {
input_chunk: Chunk<'a>,
output_row: BlockRow,
max_output_row: BlockRow,
line_count_overflow: RowDelta,
masked: bool,
}
@@ -1352,6 +1353,7 @@ impl BlockSnapshot {
input_chunk: Default::default(),
transforms: cursor,
output_row: rows.start,
line_count_overflow: RowDelta(0),
max_output_row,
masked,
}
@@ -1743,6 +1745,17 @@ impl<'a> Iterator for BlockChunks<'a> {
return None;
}
if self.line_count_overflow > RowDelta(0) {
let lines = self.line_count_overflow.0.min(u128::BITS);
self.line_count_overflow.0 -= lines;
self.output_row += RowDelta(lines);
return Some(Chunk {
text: unsafe { std::str::from_utf8_unchecked(&NEWLINES[..lines as usize]) },
chars: 1u128.unbounded_shl(lines).wrapping_sub(1),
..Default::default()
});
}
let transform = self.transforms.item()?;
if transform.block.is_some() {
let block_start = self.transforms.start().0;
@@ -1754,13 +1767,14 @@ impl<'a> Iterator for BlockChunks<'a> {
let start_in_block = self.output_row - block_start;
let end_in_block = cmp::min(self.max_output_row, block_end) - block_start;
// todo: We need to split the chunk here instead of taking min
let line_count = cmp::min(end_in_block - start_in_block, RowDelta(u128::BITS));
self.output_row += line_count;
let line_count = end_in_block - start_in_block;
let lines = RowDelta(line_count.0.min(u128::BITS));
self.line_count_overflow = line_count - lines;
self.output_row += lines;
return Some(Chunk {
text: unsafe { std::str::from_utf8_unchecked(&NEWLINES[..line_count.0 as usize]) },
chars: 1u128.unbounded_shl(line_count.0) - 1,
text: unsafe { std::str::from_utf8_unchecked(&NEWLINES[..lines.0 as usize]) },
chars: 1u128.unbounded_shl(lines.0).wrapping_sub(1),
..Default::default()
});
}
@@ -3042,7 +3056,7 @@ mod tests {
_ => BlockPlacement::Below(buffer.anchor_after(offset)),
};
let height = rng.random_range(min_height..5);
let height = rng.random_range(min_height..512);
BlockProperties {
style: BlockStyle::Fixed,
placement,
+1 -1
View File
@@ -1,7 +1,7 @@
use crate::{
ActiveDiagnostic, Anchor, AnchorRangeExt, DisplayPoint, DisplayRow, Editor, EditorSettings,
EditorSnapshot, GlobalDiagnosticRenderer, Hover,
display_map::{InlayOffset, ToDisplayPoint, invisibles::is_invisible},
display_map::{InlayOffset, ToDisplayPoint, is_invisible},
hover_links::{InlayHighlight, RangeInEditor},
movement::TextLayoutDetails,
scroll::ScrollAmount,