Add test for go-to hunk and fix discovered bugs

This commit is contained in:
Julia 2022-10-28 15:07:53 -04:00
parent ae2021e073
commit 8361b4d47a
8 changed files with 145 additions and 72 deletions

View file

@ -5258,6 +5258,7 @@ impl Editor {
this: &mut Editor, this: &mut Editor,
snapshot: &DisplaySnapshot, snapshot: &DisplaySnapshot,
initial_point: Point, initial_point: Point,
is_wrapped: bool,
direction: Direction, direction: Direction,
cx: &mut ViewContext<Editor>, cx: &mut ViewContext<Editor>,
) -> bool { ) -> bool {
@ -5274,12 +5275,18 @@ impl Editor {
let display_point = initial_point.to_display_point(snapshot); let display_point = initial_point.to_display_point(snapshot);
let mut hunks = hunks let mut hunks = hunks
.map(|hunk| diff_hunk_to_display(hunk, &snapshot)) .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
.skip_while(|hunk| hunk.display_row_range().contains(&display_point.row())) .skip_while(|hunk| {
if is_wrapped {
false
} else {
hunk.contains_display_row(display_point.row())
}
})
.dedup(); .dedup();
if let Some(hunk) = hunks.next() { if let Some(hunk) = hunks.next() {
this.change_selections(Some(Autoscroll::Center), cx, |s| { this.change_selections(Some(Autoscroll::Center), cx, |s| {
let row = hunk.display_row_range().start; let row = hunk.start_display_row();
let point = DisplayPoint::new(row, 0); let point = DisplayPoint::new(row, 0);
s.select_display_ranges([point..point]); s.select_display_ranges([point..point]);
}); });
@ -5290,12 +5297,12 @@ impl Editor {
} }
} }
if !seek_in_direction(self, &snapshot, selection.head(), direction, cx) { if !seek_in_direction(self, &snapshot, selection.head(), false, direction, cx) {
let wrapped_point = match direction { let wrapped_point = match direction {
Direction::Next => Point::zero(), Direction::Next => Point::zero(),
Direction::Prev => snapshot.buffer_snapshot.max_point(), Direction::Prev => snapshot.buffer_snapshot.max_point(),
}; };
seek_in_direction(self, &snapshot, wrapped_point, direction, cx); seek_in_direction(self, &snapshot, wrapped_point, true, direction, cx);
} }
} }

View file

@ -7,11 +7,11 @@ use unindent::Unindent;
use super::*; use super::*;
use crate::test::{ use crate::test::{
assert_text_with_selections, build_editor, editor_git_test_context::EditorGitTestContext, assert_text_with_selections, build_editor, editor_lsp_test_context::EditorLspTestContext,
editor_lsp_test_context::EditorLspTestContext, editor_test_context::EditorTestContext, editor_test_context::EditorTestContext, select_ranges,
select_ranges,
}; };
use gpui::{ use gpui::{
executor::Deterministic,
geometry::rect::RectF, geometry::rect::RectF,
platform::{WindowBounds, WindowOptions}, platform::{WindowBounds, WindowOptions},
}; };
@ -5081,8 +5081,108 @@ fn test_combine_syntax_and_fuzzy_match_highlights() {
} }
#[gpui::test] #[gpui::test]
fn go_to_hunk(cx: &mut gpui::TestAppContext) { async fn go_to_hunk(deterministic: Arc<Deterministic>, cx: &mut gpui::TestAppContext) {
let mut cx = EditorGitTestContext::new(cx); let mut cx = EditorTestContext::new(cx);
let diff_base = r#"
use some::mod;
const A: u32 = 42;
fn main() {
println!("hello");
println!("world");
}
"#
.unindent();
// Edits are modified, removed, modified, added
cx.set_state(
&r#"
use some::modified;
ˇ
fn main() {
println!("hello there");
println!("around the");
println!("world");
}
"#
.unindent(),
);
cx.set_diff_base(Some(&diff_base));
deterministic.run_until_parked();
cx.update_editor(|editor, cx| {
//Wrap around the bottom of the buffer
for _ in 0..3 {
editor.go_to_hunk(&GoToHunk, cx);
}
});
cx.assert_editor_state(
&r#"
ˇuse some::modified;
fn main() {
println!("hello there");
println!("around the");
println!("world");
}
"#
.unindent(),
);
cx.update_editor(|editor, cx| {
//Wrap around the top of the buffer
for _ in 0..2 {
editor.go_to_prev_hunk(&GoToPrevHunk, cx);
}
});
cx.assert_editor_state(
&r#"
use some::modified;
fn main() {
ˇ println!("hello there");
println!("around the");
println!("world");
}
"#
.unindent(),
);
cx.update_editor(|editor, cx| {
editor.fold(&Fold, cx);
//Make sure that the fold only gets one hunk
for _ in 0..4 {
editor.go_to_hunk(&GoToHunk, cx);
}
});
cx.assert_editor_state(
&r#"
ˇuse some::modified;
fn main() {
println!("hello there");
println!("around the");
println!("world");
}
"#
.unindent(),
);
} }
fn empty_range(row: usize, column: usize) -> Range<DisplayPoint> { fn empty_range(row: usize, column: usize) -> Range<DisplayPoint> {

View file

@ -21,14 +21,32 @@ pub enum DisplayDiffHunk {
} }
impl DisplayDiffHunk { impl DisplayDiffHunk {
pub fn display_row_range(&self) -> Range<u32> { pub fn start_display_row(&self) -> u32 {
match self { match self {
&DisplayDiffHunk::Folded { display_row } => display_row..display_row + 1, &DisplayDiffHunk::Folded { display_row } => display_row,
DisplayDiffHunk::Unfolded { DisplayDiffHunk::Unfolded {
display_row_range, .. display_row_range, ..
} => display_row_range.clone(), } => display_row_range.start,
} }
} }
pub fn contains_display_row(&self, display_row: u32) -> bool {
let range = match self {
&DisplayDiffHunk::Folded { display_row } => display_row..=display_row,
DisplayDiffHunk::Unfolded {
display_row_range, ..
} => {
if display_row_range.len() == 0 {
display_row_range.start..=display_row_range.end
} else {
display_row_range.start..=display_row_range.end - 1
}
}
};
range.contains(&display_row)
}
} }
pub fn diff_hunk_to_display(hunk: DiffHunk<u32>, snapshot: &DisplaySnapshot) -> DisplayDiffHunk { pub fn diff_hunk_to_display(hunk: DiffHunk<u32>, snapshot: &DisplaySnapshot) -> DisplayDiffHunk {

View file

@ -1,4 +1,3 @@
pub mod editor_git_test_context;
pub mod editor_lsp_test_context; pub mod editor_lsp_test_context;
pub mod editor_test_context; pub mod editor_test_context;

View file

@ -1,56 +0,0 @@
use std::ops::{Deref, DerefMut};
use gpui::ModelHandle;
use language::Buffer;
use settings::Settings;
use crate::MultiBuffer;
use super::{build_editor, editor_test_context::EditorTestContext};
pub struct EditorGitTestContext<'a> {
pub cx: EditorTestContext<'a>,
pub buffer: ModelHandle<Buffer>,
}
impl<'a> EditorGitTestContext<'a> {
pub async fn new(cx: &'a mut gpui::TestAppContext) -> EditorGitTestContext<'a> {
let (window_id, buffer, editor) = cx.update(|cx| {
cx.set_global(Settings::test(cx));
crate::init(cx);
let buffer = cx.add_model(|cx| Buffer::new(0, "", cx));
let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
let (window_id, editor) =
cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
editor.update(cx, |_, cx| cx.focus_self());
(window_id, buffer, editor)
});
Self {
cx: EditorTestContext {
cx,
window_id,
editor,
},
buffer,
}
}
}
impl<'a> Deref for EditorGitTestContext<'a> {
type Target = EditorTestContext<'a>;
fn deref(&self) -> &Self::Target {
&self.cx
}
}
impl<'a> DerefMut for EditorGitTestContext<'a> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.cx
}
}

View file

@ -151,6 +151,11 @@ impl<'a> EditorTestContext<'a> {
snapshot.anchor_before(ranges[0].start)..snapshot.anchor_after(ranges[0].end) snapshot.anchor_before(ranges[0].start)..snapshot.anchor_after(ranges[0].end)
} }
pub fn set_diff_base(&mut self, diff_base: Option<&str>) {
let diff_base = diff_base.map(String::from);
self.update_buffer(|buffer, cx| buffer.set_diff_base(diff_base, cx));
}
/// Change the editor's text and selections using a string containing /// Change the editor's text and selections using a string containing
/// embedded range markers that represent the ranges and directions of /// embedded range markers that represent the ranges and directions of
/// each selection. /// each selection.

View file

@ -681,7 +681,7 @@ impl Buffer {
self.diff_base.as_deref() self.diff_base.as_deref()
} }
pub fn update_diff_base(&mut self, diff_base: Option<String>, cx: &mut ModelContext<Self>) { pub fn set_diff_base(&mut self, diff_base: Option<String>, cx: &mut ModelContext<Self>) {
self.diff_base = diff_base; self.diff_base = diff_base;
self.git_diff_recalc(cx); self.git_diff_recalc(cx);
} }

View file

@ -4410,7 +4410,7 @@ impl Project {
.await; .await;
let buffer_id = buffer.update(&mut cx, |buffer, cx| { let buffer_id = buffer.update(&mut cx, |buffer, cx| {
buffer.update_diff_base(diff_base.clone(), cx); buffer.set_diff_base(diff_base.clone(), cx);
buffer.remote_id() buffer.remote_id()
}); });
@ -4968,7 +4968,7 @@ impl Project {
.and_then(|b| b.upgrade(cx)) .and_then(|b| b.upgrade(cx))
.ok_or_else(|| anyhow!("No such buffer {}", buffer_id))?; .ok_or_else(|| anyhow!("No such buffer {}", buffer_id))?;
buffer.update(cx, |buffer, cx| buffer.update_diff_base(diff_base, cx)); buffer.update(cx, |buffer, cx| buffer.set_diff_base(diff_base, cx));
Ok(()) Ok(())
}) })