diff --git a/src/changes.rs b/src/changes.rs index 0b314fa3b..c1855c9f1 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -2,8 +2,6 @@ use rustc_hash::FxHashMap; use crate::syntax::Syntax; - - #[derive(PartialEq, Eq, Clone, Copy)] pub enum ChangeKind<'a> { Unchanged(&'a Syntax<'a>), @@ -16,3 +14,30 @@ pub type ChangeMap<'a> = FxHashMap<&'a Syntax<'a>, ChangeKind<'a>>; pub fn new_change_map<'a>() -> ChangeMap<'a> { FxHashMap::default() } + +pub fn insert_deep_unchanged<'a>( + node: &'a Syntax<'a>, + opposite_node: &'a Syntax<'a>, + change_map: &mut ChangeMap<'a>, +) { + change_map.insert(node, ChangeKind::Unchanged(opposite_node)); + + match (node, opposite_node) { + ( + Syntax::List { + children: node_children, + .. + }, + Syntax::List { + children: opposite_children, + .. + }, + ) => { + for (child, opposite_child) in node_children.iter().zip(opposite_children) { + insert_deep_unchanged(child, opposite_child, change_map); + } + } + (Syntax::Atom { .. }, Syntax::Atom { .. }) => {} + _ => unreachable!("Unchanged nodes should be both lists, or both atoms"), + } +} diff --git a/src/dijkstra.rs b/src/dijkstra.rs index b408fcd0d..eadfa33d2 100644 --- a/src/dijkstra.rs +++ b/src/dijkstra.rs @@ -4,8 +4,8 @@ use std::{cmp::Reverse, env}; use crate::{ - changes::ChangeKind, - graph::{change_kinds, mark_route, neighbours, Edge, Vertex}, + changes::ChangeMap, + graph::{mark_route, neighbours, populate_change_map, Edge, Vertex}, syntax::Syntax, }; use itertools::Itertools; @@ -138,24 +138,10 @@ fn tree_count(root: Option<&Syntax>) -> u32 { count } -pub fn syntax_changed<'a>( +pub fn mark_syntax<'a>( lhs_syntax: Option<&'a Syntax<'a>>, rhs_syntax: Option<&'a Syntax<'a>>, -) -> FxHashMap<&'a Syntax<'a>, ChangeKind<'a>> { - info!( - "LHS nodes: {} ({} toplevel), RHS nodes: {} ({} toplevel)", - node_count(lhs_syntax), - tree_count(lhs_syntax), - node_count(rhs_syntax), - tree_count(rhs_syntax), - ); - - let start = Vertex::new(lhs_syntax, rhs_syntax); - let route = shortest_path(start); - change_kinds(&route) -} - -pub fn mark_syntax<'a>(lhs_syntax: Option<&'a Syntax<'a>>, rhs_syntax: Option<&'a Syntax<'a>>) { +) -> ChangeMap<'a> { info!( "LHS nodes: {} ({} toplevel), RHS nodes: {} ({} toplevel)", node_count(lhs_syntax), @@ -167,15 +153,18 @@ pub fn mark_syntax<'a>(lhs_syntax: Option<&'a Syntax<'a>>, rhs_syntax: Option<&' let start = Vertex::new(lhs_syntax, rhs_syntax); let route = shortest_path(start); mark_route(&route); + + populate_change_map(&route) } #[cfg(test)] mod tests { use super::*; use crate::{ + changes::ChangeKind, graph::Edge::*, positions::SingleLineSpan, - syntax::{init_all_info, AtomKind, ChangeKind}, + syntax::{init_all_info, AtomKind}, }; use itertools::Itertools; @@ -574,7 +563,7 @@ mod tests { let rhs = Syntax::new_atom(&arena, pos_helper(1), "foo", AtomKind::Normal); init_all_info(&[lhs], &[rhs]); - mark_syntax(Some(lhs), Some(rhs)); + let _change_map = mark_syntax(Some(lhs), Some(rhs)); assert_eq!(lhs.change(), Some(ChangeKind::Unchanged(rhs))); assert_eq!(rhs.change(), Some(ChangeKind::Unchanged(lhs))); } @@ -586,7 +575,7 @@ mod tests { let rhs = Syntax::new_atom(&arena, pos_helper(1), "bar", AtomKind::Normal); init_all_info(&[lhs], &[rhs]); - mark_syntax(Some(lhs), Some(rhs)); + let _change_map = mark_syntax(Some(lhs), Some(rhs)); assert_eq!(lhs.change(), Some(ChangeKind::Novel)); assert_eq!(rhs.change(), Some(ChangeKind::Novel)); } diff --git a/src/graph.rs b/src/graph.rs index 35c0388f9..62ff3d10e 100644 --- a/src/graph.rs +++ b/src/graph.rs @@ -9,7 +9,7 @@ use std::{ }; use strsim::normalized_levenshtein; -use crate::changes::{ChangeKind, ChangeMap, new_change_map}; +use crate::changes::{insert_deep_unchanged, new_change_map, ChangeKind, ChangeMap}; use crate::syntax::{AtomKind, Syntax}; use Edge::*; @@ -589,34 +589,7 @@ pub fn neighbours<'a>(v: &Vertex<'a>, buf: &mut [Option<(Edge, Vertex<'a>)>]) { ); } -fn set_deep_unchanged<'a>( - node: &'a Syntax<'a>, - opposite_node: &'a Syntax<'a>, - changes: &mut ChangeMap<'a>, -) { - changes.insert(node, ChangeKind::Unchanged(opposite_node)); - - match (node, opposite_node) { - ( - Syntax::List { - children: node_children, - .. - }, - Syntax::List { - children: opposite_children, - .. - }, - ) => { - for (child, opposite_child) in node_children.iter().zip(opposite_children) { - set_deep_unchanged(child, opposite_child, changes); - } - } - (Syntax::Atom { .. }, Syntax::Atom { .. }) => {} - _ => unreachable!("Unchanged nodes should be both lists, or both atoms"), - } -} - -pub fn change_kinds<'a>(route: &[(Edge, Vertex<'a>)]) -> ChangeMap<'a> { +pub fn populate_change_map<'a>(route: &[(Edge, Vertex<'a>)]) -> ChangeMap<'a> { let mut res = new_change_map(); for (e, v) in route { @@ -629,8 +602,8 @@ pub fn change_kinds<'a>(route: &[(Edge, Vertex<'a>)]) -> ChangeMap<'a> { let lhs = v.lhs_syntax.unwrap(); let rhs = v.rhs_syntax.unwrap(); - set_deep_unchanged(lhs, rhs, &mut res); - set_deep_unchanged(rhs, lhs, &mut res); + insert_deep_unchanged(lhs, rhs, &mut res); + insert_deep_unchanged(rhs, lhs, &mut res); } EnterUnchangedDelimiter { .. } => { // No change on the outer delimiter, but children may diff --git a/src/main.rs b/src/main.rs index a22fb18ac..0403bfa8a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -39,6 +39,7 @@ mod unchanged; extern crate log; use crate::hunks::{matched_pos_to_hunks, merge_adjacent}; +use changes::new_change_map; use context::opposite_positions; use files::read_files_or_die; use guess_language::guess; @@ -305,11 +306,12 @@ fn diff_file_content( let rhs = tsp::parse(&arena, &rhs_src, &ts_lang); init_all_info(&lhs, &rhs); - + + let mut change_map = new_change_map(); let possibly_changed = if env::var("DFT_DBG_KEEP_UNCHANGED").is_ok() { vec![(lhs.clone(), rhs.clone())] } else { - unchanged::mark_unchanged(&lhs, &rhs) + unchanged::mark_unchanged(&lhs, &rhs, &mut change_map) }; let possibly_changed_max = max_num_nodes(&possibly_changed); diff --git a/src/unchanged.rs b/src/unchanged.rs index ec7401573..b6aef6542 100644 --- a/src/unchanged.rs +++ b/src/unchanged.rs @@ -1,6 +1,4 @@ -use rustc_hash::FxHashMap; - -use crate::changes::{new_change_map, ChangeKind, ChangeMap}; +use crate::changes::{ChangeKind, ChangeMap}; use crate::myers_diff; use crate::syntax::Syntax; @@ -14,16 +12,14 @@ const MOSTLY_UNCHANGED_MIN_COMMON_CHILDREN: usize = 4; pub fn mark_unchanged<'a>( lhs_nodes: &[&'a Syntax<'a>], rhs_nodes: &[&'a Syntax<'a>], + change_map: &mut ChangeMap<'a>, ) -> Vec<(Vec<&'a Syntax<'a>>, Vec<&'a Syntax<'a>>)> { - let mut change_kinds = new_change_map(); - - let (_, lhs_nodes, rhs_nodes) = - shrink_unchanged_at_ends(lhs_nodes, rhs_nodes, &mut change_kinds); + let (_, lhs_nodes, rhs_nodes) = shrink_unchanged_at_ends(lhs_nodes, rhs_nodes, change_map); let mut res = vec![]; for (lhs_nodes, rhs_nodes) in split_mostly_unchanged_toplevel(&lhs_nodes, &rhs_nodes) { let (_, lhs_nodes, rhs_nodes) = - shrink_unchanged_at_ends(&lhs_nodes, &rhs_nodes, &mut change_kinds); + shrink_unchanged_at_ends(&lhs_nodes, &rhs_nodes, change_map); res.extend(split_unchanged(&lhs_nodes, &rhs_nodes)); } @@ -343,7 +339,7 @@ fn as_singleton_list_children<'a>( fn shrink_unchanged_delimiters<'a>( lhs_nodes: &[&'a Syntax<'a>], rhs_nodes: &[&'a Syntax<'a>], - changes: &mut ChangeMap<'a>, + change_map: &mut ChangeMap<'a>, ) -> (bool, Vec<&'a Syntax<'a>>, Vec<&'a Syntax<'a>>) { if let ( [Syntax::List { @@ -362,7 +358,7 @@ fn shrink_unchanged_delimiters<'a>( { if lhs_open == rhs_open && lhs_close == rhs_close { let (changed_later, lhs_shrunk_nodes, rhs_shrunk_nodes) = - shrink_unchanged_at_ends(lhs_children, rhs_children, changes); + shrink_unchanged_at_ends(lhs_children, rhs_children, change_map); if changed_later { lhs_nodes[0].set_change(ChangeKind::Unchanged(rhs_nodes[0])); rhs_nodes[0].set_change(ChangeKind::Unchanged(lhs_nodes[0])); @@ -382,7 +378,7 @@ fn shrink_unchanged_delimiters<'a>( fn shrink_unchanged_at_ends<'a>( lhs_nodes: &[&'a Syntax<'a>], rhs_nodes: &[&'a Syntax<'a>], - changes: &mut ChangeMap<'a>, + change_map: &mut ChangeMap<'a>, ) -> (bool, Vec<&'a Syntax<'a>>, Vec<&'a Syntax<'a>>) { let mut lhs_nodes = lhs_nodes; let mut rhs_nodes = rhs_nodes; @@ -420,7 +416,7 @@ fn shrink_unchanged_at_ends<'a>( if lhs_nodes.len() == 1 && rhs_nodes.len() == 1 { let (changed_later, lhs_nodes, rhs_nodes) = - shrink_unchanged_delimiters(lhs_nodes, rhs_nodes, changes); + shrink_unchanged_delimiters(lhs_nodes, rhs_nodes, change_map); (changed || changed_later, lhs_nodes, rhs_nodes) } else { (changed, Vec::from(lhs_nodes), Vec::from(rhs_nodes))