Get every test passing except random tabs

This commit is contained in:
Anthony 2025-06-07 01:38:04 -04:00
parent 516212a072
commit 118585d133

View file

@ -2,11 +2,11 @@ use super::{
Highlights, Highlights,
fold_map::{self, Chunk, FoldChunks, FoldEdit, FoldPoint, FoldSnapshot}, fold_map::{self, Chunk, FoldChunks, FoldEdit, FoldPoint, FoldSnapshot},
}; };
use language::Point; use language::Point;
use multi_buffer::MultiBufferSnapshot; use multi_buffer::MultiBufferSnapshot;
use std::{cmp, mem, num::NonZeroU32, ops::Range}; use std::{cmp, mem, num::NonZeroU32, ops::Range};
use sum_tree::Bias; use sum_tree::Bias;
use util::debug_panic;
const MAX_EXPANSION_COLUMN: u32 = 256; const MAX_EXPANSION_COLUMN: u32 = 256;
@ -310,6 +310,7 @@ impl TabSnapshot {
let chunks = self let chunks = self
.fold_snapshot .fold_snapshot
.chunks_at(FoldPoint::new(output.row(), 0)); .chunks_at(FoldPoint::new(output.row(), 0));
let tab_cursor = TabStopCursor::new(chunks); let tab_cursor = TabStopCursor::new(chunks);
let expanded = output.column(); let expanded = output.column();
let (collapsed, expanded_char_column, to_next_stop) = let (collapsed, expanded_char_column, to_next_stop) =
@ -363,44 +364,44 @@ impl TabSnapshot {
fn collapse_tabs(&self, mut cursor: TabStopCursor, column: u32, bias: Bias) -> (u32, u32, u32) { fn collapse_tabs(&self, mut cursor: TabStopCursor, column: u32, bias: Bias) -> (u32, u32, u32) {
let tab_size = self.tab_size.get(); let tab_size = self.tab_size.get();
let mut collapsed_column = column; let mut collapsed_column = column;
let mut seek_target = column;
let mut tab_count = 0; let mut tab_count = 0;
let mut expanded_tab_len = 0; let mut expanded_tab_len = 0;
dbg!(collapsed_column); while let Some(tab_stop) = cursor.seek(seek_target) {
while let Some(tab_stop) = cursor.seek(collapsed_column) {
// Calculate how much we want to expand this tab stop (into spaces) // Calculate how much we want to expand this tab stop (into spaces)
let mut expanded_chars = tab_stop.char_offset - tab_count + expanded_tab_len; let expanded_chars_old = tab_stop.char_offset - tab_count + expanded_tab_len;
let tab_len = tab_size - ((expanded_chars - 1) % tab_size); let tab_len = tab_size - ((expanded_chars_old - 1) % tab_size);
// Increment tab count // Increment tab count
tab_count += 1; tab_count += 1;
// The count of how many spaces we've added to this line in place of tab bytes // The count of how many spaces we've added to this line in place of tab bytes
expanded_tab_len += dbg!(tab_len); expanded_tab_len += tab_len;
// The count of bytes at this point in the iteration while considering tab_count and previous expansions // The count of bytes at this point in the iteration while considering tab_count and previous expansions
let expanded_bytes = tab_stop.byte_offset - tab_count + expanded_tab_len; let expanded_bytes = tab_stop.byte_offset - tab_count + expanded_tab_len;
// Did we expand past the search target? // Did we expand past the search target?
if expanded_bytes > column { if expanded_bytes > column {
let mut expanded_chars = tab_stop.char_offset - tab_count + expanded_tab_len;
// We expanded past the search target, so need to account for the offshoot // We expanded past the search target, so need to account for the offshoot
expanded_chars -= expanded_bytes - column; expanded_chars -= expanded_bytes - column;
dbg!(expanded_bytes);
return match bias { return match bias {
Bias::Left => ( Bias::Left => (
cursor.byte_offset(), cursor.byte_offset() - 1,
expanded_chars, expanded_chars,
expanded_bytes - column, expanded_bytes - column,
), ),
Bias::Right => (cursor.byte_offset() + 1, expanded_chars, 0), Bias::Right => (cursor.byte_offset(), expanded_chars, 0),
}; };
} else { } else {
// otherwise we only want to move the cursor collapse column forward // otherwise we only want to move the cursor collapse column forward
collapsed_column = collapsed_column - tab_len + 1; collapsed_column = collapsed_column - tab_len + 1;
seek_target = (collapsed_column - cursor.bytes_offset)
.min(self.max_expansion_column - cursor.bytes_offset);
} }
} }
dbg!(tab_count, expanded_tab_len);
let collapsed_bytes = cursor.byte_offset(); let collapsed_bytes = cursor.byte_offset();
let expanded_bytes = cursor.byte_offset() - tab_count + expanded_tab_len; let expanded_bytes = cursor.byte_offset() - tab_count + expanded_tab_len;
dbg!(collapsed_bytes, expanded_bytes, column);
// let expanded_chars = cursor.char_offset() - tab_count + expanded_tab_len; // let expanded_chars = cursor.char_offset() - tab_count + expanded_tab_len;
( (
collapsed_bytes + column.saturating_sub(expanded_bytes), collapsed_bytes + column.saturating_sub(expanded_bytes),
@ -629,8 +630,7 @@ mod tests {
let mut expanded_bytes = 0; let mut expanded_bytes = 0;
let mut expanded_chars = 0; let mut expanded_chars = 0;
let mut collapsed_bytes = 0; let mut collapsed_bytes = 0;
let mut expanded_tab_len = 0; for c in chars {
for (i, c) in chars.enumerate() {
if expanded_bytes >= column { if expanded_bytes >= column {
break; break;
} }
@ -640,13 +640,10 @@ mod tests {
if c == '\t' { if c == '\t' {
let tab_len = tab_size - (expanded_chars % tab_size); let tab_len = tab_size - (expanded_chars % tab_size);
dbg!(tab_len);
expanded_tab_len += tab_len;
expanded_chars += tab_len; expanded_chars += tab_len;
expanded_bytes += tab_len; expanded_bytes += tab_len;
if expanded_bytes > column { if expanded_bytes > column {
expanded_chars -= expanded_bytes - column; expanded_chars -= expanded_bytes - column;
dbg!(expanded_bytes);
return match bias { return match bias {
Bias::Left => { Bias::Left => {
(collapsed_bytes, expanded_chars, expanded_bytes - column) (collapsed_bytes, expanded_chars, expanded_bytes - column)
@ -666,14 +663,6 @@ mod tests {
collapsed_bytes += c.len_utf8() as u32; collapsed_bytes += c.len_utf8() as u32;
} }
dbg!(
collapsed_bytes,
column,
expanded_bytes,
expanded_chars,
expanded_tab_len
);
dbg!("expected\n---------------\n");
( (
collapsed_bytes + column.saturating_sub(expanded_bytes), collapsed_bytes + column.saturating_sub(expanded_bytes),
@ -718,32 +707,38 @@ mod tests {
let (_, fold_snapshot) = FoldMap::new(inlay_snapshot); let (_, fold_snapshot) = FoldMap::new(inlay_snapshot);
let (_, tab_snapshot) = TabMap::new(fold_snapshot, 4.try_into().unwrap()); let (_, tab_snapshot) = TabMap::new(fold_snapshot, 4.try_into().unwrap());
let range = TabPoint::zero()..tab_snapshot.max_point(); for (ix, _) in input.char_indices() {
let range = TabPoint::new(0, ix as u32)..tab_snapshot.max_point();
assert_eq!( assert_eq!(
tab_snapshot.test_to_fold_point(range.start, Bias::Left), tab_snapshot.test_to_fold_point(range.start, Bias::Left),
tab_snapshot.to_fold_point(range.start, Bias::Left) tab_snapshot.to_fold_point(range.start, Bias::Left),
); "Failed with tab_point at column {ix}"
assert_eq!( );
tab_snapshot.test_to_fold_point(range.start, Bias::Right), assert_eq!(
tab_snapshot.to_fold_point(range.start, Bias::Right) tab_snapshot.test_to_fold_point(range.start, Bias::Right),
); tab_snapshot.to_fold_point(range.start, Bias::Right),
"Failed with tab_point at column {ix}"
);
assert_eq!( assert_eq!(
tab_snapshot.test_to_fold_point(range.end, Bias::Left), tab_snapshot.test_to_fold_point(range.end, Bias::Left),
tab_snapshot.to_fold_point(range.end, Bias::Left) tab_snapshot.to_fold_point(range.end, Bias::Left),
); "Failed with tab_point at column {ix}"
assert_eq!( );
tab_snapshot.test_to_fold_point(range.end, Bias::Right), assert_eq!(
tab_snapshot.to_fold_point(range.end, Bias::Right) tab_snapshot.test_to_fold_point(range.end, Bias::Right),
); tab_snapshot.to_fold_point(range.end, Bias::Right),
"Failed with tab_point at column {ix}"
);
}
} }
#[gpui::test(iterations = 100)] #[gpui::test(iterations = 100)]
fn test_collapse_tabs_random(cx: &mut gpui::App, mut rng: StdRng) { fn test_collapse_tabs_random(cx: &mut gpui::App, mut rng: StdRng) {
// Generate random input string with up to 200 characters including tabs // Generate random input string with up to 200 characters including tabs
// to stay within the MAX_EXPANSION_COLUMN limit of 256 // to stay within the MAX_EXPANSION_COLUMN limit of 256
let len = rng.gen_range(0..=200); let len = rng.gen_range(0..=2048);
let mut input = String::with_capacity(len); let mut input = String::with_capacity(len);
for _ in 0..len { for _ in 0..len {
@ -769,33 +764,35 @@ mod tests {
let (_, fold_snapshot) = FoldMap::new(inlay_snapshot); let (_, fold_snapshot) = FoldMap::new(inlay_snapshot);
let (_, tab_snapshot) = TabMap::new(fold_snapshot, 4.try_into().unwrap()); let (_, tab_snapshot) = TabMap::new(fold_snapshot, 4.try_into().unwrap());
let range = TabPoint::zero()..tab_snapshot.max_point(); for (ix, _) in input.char_indices() {
let range = TabPoint::new(0, ix as u32)..tab_snapshot.max_point();
assert_eq!( assert_eq!(
tab_snapshot.test_to_fold_point(range.start, Bias::Left), tab_snapshot.test_to_fold_point(range.start, Bias::Left),
tab_snapshot.to_fold_point(range.start, Bias::Left), tab_snapshot.to_fold_point(range.start, Bias::Left),
"Failed with input: {}", "Failed with input: {}, with idx: {ix}",
input input
); );
assert_eq!( assert_eq!(
tab_snapshot.test_to_fold_point(range.start, Bias::Right), tab_snapshot.test_to_fold_point(range.start, Bias::Right),
tab_snapshot.to_fold_point(range.start, Bias::Right), tab_snapshot.to_fold_point(range.start, Bias::Right),
"Failed with input: {}", "Failed with input: {}, with idx: {ix}",
input input
); );
assert_eq!( assert_eq!(
tab_snapshot.test_to_fold_point(range.end, Bias::Left), tab_snapshot.test_to_fold_point(range.end, Bias::Left),
tab_snapshot.to_fold_point(range.end, Bias::Left), tab_snapshot.to_fold_point(range.end, Bias::Left),
"Failed with input: {}", "Failed with input: {}, with idx: {ix}",
input input
); );
assert_eq!( assert_eq!(
tab_snapshot.test_to_fold_point(range.end, Bias::Right), tab_snapshot.test_to_fold_point(range.end, Bias::Right),
tab_snapshot.to_fold_point(range.end, Bias::Right), tab_snapshot.to_fold_point(range.end, Bias::Right),
"Failed with input: {}", "Failed with input: {}, with idx: {ix}",
input input
); );
}
} }
#[gpui::test] #[gpui::test]
@ -1094,8 +1091,13 @@ mod tests {
let len = rng.gen_range(0..=2048); let len = rng.gen_range(0..=2048);
let mut input = String::with_capacity(len); let mut input = String::with_capacity(len);
for _ in 0..len { let mut skip_tabs = rng.gen_bool(0.10);
if rng.gen_bool(0.15) { for idx in 0..len {
if idx % 128 == 0 {
skip_tabs = rng.gen_bool(0.10);
}
if rng.gen_bool(0.15) && !skip_tabs {
// 15% chance of inserting a tab // 15% chance of inserting a tab
input.push('\t'); input.push('\t');
} else { } else {
@ -1247,6 +1249,7 @@ impl<'a> TabStopCursor<'a> {
self.end_of_chunk = Some(overshoot); self.end_of_chunk = Some(overshoot);
return None; return None;
} }
self.bytes_offset += chunk.text.len() as u32;
continue; continue;
} }