Fix folds_in_range and add a test for it

With the current ordering, a linear scan is required in order to
determine which folds intersect the given range.
This commit is contained in:
Antonio Scandurra
2021-05-04 11:24:33 +02:00
parent aa2a2ececf
commit a0428667d0
3 changed files with 61 additions and 49 deletions
+44 -20
View File
@@ -89,31 +89,20 @@ impl FoldMap {
DisplayPoint(self.transforms.summary().display.rightmost_point)
}
pub fn folds_in_range<T>(&self, range: Range<T>, app: &AppContext) -> Result<&[Range<Anchor>]>
pub fn folds_in_range<'a, T>(
&'a self,
range: Range<T>,
app: &'a AppContext,
) -> Result<impl Iterator<Item = &'a Range<Anchor>>>
where
T: ToOffset,
{
let buffer = self.buffer.read(app);
let range = buffer.anchor_before(range.start)?..buffer.anchor_before(range.end)?;
let mut start_ix = find_insertion_index(&self.folds, |probe| probe.cmp(&range, buffer))?;
let mut end_ix = start_ix;
for fold in self.folds[..start_ix].iter().rev() {
if fold.end.cmp(&range.start, buffer)? == Ordering::Greater {
start_ix -= 1;
} else {
break;
}
}
for fold in &self.folds[end_ix..] {
if range.end.cmp(&fold.start, buffer)? == Ordering::Greater {
end_ix += 1;
} else {
break;
}
}
Ok(&self.folds[start_ix..end_ix])
Ok(self.folds.iter().filter(move |fold| {
range.start.cmp(&fold.end, buffer).unwrap() == Ordering::Less
&& range.end.cmp(&fold.start, buffer).unwrap() == Ordering::Greater
}))
}
pub fn fold<T: ToOffset>(
@@ -500,6 +489,7 @@ impl<'a> Dimension<'a, TransformSummary> for usize {
mod tests {
use super::*;
use crate::test::sample_text;
use buffer::ToPoint;
use gpui::App;
#[test]
@@ -645,6 +635,40 @@ mod tests {
});
}
#[test]
fn test_folds_in_range() {
App::test((), |app| {
let buffer = app.add_model(|ctx| Buffer::new(0, sample_text(5, 6), ctx));
let mut map = FoldMap::new(buffer.clone(), app.as_ref());
let buffer = buffer.read(app);
map.fold(
vec![
Point::new(0, 2)..Point::new(2, 2),
Point::new(0, 4)..Point::new(1, 0),
Point::new(1, 2)..Point::new(3, 2),
Point::new(3, 1)..Point::new(4, 1),
],
app.as_ref(),
)
.unwrap();
let fold_ranges = map
.folds_in_range(Point::new(1, 0)..Point::new(1, 3), app.as_ref())
.unwrap()
.map(|fold| {
fold.start.to_point(buffer).unwrap()..fold.end.to_point(buffer).unwrap()
})
.collect::<Vec<_>>();
assert_eq!(
fold_ranges,
vec![
Point::new(0, 2)..Point::new(2, 2),
Point::new(1, 2)..Point::new(3, 2)
]
);
});
}
#[test]
fn test_random_folds() {
use crate::editor::ToPoint;
+5 -1
View File
@@ -34,7 +34,11 @@ impl DisplayMap {
}
}
pub fn folds_in_range<T>(&self, range: Range<T>, app: &AppContext) -> Result<&[Range<Anchor>]>
pub fn folds_in_range<'a, T>(
&'a self,
range: Range<T>,
app: &'a AppContext,
) -> Result<impl Iterator<Item = &'a Range<Anchor>>>
where
T: ToOffset,
{