diff --git a/src/in_diff.rs b/src/in_diff.rs index 6c9c4128..6fbfab7f 100644 --- a/src/in_diff.rs +++ b/src/in_diff.rs @@ -125,8 +125,41 @@ fn affected_lines(patch: &Patch) -> Vec { r } +/// Recreate a partial view of the new file from a Patch. +/// +/// This contains lines present as adedd or context. Typically not all context +/// will be covered, so the output is a list of line numbers and their text. +fn partial_new_file<'d>(patch: &Patch<'d>) -> Vec<(usize, &'d str)> { + let mut r: Vec<(usize, &'d str)> = Vec::new(); + for hunk in &patch.hunks { + let mut lineno: usize = hunk.new_range.start.try_into().unwrap(); + for line in &hunk.lines { + match line { + Line::Context(text) | Line::Add(text) => { + debug_assert!(lineno >= 1, "{lineno}"); + debug_assert!( + r.last().map_or(true, |last| last.0 < lineno), + "{lineno} {r:?}" + ); + r.push((lineno, text)); + lineno += 1; + } + Line::Remove(_) => {} + } + } + debug_assert_eq!( + lineno, + (hunk.new_range.start + hunk.new_range.count) as usize, + "Wrong number of resulting lines?" + ); + } + r +} + #[cfg(test)] mod test_super { + use std::fs::read_to_string; + use assert_cmd::assert; use pretty_assertions::assert_eq; use similar::TextDiff; @@ -170,7 +203,7 @@ index eb42779..a0091b7 100644 TextDiff::from_lines(old, new) .unified_diff() .context_radius(2) - .header("a/file", "b/file") + .header("a/file.rs", "b/file.rs") .to_string() } @@ -263,4 +296,19 @@ index eb42779..a0091b7 100644 } } } + + #[test] + fn reconstruct_partial_new_file() { + let old = read_to_string("testdata/tree/diff0/src/lib.rs").unwrap(); + let new = read_to_string("testdata/tree/diff1/src/lib.rs").unwrap(); + let diff = make_diff(&old, &new); + let patch = Patch::from_single(&diff).unwrap(); + let reconstructed = partial_new_file(&patch); + println!("{reconstructed:#?}"); + assert_eq!(reconstructed.len(), 16); + let new_lines = new.lines().collect_vec(); + for (lineno, text) in reconstructed { + assert_eq!(text, new_lines[lineno - 1]); + } + } } diff --git a/src/snapshots/cargo_mutants__visit__test__expected_mutants_for_own_source_tree.snap b/src/snapshots/cargo_mutants__visit__test__expected_mutants_for_own_source_tree.snap index 9cb1d00a..d7b9bf68 100644 --- a/src/snapshots/cargo_mutants__visit__test__expected_mutants_for_own_source_tree.snap +++ b/src/snapshots/cargo_mutants__visit__test__expected_mutants_for_own_source_tree.snap @@ -139,6 +139,11 @@ src/in_diff.rs: replace strip_patch_path -> &Utf8Path with &Default::default() src/in_diff.rs: replace affected_lines -> Vec with vec![] src/in_diff.rs: replace affected_lines -> Vec with vec![0] src/in_diff.rs: replace affected_lines -> Vec with vec![1] +src/in_diff.rs: replace partial_new_file -> Vec<(usize, &'d str)> with vec![] +src/in_diff.rs: replace partial_new_file -> Vec<(usize, &'d str)> with vec![(0, "")] +src/in_diff.rs: replace partial_new_file -> Vec<(usize, &'d str)> with vec![(0, "xyzzy")] +src/in_diff.rs: replace partial_new_file -> Vec<(usize, &'d str)> with vec![(1, "")] +src/in_diff.rs: replace partial_new_file -> Vec<(usize, &'d str)> with vec![(1, "xyzzy")] src/interrupt.rs: replace install_handler with () src/lab.rs: replace test_mutants -> Result with Ok(Default::default()) src/lab.rs: replace test_mutants -> Result with Err(::anyhow::anyhow!("mutated!"))