fix: preserve review comments across unrelated edits
This commit is contained in:
+131
-28
@@ -67,13 +67,18 @@ fn database_restarts_preserve_identity_and_exact_stale_anchors() {
|
||||
assert_eq!(loaded.comments, review.comments);
|
||||
assert_eq!(loaded.reviewed_files, review.reviewed_files);
|
||||
assert_eq!(loaded.verdict, review.verdict);
|
||||
assert!(!loaded.comments[0].anchor.matches_lines(
|
||||
"working:new-snapshot",
|
||||
Path::new("日本語.rs"),
|
||||
Side::Before,
|
||||
&["changed".into()],
|
||||
true,
|
||||
));
|
||||
assert!(
|
||||
loaded.comments[0]
|
||||
.anchor
|
||||
.mapped_range(
|
||||
"working:new-snapshot",
|
||||
Path::new("日本語.rs"),
|
||||
Side::Before,
|
||||
&["changed".into()],
|
||||
true,
|
||||
)
|
||||
.is_none()
|
||||
);
|
||||
let path = root.join("export.json");
|
||||
loaded.save(&path).unwrap();
|
||||
let exported = fs::read(&path).unwrap();
|
||||
@@ -387,6 +392,92 @@ fn default_directory_uses_absolute_xdg_then_absolute_home() {
|
||||
assert!(resolve(None, Some("")).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn anchor_survives_unrelated_edit() {
|
||||
let anchor = Anchor {
|
||||
revision: "working:old".into(),
|
||||
path: "source.rs".into(),
|
||||
side: Side::After,
|
||||
start: crate::plugin::TextPosition { row: 1, column: 0 },
|
||||
end: crate::plugin::TextPosition { row: 1, column: 6 },
|
||||
content: "before\ntarget\nafter\n".into(),
|
||||
};
|
||||
let map = |text: &str| {
|
||||
anchor.mapped_range(
|
||||
"working:new",
|
||||
Path::new("source.rs"),
|
||||
Side::After,
|
||||
&text
|
||||
.trim_end_matches('\n')
|
||||
.split('\n')
|
||||
.map(str::to_owned)
|
||||
.collect::<Vec<_>>(),
|
||||
text.ends_with('\n'),
|
||||
)
|
||||
};
|
||||
assert_eq!(
|
||||
map("changed\ntarget\nafter\n"),
|
||||
Some(anchor.start..anchor.end)
|
||||
);
|
||||
assert_eq!(
|
||||
map("inserted\nbefore\ntarget\nafter\n"),
|
||||
Some(
|
||||
crate::plugin::TextPosition { row: 2, column: 0 }..crate::plugin::TextPosition {
|
||||
row: 2,
|
||||
column: 6
|
||||
}
|
||||
)
|
||||
);
|
||||
assert!(map("before\ntargEt\nafter\n").is_none());
|
||||
assert!(map("before\nafter\n").is_none());
|
||||
assert!(map("before\ntarget\nafter\nbefore\ntarget\nafter\n").is_none());
|
||||
assert_eq!(map("target\nbefore\ntarget\nafter\n").unwrap().start.row, 2);
|
||||
assert_eq!(anchor.content, "before\ntarget\nafter\n");
|
||||
let partial = Anchor {
|
||||
content: "header\r\nprefix 👩💻e\u{301} suffix\r\nfooter\r\n".into(),
|
||||
start: crate::plugin::TextPosition { row: 1, column: 7 },
|
||||
end: crate::plugin::TextPosition { row: 1, column: 9 },
|
||||
..anchor.clone()
|
||||
};
|
||||
let moved = partial
|
||||
.mapped_range(
|
||||
"working:new",
|
||||
Path::new("source.rs"),
|
||||
Side::After,
|
||||
&[
|
||||
"inserted\r".into(),
|
||||
"header\r".into(),
|
||||
"longer prefix 👩💻e\u{301} suffix\r".into(),
|
||||
"footer\r".into(),
|
||||
],
|
||||
true,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
moved.start,
|
||||
crate::plugin::TextPosition { row: 2, column: 14 }
|
||||
);
|
||||
assert_eq!(
|
||||
moved.end,
|
||||
crate::plugin::TextPosition { row: 2, column: 16 }
|
||||
);
|
||||
assert!(
|
||||
partial
|
||||
.mapped_range(
|
||||
"other-commit",
|
||||
Path::new("source.rs"),
|
||||
Side::After,
|
||||
&[
|
||||
"header\r".into(),
|
||||
"prefix 👩💻e\u{301} suffix\r".into(),
|
||||
"footer\r".into()
|
||||
],
|
||||
true
|
||||
)
|
||||
.is_none()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn persistence_validates_anchors_and_preserves_files_on_failure() {
|
||||
let directory = directory();
|
||||
@@ -413,27 +504,39 @@ fn persistence_validates_anchors_and_preserves_files_on_failure() {
|
||||
assert_eq!(loaded.comments, review.comments);
|
||||
assert_eq!(loaded.verdict, review.verdict);
|
||||
let anchor = &loaded.comments[0].anchor;
|
||||
assert!(!anchor.matches_lines(
|
||||
"working:other",
|
||||
Path::new("source.rs"),
|
||||
Side::After,
|
||||
&["first".into(), "last".into()],
|
||||
true
|
||||
));
|
||||
assert!(anchor.matches_lines(
|
||||
"working:immutable",
|
||||
Path::new("source.rs"),
|
||||
Side::After,
|
||||
&["first".into(), "last".into()],
|
||||
true
|
||||
));
|
||||
assert!(!anchor.matches_lines(
|
||||
"working:immutable",
|
||||
Path::new("source.rs"),
|
||||
Side::After,
|
||||
&["first".into(), "last".into()],
|
||||
false
|
||||
));
|
||||
assert!(
|
||||
anchor
|
||||
.mapped_range(
|
||||
"working:other",
|
||||
Path::new("source.rs"),
|
||||
Side::After,
|
||||
&["first".into(), "last".into()],
|
||||
true
|
||||
)
|
||||
.is_some()
|
||||
);
|
||||
assert!(
|
||||
anchor
|
||||
.mapped_range(
|
||||
"working:immutable",
|
||||
Path::new("source.rs"),
|
||||
Side::After,
|
||||
&["first".into(), "last".into()],
|
||||
true
|
||||
)
|
||||
.is_some()
|
||||
);
|
||||
assert!(
|
||||
anchor
|
||||
.mapped_range(
|
||||
"working:immutable",
|
||||
Path::new("source.rs"),
|
||||
Side::After,
|
||||
&["first".into(), "last".into()],
|
||||
false
|
||||
)
|
||||
.is_none()
|
||||
);
|
||||
loaded.summary = "Updated".into();
|
||||
loaded.save(&path).unwrap();
|
||||
assert_eq!(Review::load(&path, &root).unwrap().summary, "Updated");
|
||||
|
||||
Reference in New Issue
Block a user