From 094133fe10c6eb785d0455b75a37160af36d6a98 Mon Sep 17 00:00:00 2001 From: Wilfred Hughes Date: Wed, 7 Jul 2021 23:45:22 -0700 Subject: [PATCH] Ensure that we display all context lines, even if matched pairs are unordered --- CHANGELOG.md | 3 +++ src/syntax.rs | 32 ++++++++++++++++++++++++++------ 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eaf95f474..9429b1bf9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ ## 0.4 (unreleased) +Fixed an issue where complex diffs would not display some unchanged +lines. + ## 0.3 Diffs are now displayed with unchanged lines aligned to the other side. diff --git a/src/syntax.rs b/src/syntax.rs index cb6750da3..6bfae3210 100644 --- a/src/syntax.rs +++ b/src/syntax.rs @@ -5,7 +5,7 @@ use itertools::{EitherOrBoth, Itertools}; use std::cell::Cell; use std::cmp::min; use std::collections::hash_map::DefaultHasher; -use std::collections::{HashMap, HashSet}; +use std::collections::HashMap; use std::fmt; use std::hash::{Hash, Hasher}; use typed_arena::Arena; @@ -556,15 +556,16 @@ pub fn aligned_lines( rhs_lines: &[LineNumber], lhs_line_matches: &HashMap, ) -> Vec<(Option, Option)> { - let mut rhs_lines_available: HashSet<_> = rhs_lines.iter().collect(); - - // For every LHS line, if there is a RHS line that included in - // `rhs_lines` and hasn't yet been paired up, add it to matched_lines. + let mut rhs_highest_matched = rhs_lines.first().unwrap().number - 1; + // For every LHS line, if there is a RHS line that is included in + // `rhs_lines` and hasn't yet been paired up, add it to + // matched_lines. let mut matched_lines = vec![]; for lhs_line in lhs_lines { if let Some(rhs_line) = lhs_line_matches.get(lhs_line) { - if rhs_lines_available.remove(&rhs_line) { + if rhs_line.number > rhs_highest_matched { matched_lines.push((lhs_line, rhs_line)); + rhs_highest_matched = rhs_line.number; } } } @@ -733,6 +734,25 @@ mod tests { ); } + #[test] + fn test_aligned_out_of_order() { + let lhs_lines: Vec = vec![1.into(), 2.into()]; + let rhs_lines: Vec = vec![11.into(), 12.into()]; + + let mut line_matches: HashMap = HashMap::new(); + line_matches.insert(2.into(), 11.into()); + line_matches.insert(1.into(), 12.into()); + + assert_eq!( + aligned_lines(&lhs_lines, &rhs_lines, &line_matches), + vec![ + (None, Some(11.into())), + (Some(1.into()), Some(12.into())), + (Some(2.into()), None) + ] + ); + } + /// Ensure that we assign prev_opposite_pos even if the change is on the first node. #[test] fn test_prev_opposite_pos_first_node() {