mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-25 01:34:02 +00:00
Add test for go-to hunk and fix discovered bugs
This commit is contained in:
parent
ae2021e073
commit
8361b4d47a
8 changed files with 145 additions and 72 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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.
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(())
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in a new issue