Ensure files with no common content are aligned

empty_delimiters_heuristic
Wilfred Hughes 2024-07-20 23:09:06 +07:00
parent 1e8be4558b
commit 92fa3fb3de
6 changed files with 80 additions and 5 deletions

@ -1,5 +1,10 @@
## 0.60 (unreleased) ## 0.60 (unreleased)
### Display
Fixed an issue where files with no common content would show duplicate
hunks.
## 0.59 (released 20th July 2024) ## 0.59 (released 20th July 2024)
### Diffing ### Diffing

@ -10,6 +10,9 @@ sample_files/added_line_1.txt sample_files/added_line_2.txt
sample_files/align_footer_1.txt sample_files/align_footer_2.txt sample_files/align_footer_1.txt sample_files/align_footer_2.txt
d640bd2de31e56a39f0efb92aff0f379 - d640bd2de31e56a39f0efb92aff0f379 -
sample_files/all_changed_1.js sample_files/all_changed_2.js
40eb536d8b626e27ae227a090fb05f25 -
sample_files/apex_1.cls sample_files/apex_2.cls sample_files/apex_1.cls sample_files/apex_2.cls
8e477350907734ac4d5201752523dff3 - 8e477350907734ac4d5201752523dff3 -
@ -134,7 +137,7 @@ sample_files/load_1.js sample_files/load_2.js
22365043359164f717d495336d86b996 - 22365043359164f717d495336d86b996 -
sample_files/long_line_1.txt sample_files/long_line_2.txt sample_files/long_line_1.txt sample_files/long_line_2.txt
40e22d364bb714421eec24b8ef808f01 - 7fc50bd547f0c20fda89a1931e5eb61e -
sample_files/lua_1.lua sample_files/lua_2.lua sample_files/lua_1.lua sample_files/lua_2.lua
8318115b642361955346cc620bc3ad86 - 8318115b642361955346cc620bc3ad86 -
@ -227,7 +230,7 @@ sample_files/simple_1.scss sample_files/simple_2.scss
265261e79df78abfc09392d72a0273d8 - 265261e79df78abfc09392d72a0273d8 -
sample_files/simple_1.txt sample_files/simple_2.txt sample_files/simple_1.txt sample_files/simple_2.txt
416d05b8a02e41cb70b78d28cd3153d9 - 6fd97a544afd0a3be7eebba75f82f696 -
sample_files/slider_1.rs sample_files/slider_2.rs sample_files/slider_1.rs sample_files/slider_2.rs
d10128f3d9ffc4a8670f417a9371bacc - d10128f3d9ffc4a8670f417a9371bacc -

@ -1,7 +1,7 @@
//! A fallback "parser" for plain text. //! A fallback "parser" for plain text.
use lazy_static::lazy_static; use lazy_static::lazy_static;
use line_numbers::LinePositions; use line_numbers::{LinePositions, SingleLineSpan};
use regex::Regex; use regex::Regex;
use crate::words::split_words; use crate::words::split_words;
@ -118,9 +118,12 @@ pub(crate) fn change_positions(lhs_src: &str, rhs_src: &str) -> Vec<MatchedPos>
let mut rhs_offset = 0; let mut rhs_offset = 0;
let mut mps = vec![]; let mut mps = vec![];
let mut seen_unchanged = false;
for (kind, lhs_lines, rhs_lines) in changed_parts(lhs_src, rhs_src) { for (kind, lhs_lines, rhs_lines) in changed_parts(lhs_src, rhs_src) {
match kind { match kind {
TextChangeKind::Unchanged => { TextChangeKind::Unchanged => {
seen_unchanged = true;
for (lhs_line, rhs_line) in lhs_lines.iter().zip(rhs_lines) { for (lhs_line, rhs_line) in lhs_lines.iter().zip(rhs_lines) {
let lhs_pos = let lhs_pos =
lhs_lp.from_region(lhs_offset, lhs_offset + line_len_in_bytes(lhs_line)); lhs_lp.from_region(lhs_offset, lhs_offset + line_len_in_bytes(lhs_line));
@ -210,6 +213,33 @@ pub(crate) fn change_positions(lhs_src: &str, rhs_src: &str) -> Vec<MatchedPos>
} }
} }
// If there are no unchanged items, insert a dummy item at the
// beginning of both files with a width of zero. This gives
// display something to use when aligning.
if !seen_unchanged {
let lhs_pos = SingleLineSpan {
line: 0.into(),
start_col: 0,
end_col: 0,
};
let rhs_pos = SingleLineSpan {
line: 0.into(),
start_col: 0,
end_col: 0,
};
mps.insert(
0,
MatchedPos {
kind: MatchKind::UnchangedToken {
highlight: TokenKind::Atom(AtomKind::Normal),
self_pos: vec![lhs_pos],
opposite_pos: vec![rhs_pos],
},
pos: lhs_pos,
},
);
}
mps mps
} }

@ -875,7 +875,37 @@ pub(crate) fn change_positions<'a>(
change_map: &ChangeMap<'a>, change_map: &ChangeMap<'a>,
) -> Vec<MatchedPos> { ) -> Vec<MatchedPos> {
let mut positions = Vec::new(); let mut positions = Vec::new();
change_positions_(nodes, change_map, &mut positions); let mut seen_unchanged = false;
change_positions_(nodes, change_map, &mut positions, &mut seen_unchanged);
// If there are no unchanged items, insert a dummy item at the
// beginning of both files with a width of zero. This gives
// display something to use when aligning.
if !seen_unchanged {
let lhs_pos = SingleLineSpan {
line: 0.into(),
start_col: 0,
end_col: 0,
};
let rhs_pos = SingleLineSpan {
line: 0.into(),
start_col: 0,
end_col: 0,
};
positions.insert(
0,
MatchedPos {
kind: MatchKind::UnchangedToken {
highlight: TokenKind::Atom(AtomKind::Normal),
self_pos: vec![lhs_pos],
opposite_pos: vec![rhs_pos],
},
pos: lhs_pos,
},
);
}
positions positions
} }
@ -883,12 +913,17 @@ fn change_positions_<'a>(
nodes: &[&'a Syntax<'a>], nodes: &[&'a Syntax<'a>],
change_map: &ChangeMap<'a>, change_map: &ChangeMap<'a>,
positions: &mut Vec<MatchedPos>, positions: &mut Vec<MatchedPos>,
seen_unchanged: &mut bool,
) { ) {
for node in nodes { for node in nodes {
let change = change_map let change = change_map
.get(node) .get(node)
.unwrap_or_else(|| panic!("Should have changes set in all nodes: {:#?}", node)); .unwrap_or_else(|| panic!("Should have changes set in all nodes: {:#?}", node));
if matches!(change, ChangeKind::Unchanged(_)) {
*seen_unchanged = true;
}
match node { match node {
List { List {
open_position, open_position,
@ -903,7 +938,7 @@ fn change_positions_<'a>(
false, false,
)); ));
change_positions_(children, change_map, positions); change_positions_(children, change_map, positions, seen_unchanged);
positions.extend(MatchedPos::new( positions.extend(MatchedPos::new(
change, change,