Explore two graph nodes for each parenthesis position

This produces substantially better diff results, and fixes the 'last
item in the list shown as changed' problem.

This can produce slower diffing. typing_before.ml takes 10% more
instructions and slow_before.rs takes 110% more instructions.
pull/341/head
Wilfred Hughes 2022-08-21 15:52:05 +07:00
parent a71d6118cf
commit c957818514
3 changed files with 38 additions and 10 deletions

@ -1,5 +1,11 @@
## 0.33 (unreleased)
### Diffing
Difftastic now explores 2x more parenthesis nesting
possibilities. This can make diffing slower, but produces
substantially better results.
### Parsing
Added support for CMake.

@ -140,13 +140,13 @@ sample_files/ruby_before.rb sample_files/ruby_after.rb
4a9847a91e32ec6afdc2f0b01e28d2d6 -
sample_files/scala_before.scala sample_files/scala_after.scala
b276168d30704b4242fc82dc1f8382d8 -
200c6ae867dfbfb4337efd5432d81431 -
sample_files/Session_before.kt sample_files/Session_after.kt
46994b58bb24200f82866951013f03ce -
sample_files/simple_before.js sample_files/simple_after.js
4fa7016f884e76dddba4cab12cab8c61 -
45fef08587e93e19a3bd76299aa7c142 -
sample_files/simple_before.txt sample_files/simple_after.txt
4b653ebe89321835c35722dd065cf6a2 -
@ -155,7 +155,7 @@ sample_files/slider_before.rs sample_files/slider_after.rs
50e1df5af0bf4a1fa7211e079196f1a9 -
sample_files/slow_before.rs sample_files/slow_after.rs
e8e7521e32766879f7219788a113005a -
1090ccf266b6e9fd22f2585f9fa350a9 -
sample_files/small_before.js sample_files/small_after.js
27bcac13aa17141718a3e6b8c0ac8f47 -
@ -179,7 +179,7 @@ sample_files/toml_before.toml sample_files/toml_after.toml
1e2de7235c339b07a0784498453e896c -
sample_files/typing_before.ml sample_files/typing_after.ml
ceba89e4ffc8406454d337638c7d45e6 -
75d0b1bec67a58b17c17a6438c447252 -
sample_files/whitespace_before.tsx sample_files/whitespace_after.tsx
c4151c5a44b11e04fd11c2594597ed33 -

@ -101,7 +101,7 @@ impl<'a, 'b> Hash for Vertex<'a, 'b> {
}
/// Tracks entering syntax List nodes.
#[derive(Clone)]
#[derive(Clone, PartialEq)]
enum EnteredDelimiter<'a> {
/// If we've entered the LHS or RHS separately, we can pop either
/// side independently.
@ -340,13 +340,35 @@ impl Edge {
fn allocate_if_new<'syn, 'b>(
v: Vertex<'syn, 'b>,
alloc: &'b Bump,
seen: &mut FxHashMap<&Vertex<'syn, 'b>, &'b Vertex<'syn, 'b>>,
seen: &mut FxHashMap<&Vertex<'syn, 'b>, Vec<&'b Vertex<'syn, 'b>>>,
) -> &'b Vertex<'syn, 'b> {
match seen.get(&v) {
Some(existing) => *existing,
match seen.get_mut(&v) {
Some(existing) => {
// Don't explore more than two possible parenthesis
// nestings for each syntax node pair.
if let Some(allocated) = existing.last() {
if existing.len() >= 2 {
return *allocated;
}
}
// If we have seen exactly this graph node before, even
// considering parenthesis matching, return it.
for existing_node in existing.iter() {
if existing_node.parents == v.parents {
return existing_node;
}
}
// We haven't reached the graph node limit yet, allocate a
// new one.
let allocated = alloc.alloc(v);
existing.push(allocated);
allocated
}
None => {
let allocated = alloc.alloc(v);
seen.insert(allocated, allocated);
seen.insert(allocated, vec![allocated]);
allocated
}
}
@ -357,7 +379,7 @@ fn allocate_if_new<'syn, 'b>(
pub fn get_set_neighbours<'syn, 'b>(
v: &Vertex<'syn, 'b>,
alloc: &'b Bump,
seen: &mut FxHashMap<&Vertex<'syn, 'b>, &'b Vertex<'syn, 'b>>,
seen: &mut FxHashMap<&Vertex<'syn, 'b>, Vec<&'b Vertex<'syn, 'b>>>,
) -> Vec<(Edge, &'b Vertex<'syn, 'b>)> {
match &*v.neighbours.borrow() {
Some(neighbours) => return neighbours.clone(),