mirror of https://github.com/Wilfred/difftastic/
parent
a2dc0b5109
commit
94e968b660
@ -0,0 +1,95 @@
|
|||||||
|
use crate::syntax::{ChangeKind, Syntax};
|
||||||
|
|
||||||
|
pub fn skip_unchanged_at_ends<'a>(
|
||||||
|
lhs_nodes: &[&'a Syntax<'a>],
|
||||||
|
rhs_nodes: &[&'a Syntax<'a>],
|
||||||
|
) -> (Vec<&'a Syntax<'a>>, Vec<&'a Syntax<'a>>) {
|
||||||
|
let mut lhs_nodes = lhs_nodes;
|
||||||
|
let mut rhs_nodes = rhs_nodes;
|
||||||
|
|
||||||
|
while let (Some(lhs_node), Some(rhs_node)) = (lhs_nodes.first(), rhs_nodes.first()) {
|
||||||
|
if lhs_node.content_id() == rhs_node.content_id() {
|
||||||
|
skip_pair(lhs_node, rhs_node);
|
||||||
|
|
||||||
|
lhs_nodes = &lhs_nodes[1..];
|
||||||
|
rhs_nodes = &rhs_nodes[1..];
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while let (Some(lhs_node), Some(rhs_node)) = (lhs_nodes.last(), rhs_nodes.last()) {
|
||||||
|
if lhs_node.content_id() == rhs_node.content_id() {
|
||||||
|
skip_pair(lhs_node, rhs_node);
|
||||||
|
|
||||||
|
lhs_nodes = &lhs_nodes[..lhs_nodes.len() - 1];
|
||||||
|
rhs_nodes = &rhs_nodes[..rhs_nodes.len() - 1];
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(Vec::from(lhs_nodes), Vec::from(rhs_nodes))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn skip_pair<'a>(lhs_node: &'a Syntax<'a>, rhs_node: &'a Syntax<'a>) {
|
||||||
|
lhs_node.set_change_deep(ChangeKind::Unchanged(rhs_node));
|
||||||
|
rhs_node.set_change_deep(ChangeKind::Unchanged(lhs_node));
|
||||||
|
|
||||||
|
detach(lhs_node);
|
||||||
|
detach(rhs_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn detach(node: &Syntax) {
|
||||||
|
if let Some(next_node) = node.next() {
|
||||||
|
node.info().next.set(None);
|
||||||
|
next_node.info().prev.set(None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use crate::{
|
||||||
|
guess_language,
|
||||||
|
syntax::init_info,
|
||||||
|
tree_sitter_parser::{from_language, parse},
|
||||||
|
};
|
||||||
|
use typed_arena::Arena;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_unchanged_at_start() {
|
||||||
|
let arena = Arena::new();
|
||||||
|
let config = from_language(guess_language::Language::EmacsLisp);
|
||||||
|
|
||||||
|
let lhs_nodes = parse(&arena, "unchanged A B", &config);
|
||||||
|
let rhs_nodes = parse(&arena, "unchanged X", &config);
|
||||||
|
init_info(&lhs_nodes, &rhs_nodes);
|
||||||
|
|
||||||
|
let (lhs_after_skip, rhs_after_skip) = skip_unchanged_at_ends(&lhs_nodes, &rhs_nodes);
|
||||||
|
|
||||||
|
assert_eq!(lhs_nodes[0].change(), Some(ChangeKind::Unchanged(rhs_nodes[0])));
|
||||||
|
assert_eq!(rhs_nodes[0].change(), Some(ChangeKind::Unchanged(lhs_nodes[0])));
|
||||||
|
|
||||||
|
assert_eq!(lhs_after_skip.len(), 2);
|
||||||
|
assert_eq!(rhs_after_skip.len(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_unchanged_at_end() {
|
||||||
|
let arena = Arena::new();
|
||||||
|
let config = from_language(guess_language::Language::EmacsLisp);
|
||||||
|
|
||||||
|
let lhs_nodes = parse(&arena, "A B unchanged", &config);
|
||||||
|
let rhs_nodes = parse(&arena, "X unchanged", &config);
|
||||||
|
init_info(&lhs_nodes, &rhs_nodes);
|
||||||
|
|
||||||
|
let (lhs_after_skip, rhs_after_skip) = skip_unchanged_at_ends(&lhs_nodes, &rhs_nodes);
|
||||||
|
|
||||||
|
assert_eq!(lhs_nodes[2].change(), Some(ChangeKind::Unchanged(rhs_nodes[1])));
|
||||||
|
assert_eq!(rhs_nodes[1].change(), Some(ChangeKind::Unchanged(lhs_nodes[2])));
|
||||||
|
|
||||||
|
assert_eq!(lhs_after_skip.len(), 2);
|
||||||
|
assert_eq!(rhs_after_skip.len(), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue