feat: support comments in ordinary source buffers
This commit is contained in:
+107
-78
@@ -2460,6 +2460,7 @@ fn column_view_suppresses_whole_file_emphasis_without_losing_change_markers() {
|
||||
|
||||
#[test]
|
||||
fn working_refresh_preserves_noops_errors_and_view_state_but_invalidates_old_identity() {
|
||||
let mut review = crate::review::ReviewState::default();
|
||||
let mut state = live_state(vec!["old".into()], vec!["new".into()], false);
|
||||
state.loading = false;
|
||||
state.pending = None;
|
||||
@@ -2554,7 +2555,7 @@ fn working_refresh_preserves_noops_errors_and_view_state_but_invalidates_old_ide
|
||||
.unwrap()
|
||||
.editable_paths
|
||||
.insert("file".into());
|
||||
state.refresh_after(&["dirty".into()], 1);
|
||||
state.refresh_after(&["dirty".into()], 1, &mut review);
|
||||
assert_eq!(state.comparison.as_ref().unwrap().files[1].after, ["dirty"]);
|
||||
state.queue_checkout_refresh(false);
|
||||
state.take_request();
|
||||
@@ -2575,6 +2576,7 @@ fn working_refresh_preserves_noops_errors_and_view_state_but_invalidates_old_ide
|
||||
|
||||
#[test]
|
||||
fn reviewed_files_use_highlighted_catalog_indices_not_sorted_or_filtered_rows() {
|
||||
let mut review = crate::review::ReviewState::default();
|
||||
let mut state = DiffState::new();
|
||||
let mut changes = comparison();
|
||||
changes.files[0].path = "nested/z.txt".into();
|
||||
@@ -2591,9 +2593,9 @@ fn reviewed_files_use_highlighted_catalog_indices_not_sorted_or_filtered_rows()
|
||||
}
|
||||
files.reveal_path(Path::new("nested/a.txt"));
|
||||
assert_eq!(state.file, 0);
|
||||
assert_eq!(state.toggle_reviewed(), Ok(true));
|
||||
assert_eq!(state.toggle_reviewed(&mut review), Ok(true));
|
||||
assert_eq!(state.reviewed_files, BTreeSet::from([1]));
|
||||
assert_eq!(state.toggle_reviewed(), Ok(false));
|
||||
assert_eq!(state.toggle_reviewed(&mut review), Ok(false));
|
||||
assert!(state.reviewed_files.is_empty());
|
||||
}
|
||||
let files = state.files.as_mut().unwrap();
|
||||
@@ -2602,7 +2604,7 @@ fn reviewed_files_use_highlighted_catalog_indices_not_sorted_or_filtered_rows()
|
||||
let selected = files.entries().position(|entry| entry.is_dir).unwrap();
|
||||
files.selected = selected;
|
||||
assert_eq!(
|
||||
state.toggle_reviewed(),
|
||||
state.toggle_reviewed(&mut review),
|
||||
Err("Select a changed file, not a directory")
|
||||
);
|
||||
assert!(state.reviewed_files.is_empty());
|
||||
@@ -2611,32 +2613,42 @@ fn reviewed_files_use_highlighted_catalog_indices_not_sorted_or_filtered_rows()
|
||||
for ch in "missing".chars() {
|
||||
files.handle_filter_input(&Input::Char(ch));
|
||||
}
|
||||
assert_eq!(state.toggle_reviewed(), Err("No changed file is selected"));
|
||||
assert_eq!(
|
||||
state.toggle_reviewed(&mut review),
|
||||
Err("No changed file is selected")
|
||||
);
|
||||
state.files = Some(FilePicker::from_paths(
|
||||
PathBuf::new(),
|
||||
[(0, PathBuf::from("ordinary.txt"))],
|
||||
));
|
||||
assert_eq!(state.toggle_reviewed(), Err("No changed file is selected"));
|
||||
assert_eq!(
|
||||
state.toggle_reviewed(&mut review),
|
||||
Err("No changed file is selected")
|
||||
);
|
||||
state.focus = Focus::Before;
|
||||
assert_eq!(state.toggle_reviewed(), Ok(true));
|
||||
assert_eq!(state.toggle_reviewed(&mut review), Ok(true));
|
||||
assert_eq!(state.reviewed_files, BTreeSet::from([0]));
|
||||
assert!(state.select_file_index(2));
|
||||
state.focus = Focus::Before;
|
||||
assert_eq!(state.toggle_reviewed(), Ok(true));
|
||||
assert_eq!(state.toggle_reviewed(&mut review), Ok(true));
|
||||
assert_eq!(state.reviewed_files, BTreeSet::from([0, 2]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reviewed_files_survive_lazy_details_and_views_but_reset_on_comparison() {
|
||||
let mut review = crate::review::ReviewState::default();
|
||||
let mut state = DiffState::new();
|
||||
assert_eq!(state.toggle_reviewed(), Err("No comparison is open"));
|
||||
assert_eq!(
|
||||
state.toggle_reviewed(&mut review),
|
||||
Err("No comparison is open")
|
||||
);
|
||||
let mut changes = comparison();
|
||||
changes.files[0].loaded = false;
|
||||
changes.files[0].before.clear();
|
||||
changes.files[0].after.clear();
|
||||
state.request_kind = Some(RequestKind::Comparison);
|
||||
state.apply_result(1, Ok(Outcome::Comparison(changes)));
|
||||
assert_eq!(state.toggle_reviewed(), Ok(true));
|
||||
assert_eq!(state.toggle_reviewed(&mut review), Ok(true));
|
||||
assert_eq!(state.reviewed_files, BTreeSet::from([0]));
|
||||
let file = comparison().files.remove(0);
|
||||
state.apply_result(
|
||||
@@ -2667,10 +2679,13 @@ fn reviewed_files_survive_lazy_details_and_views_but_reset_on_comparison() {
|
||||
));
|
||||
state.toggle_comparison_mode().unwrap();
|
||||
assert!(state.reviewed_files.is_empty());
|
||||
assert_eq!(state.toggle_reviewed(), Err("No comparison is open"));
|
||||
assert_eq!(
|
||||
state.toggle_reviewed(&mut review),
|
||||
Err("No comparison is open")
|
||||
);
|
||||
state.apply_result(3, Ok(Outcome::Comparison(comparison())));
|
||||
assert!(state.reviewed_files.is_empty());
|
||||
assert_eq!(state.toggle_reviewed(), Ok(true));
|
||||
assert_eq!(state.toggle_reviewed(&mut review), Ok(true));
|
||||
state.request_kind = Some(RequestKind::Comparison);
|
||||
state.apply_result(4, Ok(Outcome::Comparison(comparison())));
|
||||
assert!(state.reviewed_files.is_empty());
|
||||
@@ -2678,17 +2693,18 @@ fn reviewed_files_survive_lazy_details_and_views_but_reset_on_comparison() {
|
||||
|
||||
#[test]
|
||||
fn restored_review_marks_use_file_identities_and_rename_paths_not_catalog_order() {
|
||||
let mut review = crate::review::ReviewState::default();
|
||||
let mut state = DiffState::new();
|
||||
state.request_kind = Some(RequestKind::Comparison);
|
||||
state.apply_result(1, Ok(Outcome::Comparison(comparison())));
|
||||
state.comparison.as_mut().unwrap().files[0].review_revisions =
|
||||
Some(["file:before".into(), "file:after".into()]);
|
||||
assert_eq!(state.toggle_reviewed(), Ok(true));
|
||||
assert_eq!(state.toggle_reviewed(&mut review), Ok(true));
|
||||
state.comparison.as_mut().unwrap().files.swap(0, 1);
|
||||
state.restore_reviewed_files();
|
||||
state.restore_reviewed_files(&review);
|
||||
assert_eq!(state.reviewed_files, BTreeSet::from([1]));
|
||||
state.comparison.as_mut().unwrap().files[1].old_path = Some("different.txt".into());
|
||||
state.restore_reviewed_files();
|
||||
state.restore_reviewed_files(&review);
|
||||
assert!(state.reviewed_files.is_empty());
|
||||
state.comparison.as_mut().unwrap().files[1].old_path = Some("old.txt".into());
|
||||
for side in [0, 1] {
|
||||
@@ -2698,7 +2714,7 @@ fn restored_review_marks_use_file_identities_and_rename_paths_not_catalog_order(
|
||||
.unwrap();
|
||||
let original = identities[side].clone();
|
||||
identities[side].push_str("-different");
|
||||
state.restore_reviewed_files();
|
||||
state.restore_reviewed_files(&review);
|
||||
assert!(state.reviewed_files.is_empty());
|
||||
state.comparison.as_mut().unwrap().files[1]
|
||||
.review_revisions
|
||||
@@ -2706,12 +2722,13 @@ fn restored_review_marks_use_file_identities_and_rename_paths_not_catalog_order(
|
||||
.unwrap()[side] = original;
|
||||
}
|
||||
state.comparison.as_mut().unwrap().files[1].loaded = false;
|
||||
state.restore_reviewed_files();
|
||||
state.restore_reviewed_files(&review);
|
||||
assert_eq!(state.reviewed_files, BTreeSet::from([1]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unchanged_file_review_survives_other_files_changing() {
|
||||
let mut review = crate::review::ReviewState::default();
|
||||
use crate::repository::Repository;
|
||||
use std::sync::{Arc, atomic::AtomicBool};
|
||||
let root = std::env::temp_dir().join(format!("vamp-review-files-{}", std::process::id()));
|
||||
@@ -2759,13 +2776,13 @@ fn unchanged_file_review_survives_other_files_changing() {
|
||||
let original_revisions = changes.revisions.clone();
|
||||
state.request_kind = Some(RequestKind::Comparison);
|
||||
state.apply_result(1, Ok(Outcome::Comparison(changes)));
|
||||
state.toggle_reviewed().unwrap();
|
||||
state.toggle_reviewed(&mut review).unwrap();
|
||||
state.file = 1;
|
||||
state.focus = Focus::Before;
|
||||
state.toggle_reviewed().unwrap();
|
||||
state.toggle_reviewed(&mut review).unwrap();
|
||||
let mut store = crate::review::Store::open(&root.join("reviews")).unwrap();
|
||||
store.save(&mut state.local_review.document).unwrap();
|
||||
let id = state.local_review.document.storage_id.unwrap();
|
||||
store.save(&mut review.document).unwrap();
|
||||
let id = review.document.storage_id.unwrap();
|
||||
std::fs::write(root.join("b.txt"), "edited again\n").unwrap();
|
||||
let changes = repository
|
||||
.compare(2, &before, &after, ComparisonMode::Snapshots, &[])
|
||||
@@ -2773,8 +2790,8 @@ fn unchanged_file_review_survives_other_files_changing() {
|
||||
assert_ne!(changes.revisions, original_revisions);
|
||||
state.request_kind = Some(RequestKind::Comparison);
|
||||
state.apply_result(2, Ok(Outcome::Comparison(changes)));
|
||||
state.local_review.document = store.load(&root, id).unwrap();
|
||||
state.restore_reviewed_files();
|
||||
review.document = store.load(&root, id).unwrap();
|
||||
state.restore_reviewed_files(&review);
|
||||
assert_eq!(state.reviewed_files, BTreeSet::from([0]));
|
||||
let detail = repository.load_file(2, 0).unwrap();
|
||||
state.apply_result(
|
||||
@@ -2785,33 +2802,36 @@ fn unchanged_file_review_survives_other_files_changing() {
|
||||
file: detail,
|
||||
}),
|
||||
);
|
||||
state.restore_reviewed_files();
|
||||
state.restore_reviewed_files(&review);
|
||||
assert_eq!(state.reviewed_files, BTreeSet::from([0]));
|
||||
std::fs::remove_dir_all(root).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn restored_live_review_marks_require_exact_text_and_final_newline() {
|
||||
let mut review = crate::review::ReviewState::default();
|
||||
let mut reopened_review = crate::review::ReviewState::default();
|
||||
let mut state = live_state(vec!["base".into()], vec!["changed".into()], false);
|
||||
state.refresh_after(&["unsaved".into(), String::new()], 1);
|
||||
assert_eq!(state.toggle_reviewed(), Ok(true));
|
||||
let document = state.local_review.document.clone();
|
||||
state.refresh_after(&["unsaved".into(), String::new()], 1, &mut review);
|
||||
assert_eq!(state.toggle_reviewed(&mut review), Ok(true));
|
||||
let document = review.document.clone();
|
||||
let mut reopened = live_state(vec!["base".into()], vec!["changed".into()], false);
|
||||
reopened.local_review.document = document.clone();
|
||||
reopened.restore_reviewed_files();
|
||||
reopened_review.document = document.clone();
|
||||
reopened.restore_reviewed_files(&reopened_review);
|
||||
assert!(reopened.reviewed_files.is_empty());
|
||||
reopened.refresh_after(&["unsaved".into(), String::new()], 1);
|
||||
reopened.refresh_after(&["unsaved".into(), String::new()], 1, &mut reopened_review);
|
||||
assert_eq!(reopened.reviewed_files, BTreeSet::from([0]));
|
||||
reopened.refresh_after(&["unsaved".into()], 2);
|
||||
reopened.refresh_after(&["unsaved".into()], 2, &mut reopened_review);
|
||||
assert!(reopened.reviewed_files.is_empty());
|
||||
assert!(reopened.local_review.document.reviewed_files.is_empty());
|
||||
reopened.local_review.document = document;
|
||||
reopened.restore_reviewed_files();
|
||||
assert!(reopened_review.document.reviewed_files.is_empty());
|
||||
reopened_review.document = document;
|
||||
reopened.restore_reviewed_files(&reopened_review);
|
||||
assert!(reopened.reviewed_files.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn working_review_marks_clear_only_for_changed_bytes_or_eof() {
|
||||
let mut review = crate::review::ReviewState::default();
|
||||
for (after, eof, lines) in [
|
||||
(vec!["changed".into()], false, vec!["changed".into()]),
|
||||
(
|
||||
@@ -2822,24 +2842,24 @@ fn working_review_marks_clear_only_for_changed_bytes_or_eof() {
|
||||
(Vec::new(), false, vec![String::new()]),
|
||||
] {
|
||||
let mut state = live_state(vec!["base".into()], after, eof);
|
||||
assert_eq!(state.toggle_reviewed(), Ok(true));
|
||||
state.refresh_after(&lines, 1);
|
||||
assert_eq!(state.toggle_reviewed(&mut review), Ok(true));
|
||||
state.refresh_after(&lines, 1, &mut review);
|
||||
assert_eq!(state.reviewed_files, BTreeSet::from([0]));
|
||||
state.refresh_after(&lines, 2);
|
||||
state.refresh_after(&lines, 2, &mut review);
|
||||
assert_eq!(state.reviewed_files, BTreeSet::from([0]));
|
||||
state.refresh_after(&["edited".into()], 3);
|
||||
state.refresh_after(&["edited".into()], 3, &mut review);
|
||||
assert!(state.reviewed_files.is_empty());
|
||||
assert_eq!(state.toggle_reviewed(), Ok(true));
|
||||
state.refresh_after(&["edited".into(), String::new()], 4);
|
||||
assert_eq!(state.toggle_reviewed(&mut review), Ok(true));
|
||||
state.refresh_after(&["edited".into(), String::new()], 4, &mut review);
|
||||
assert!(state.reviewed_files.is_empty());
|
||||
assert_eq!(state.toggle_reviewed(), Ok(true));
|
||||
state.refresh_after(&["edited".into()], 5);
|
||||
assert_eq!(state.toggle_reviewed(&mut review), Ok(true));
|
||||
state.refresh_after(&["edited".into()], 5, &mut review);
|
||||
assert!(state.reviewed_files.is_empty());
|
||||
}
|
||||
let mut state = live_state(vec!["base".into()], vec!["changed".into()], false);
|
||||
state.comparison.as_mut().unwrap().files[0].loaded = false;
|
||||
assert_eq!(state.toggle_reviewed(), Ok(true));
|
||||
state.refresh_after(&["edited".into()], 1);
|
||||
assert_eq!(state.toggle_reviewed(&mut review), Ok(true));
|
||||
state.refresh_after(&["edited".into()], 1, &mut review);
|
||||
assert_eq!(state.reviewed_files, BTreeSet::from([0]));
|
||||
}
|
||||
|
||||
@@ -2901,19 +2921,20 @@ fn unified_groups_changed_runs_and_roundtrips_side_specific_source_rows() {
|
||||
|
||||
#[test]
|
||||
fn unified_live_reflow_preserves_removed_top_and_expanded_source_excerpts() {
|
||||
let mut review = crate::review::ReviewState::default();
|
||||
let base: Vec<_> = (0..40).map(|row| format!("line {row}")).collect();
|
||||
let mut lines = base.clone();
|
||||
lines[20] = "new line".into();
|
||||
let mut state = live_state(base, lines.clone(), false);
|
||||
state.set_context_options(1, 3);
|
||||
state.refresh_after(&lines, 1);
|
||||
state.refresh_after(&lines, 1, &mut review);
|
||||
state.set_view_mode(ViewMode::Unified);
|
||||
state.top = state.source_display_row(Focus::Before, 20).unwrap();
|
||||
state.expand_source_excerpt(Focus::After, false, 20);
|
||||
assert_eq!(state.display_source_row(Focus::Before, state.top), Some(20));
|
||||
assert!(state.source_display_row(Focus::After, 16).is_some());
|
||||
lines.insert(0, "inserted".into());
|
||||
state.refresh_after(&lines, 2);
|
||||
state.refresh_after(&lines, 2, &mut review);
|
||||
assert_eq!(state.display_focus(state.top), Some(Focus::Before));
|
||||
assert_eq!(state.display_source_row(Focus::Before, state.top), Some(20));
|
||||
assert!(state.source_display_row(Focus::After, 17).is_some());
|
||||
@@ -2932,6 +2953,7 @@ fn unified_live_reflow_preserves_removed_top_and_expanded_source_excerpts() {
|
||||
|
||||
#[test]
|
||||
fn character_ranges_follow_insertions_deletions_unicode_and_live_edits() {
|
||||
let mut review = crate::review::ReviewState::default();
|
||||
for (before, after, expected) in [
|
||||
("ab", "a界b", vec![[1..1, 1..2]]),
|
||||
("a界b", "ab", vec![[1..2, 1..1]]),
|
||||
@@ -2941,17 +2963,18 @@ fn character_ranges_follow_insertions_deletions_unicode_and_live_edits() {
|
||||
assert_eq!(state.rows[0].changes, expected);
|
||||
}
|
||||
let mut state = live_state(vec!["abc".into()], vec!["aXbc".into()], false);
|
||||
state.refresh_after(&["aXYbc".into()], 1);
|
||||
state.refresh_after(&["aXYbc".into()], 1, &mut review);
|
||||
assert_eq!(state.rows[0].changes, vec![[1..1, 1..3]]);
|
||||
state.refresh_after(&["abYZc".into()], 2);
|
||||
state.refresh_after(&["abYZc".into()], 2, &mut review);
|
||||
assert_eq!(state.rows[0].changes, vec![[2..2, 2..4]]);
|
||||
state.refresh_after(&["abc".into()], 3);
|
||||
state.refresh_after(&["abc".into()], 3, &mut review);
|
||||
assert_eq!(state.rows[0].kind, RowKind::Equal);
|
||||
assert!(state.rows[0].changes.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn character_highlights_merge_incidental_matches_but_preserve_meaningful_gaps() {
|
||||
let mut review = crate::review::ReviewState::default();
|
||||
let mut cases = vec![
|
||||
("a..c".into(), "b..d".into(), vec![[0..4, 0..4]]),
|
||||
("base".into(), "edited".into(), vec![[0..4, 0..6]]),
|
||||
@@ -2995,14 +3018,15 @@ fn character_highlights_merge_incidental_matches_but_preserve_meaningful_gaps()
|
||||
for (before, after, expected) in cases {
|
||||
let mut state = live_state(vec![before], vec![after.clone()], false);
|
||||
assert_eq!(state.rows[0].changes, expected, "{after:?}");
|
||||
state.refresh_after(&[format!("{after}!")], 1);
|
||||
state.refresh_after(std::slice::from_ref(&after), 2);
|
||||
state.refresh_after(&[format!("{after}!")], 1, &mut review);
|
||||
state.refresh_after(std::slice::from_ref(&after), 2, &mut review);
|
||||
assert_eq!(state.rows[0].changes, expected, "live edit: {after:?}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reverting_loaded_file_keeps_unloaded_changes_selectable() {
|
||||
let mut review = crate::review::ReviewState::default();
|
||||
let mut state = live_state(vec!["base".into()], vec!["changed".into()], false);
|
||||
state.comparison_id = Some(17);
|
||||
state.pending = None;
|
||||
@@ -3020,7 +3044,7 @@ fn reverting_loaded_file_keeps_unloaded_changes_selectable() {
|
||||
hunks: vec![],
|
||||
notice: None,
|
||||
});
|
||||
state.refresh_after(&["base".into()], 1);
|
||||
state.refresh_after(&["base".into()], 1, &mut review);
|
||||
assert_eq!(
|
||||
state
|
||||
.files
|
||||
@@ -3043,36 +3067,37 @@ fn reverting_loaded_file_keeps_unloaded_changes_selectable() {
|
||||
|
||||
#[test]
|
||||
fn live_width_cache_scans_only_changed_lines_and_shrinks_after_deletion() {
|
||||
let mut review = crate::review::ReviewState::default();
|
||||
let base = vec!["original".into(), "medium".into(), "short".into()];
|
||||
let mut lines = vec!["界\tz".into(), "medium".into(), "short".into()];
|
||||
let mut state = live_state(base, lines.clone(), false);
|
||||
state.refresh_after(&lines, 1);
|
||||
state.refresh_after(&lines, 1, &mut review);
|
||||
assert_eq!(state.after_widths, [5, 6, 5]);
|
||||
lines[0] = "界界\t🙂".into();
|
||||
WIDTH_SCANS.set(0);
|
||||
state.refresh_after(&lines, 2);
|
||||
state.refresh_after(&lines, 2, &mut review);
|
||||
assert_eq!(WIDTH_SCANS.get(), 1);
|
||||
assert_eq!(state.max_after, 10);
|
||||
state.left_after = 9;
|
||||
lines[0] = "界".into();
|
||||
WIDTH_SCANS.set(0);
|
||||
state.refresh_after(&lines, 3);
|
||||
state.refresh_after(&lines, 3, &mut review);
|
||||
assert_eq!(WIDTH_SCANS.get(), 1);
|
||||
assert_eq!(state.max_after, 6);
|
||||
assert_eq!(state.left_after, 6);
|
||||
lines.remove(1);
|
||||
WIDTH_SCANS.set(0);
|
||||
state.refresh_after(&lines, 4);
|
||||
state.refresh_after(&lines, 4, &mut review);
|
||||
assert_eq!(WIDTH_SCANS.get(), 0);
|
||||
assert_eq!(state.after_widths, [2, 5]);
|
||||
assert_eq!(state.max_after, 5);
|
||||
lines.insert(1, "巨大\t🙂".into());
|
||||
WIDTH_SCANS.set(0);
|
||||
state.refresh_after(&lines, 5);
|
||||
state.refresh_after(&lines, 5, &mut review);
|
||||
assert_eq!(WIDTH_SCANS.get(), 1);
|
||||
assert_eq!(state.after_widths, [2, 10, 5]);
|
||||
lines = vec!["".into()];
|
||||
state.refresh_after(&lines, 6);
|
||||
state.refresh_after(&lines, 6, &mut review);
|
||||
assert_eq!(state.after_widths, [0]);
|
||||
assert_eq!(state.max_after, 0);
|
||||
assert_eq!(state.left_after, 0);
|
||||
@@ -3080,6 +3105,7 @@ fn live_width_cache_scans_only_changed_lines_and_shrinks_after_deletion() {
|
||||
|
||||
#[test]
|
||||
fn stable_line_edits_keep_fresh_hunks_expansion_and_scroll_anchor_until_revert() {
|
||||
let mut review = crate::review::ReviewState::default();
|
||||
let base = (0..100)
|
||||
.map(|row| format!("line {row}"))
|
||||
.collect::<Vec<_>>();
|
||||
@@ -3088,7 +3114,7 @@ fn stable_line_edits_keep_fresh_hunks_expansion_and_scroll_anchor_until_revert()
|
||||
let mut state = live_state(base.clone(), lines.clone(), true);
|
||||
state.set_context_options(2, 5);
|
||||
lines.push(String::new());
|
||||
state.refresh_after(&lines, 1);
|
||||
state.refresh_after(&lines, 1, &mut review);
|
||||
state.top = state.after_display_row(30).unwrap();
|
||||
state.handle(Input::Char('['));
|
||||
let display = state.display_rows.clone();
|
||||
@@ -3102,7 +3128,7 @@ fn stable_line_edits_keep_fresh_hunks_expansion_and_scroll_anchor_until_revert()
|
||||
changed_line_range(&file.after, &lines)
|
||||
));
|
||||
WIDTH_SCANS.set(0);
|
||||
state.refresh_after(&lines, 2);
|
||||
state.refresh_after(&lines, 2, &mut review);
|
||||
assert_eq!(WIDTH_SCANS.get(), 1);
|
||||
assert_eq!(state.display_rows, display);
|
||||
assert_eq!(state.excerpt_ranges, excerpts);
|
||||
@@ -3131,14 +3157,14 @@ fn stable_line_edits_keep_fresh_hunks_expansion_and_scroll_anchor_until_revert()
|
||||
&lines,
|
||||
changed_line_range(&file.after, &lines)
|
||||
));
|
||||
state.refresh_after(&lines, 3);
|
||||
state.refresh_after(&lines, 3, &mut review);
|
||||
assert!(state.comparison.as_ref().unwrap().files[0].hunks.is_empty());
|
||||
assert!(state.rows.iter().all(|row| row.kind == RowKind::Equal));
|
||||
assert!(state.after_display_row(23).is_some());
|
||||
assert_eq!(state.top, state.after_display_row(30).unwrap());
|
||||
assert_eq!(state.files.as_ref().unwrap().entries().len(), 0);
|
||||
lines[50] = "changed again".into();
|
||||
state.refresh_after(&lines, 4);
|
||||
state.refresh_after(&lines, 4, &mut review);
|
||||
assert_eq!(state.files.as_ref().unwrap().entries().len(), 1);
|
||||
assert!(state.after_display_row(23).is_some());
|
||||
assert!(state.after_display_row(50).is_some());
|
||||
@@ -3146,6 +3172,7 @@ fn stable_line_edits_keep_fresh_hunks_expansion_and_scroll_anchor_until_revert()
|
||||
|
||||
#[test]
|
||||
fn live_reflow_keeps_separate_hunks_and_expanded_context_after_revert() {
|
||||
let mut review = crate::review::ReviewState::default();
|
||||
let base = (0..100)
|
||||
.map(|row| format!("line {row}"))
|
||||
.collect::<Vec<_>>();
|
||||
@@ -3155,7 +3182,7 @@ fn live_reflow_keeps_separate_hunks_and_expanded_context_after_revert() {
|
||||
let mut state = live_state(base.clone(), changed.clone(), true);
|
||||
state.set_context_options(2, 5);
|
||||
changed.push(String::new());
|
||||
state.refresh_after(&changed, 1);
|
||||
state.refresh_after(&changed, 1, &mut review);
|
||||
assert_eq!(state.comparison.as_ref().unwrap().files[0].hunks.len(), 2);
|
||||
assert!(
|
||||
state
|
||||
@@ -3167,7 +3194,7 @@ fn live_reflow_keeps_separate_hunks_and_expanded_context_after_revert() {
|
||||
state.handle(Input::Char('['));
|
||||
assert!(state.after_display_row(23).is_some());
|
||||
changed.insert(10, "inserted outside excerpts".into());
|
||||
state.refresh_after(&changed, 2);
|
||||
state.refresh_after(&changed, 2, &mut review);
|
||||
assert!(state.after_display_row(24).is_some());
|
||||
assert_eq!(state.comparison.as_ref().unwrap().files[0].hunks.len(), 3);
|
||||
assert!(
|
||||
@@ -3178,7 +3205,7 @@ fn live_reflow_keeps_separate_hunks_and_expanded_context_after_revert() {
|
||||
);
|
||||
let mut reverted = base;
|
||||
reverted.push(String::new());
|
||||
state.refresh_after(&reverted, 3);
|
||||
state.refresh_after(&reverted, 3, &mut review);
|
||||
assert!(state.comparison.as_ref().unwrap().files[0].hunks.is_empty());
|
||||
assert!(state.rows.iter().all(|row| row.kind == RowKind::Equal));
|
||||
assert!(state.after_display_row(23).is_some());
|
||||
@@ -3186,21 +3213,22 @@ fn live_reflow_keeps_separate_hunks_and_expanded_context_after_revert() {
|
||||
assert_eq!(state.files.as_ref().unwrap().entries().len(), 0);
|
||||
assert_eq!(state.file, 0);
|
||||
reverted[50] = "changed again".into();
|
||||
state.refresh_after(&reverted, 4);
|
||||
state.refresh_after(&reverted, 4, &mut review);
|
||||
assert_eq!(state.files.as_ref().unwrap().entries().len(), 1);
|
||||
assert!(state.after_display_row(50).is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn live_empty_and_eof_rows_match_buffer_without_false_eof_highlights() {
|
||||
let mut review = crate::review::ReviewState::default();
|
||||
let mut state = live_state(vec!["same".into()], vec!["changed".into()], true);
|
||||
state.refresh_after(&["same".into(), "".into()], 1);
|
||||
state.refresh_after(&["same".into(), "".into()], 1, &mut review);
|
||||
assert!(state.comparison.as_ref().unwrap().files[0].hunks.is_empty());
|
||||
assert_eq!(state.rows.len(), 2);
|
||||
assert!(state.rows.iter().all(|row| row.kind == RowKind::Equal));
|
||||
assert!(state.after_display_row(0).is_some());
|
||||
assert!(state.after_display_row(1).is_none());
|
||||
state.refresh_after(&["same".into()], 2);
|
||||
state.refresh_after(&["same".into()], 2, &mut review);
|
||||
assert_eq!(state.rows[0].kind, RowKind::Changed);
|
||||
assert!(
|
||||
state.comparison.as_ref().unwrap().files[0]
|
||||
@@ -3209,18 +3237,18 @@ fn live_empty_and_eof_rows_match_buffer_without_false_eof_highlights() {
|
||||
.unwrap()
|
||||
.contains("After missing")
|
||||
);
|
||||
state.refresh_after(&["".into()], 3);
|
||||
state.refresh_after(&["".into()], 3, &mut review);
|
||||
assert!(state.after_display_row(0).is_some());
|
||||
assert_eq!(state.comparison.as_ref().unwrap().files[0].after, [""]);
|
||||
let mut empty = live_state(vec![], vec!["text".into()], false);
|
||||
empty.refresh_after(&["".into()], 1);
|
||||
empty.refresh_after(&["".into()], 1, &mut review);
|
||||
assert!(empty.comparison.as_ref().unwrap().files[0].hunks.is_empty());
|
||||
assert_eq!(empty.rows.len(), 1);
|
||||
assert_eq!(empty.rows[0].kind, RowKind::Equal);
|
||||
assert_eq!(empty.after_display_row(0), Some(0));
|
||||
empty.after.as_mut().unwrap().target = RevisionTarget::Commit("historic".into());
|
||||
empty.comparison.as_mut().unwrap().editable_paths.clear();
|
||||
empty.refresh_after(&["must not apply".into()], 2);
|
||||
empty.refresh_after(&["must not apply".into()], 2, &mut review);
|
||||
assert_eq!(empty.comparison.as_ref().unwrap().files[0].after, [""]);
|
||||
empty.handle(Input::Escape);
|
||||
assert_eq!(empty.phase, Phase::View);
|
||||
@@ -3372,6 +3400,7 @@ fn mode_action_keeps_filter_input_and_rejects_superseded_comparisons() {
|
||||
|
||||
#[test]
|
||||
fn review_anchors_match_frozen_context_and_exact_live_eof_without_allocating() {
|
||||
let review = crate::review::ReviewState::default();
|
||||
use crate::review::{Anchor, Side};
|
||||
let mut state = live_state(vec!["old".into()], vec!["new".into()], true);
|
||||
let anchor = Anchor {
|
||||
@@ -3382,15 +3411,15 @@ fn review_anchors_match_frozen_context_and_exact_live_eof_without_allocating() {
|
||||
end: crate::plugin::TextPosition { row: 1, column: 0 },
|
||||
content: "new\n".into(),
|
||||
};
|
||||
assert!(state.review_anchor_range(&anchor).is_some());
|
||||
assert!(state.review_anchor_range(&anchor, &review).is_some());
|
||||
state.live_files.insert(0);
|
||||
assert!(state.review_anchor_range(&anchor).is_none());
|
||||
assert!(state.review_anchor_range(&anchor, &review).is_none());
|
||||
state.comparison.as_mut().unwrap().files[0]
|
||||
.after
|
||||
.push(String::new());
|
||||
assert!(state.review_anchor_range(&anchor).is_some());
|
||||
assert!(state.review_anchor_range(&anchor, &review).is_some());
|
||||
state.comparison.as_mut().unwrap().files[0].after[0] = "changed".into();
|
||||
assert!(state.review_anchor_range(&anchor).is_none());
|
||||
assert!(state.review_anchor_range(&anchor, &review).is_none());
|
||||
state.comparison.as_mut().unwrap().files[0].old_path = Some("original".into());
|
||||
let before = Anchor {
|
||||
revision: "base".into(),
|
||||
@@ -3399,12 +3428,12 @@ fn review_anchors_match_frozen_context_and_exact_live_eof_without_allocating() {
|
||||
content: "old\n".into(),
|
||||
..anchor
|
||||
};
|
||||
assert!(state.review_anchor_range(&before).is_some());
|
||||
assert!(state.review_anchor_range(&before, &review).is_some());
|
||||
state.comparison.as_mut().unwrap().files[0].loaded = false;
|
||||
assert!(state.review_anchor_range(&before).is_none());
|
||||
assert!(state.review_anchor_range(&before, &review).is_none());
|
||||
state.comparison.as_mut().unwrap().files[0].loaded = true;
|
||||
state.comparison.as_mut().unwrap().revisions[0] = "other".into();
|
||||
assert!(state.review_anchor_range(&before).is_none());
|
||||
assert!(state.review_anchor_range(&before, &review).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user