Skip to content

Commit

Permalink
feat: Consider node position in Tree Matching
Browse files Browse the repository at this point in the history
  • Loading branch information
jpedroh committed Nov 9, 2023
1 parent cb8dd75 commit 411671d
Show file tree
Hide file tree
Showing 10 changed files with 570 additions and 62 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion bin/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ fn main() {

let right = r#"
public interface Repository {
void create(Pessoa pessoa);
void delete(Pessoa pessoa);
void remove(Pessoa pessoa);
void insert(Pessoa pessoa);
void create(Pessoa pessoa);
}
"#;

Expand Down
6 changes: 6 additions & 0 deletions matching/src/matchings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,17 @@ impl<'a> IntoIterator for Matchings<'a> {

#[cfg(test)]
mod tests {
use model::Point;

use super::*;

#[test]
fn returns_none_if_a_matching_for_the_node_is_not_found() {
let a_node = CSTNode::Terminal {
kind: "kind",
value: "value".into(),
start_position: Point { row: 0, column: 0 },
end_position: Point { row: 0, column: 5 },
};

assert_eq!(None, Matchings::empty().find_matching_for(&a_node))
Expand All @@ -99,6 +103,8 @@ mod tests {
let a_node = CSTNode::Terminal {
kind: "kind",
value: "value".into(),
start_position: Point { row: 0, column: 0 },
end_position: Point { row: 0, column: 5 },
};

let mut matchings = HashMap::new();
Expand Down
58 changes: 57 additions & 1 deletion matching/src/ordered_tree_matching.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ pub fn ordered_tree_matching<'a>(left: &'a CSTNode, right: &'a CSTNode) -> Match
CSTNode::NonTerminal {
kind: kind_left,
children: children_left,
..
},
CSTNode::NonTerminal {
kind: kind_right,
children: children_right,
..
},
) => {
let root_matching: usize = (kind_left == kind_right).into();
Expand Down Expand Up @@ -96,10 +98,12 @@ pub fn ordered_tree_matching<'a>(left: &'a CSTNode, right: &'a CSTNode) -> Match
CSTNode::Terminal {
kind: kind_left,
value: value_left,
..
},
CSTNode::Terminal {
kind: kind_right,
value: value_right,
..
},
) => {
let is_perfetch_match = kind_left == kind_right && value_left == value_right;
Expand All @@ -118,17 +122,21 @@ pub fn ordered_tree_matching<'a>(left: &'a CSTNode, right: &'a CSTNode) -> Match
#[cfg(test)]
mod tests {
use crate::{matching_entry::MatchingEntry, *};
use model::CSTNode;
use model::{CSTNode, Point};

#[test]
fn two_terminal_nodes_matches_with_a_score_of_one_if_they_have_the_same_kind_and_value() {
let left = CSTNode::Terminal {
kind: "kind",
value: "value".to_owned(),
start_position: Point { row: 0, column: 0 },
end_position: Point { row: 0, column: 5 },
};
let right = CSTNode::Terminal {
kind: "kind",
value: "value".to_owned(),
start_position: Point { row: 0, column: 0 },
end_position: Point { row: 0, column: 5 },
};

let matchings = ordered_tree_matching(&left, &right);
Expand All @@ -144,10 +152,14 @@ mod tests {
let left = CSTNode::Terminal {
kind: "kind",
value: "value_a".to_owned(),
start_position: Point { row: 0, column: 0 },
end_position: Point { row: 0, column: 7 },
};
let right = CSTNode::Terminal {
kind: "kind",
value: "value_b".to_owned(),
start_position: Point { row: 0, column: 0 },
end_position: Point { row: 0, column: 7 },
};

let matchings = ordered_tree_matching(&left, &right);
Expand All @@ -163,10 +175,14 @@ mod tests {
let left = CSTNode::Terminal {
kind: "kind_a",
value: "value".to_owned(),
start_position: Point { row: 0, column: 0 },
end_position: Point { row: 0, column: 5 },
};
let right = CSTNode::Terminal {
kind: "kind_b",
value: "value".to_owned(),
start_position: Point { row: 0, column: 0 },
end_position: Point { row: 0, column: 5 },
};

let matchings = ordered_tree_matching(&left, &right);
Expand All @@ -182,10 +198,14 @@ mod tests {
let left = CSTNode::Terminal {
kind: "kind_a",
value: "value_a".to_owned(),
start_position: Point { row: 0, column: 0 },
end_position: Point { row: 0, column: 7 },
};
let right = CSTNode::Terminal {
kind: "kind_b",
value: "value_a".to_owned(),
start_position: Point { row: 0, column: 0 },
end_position: Point { row: 0, column: 7 },
};

let matchings = ordered_tree_matching(&left, &right);
Expand All @@ -201,13 +221,19 @@ mod tests {
let child = CSTNode::Terminal {
kind: "kind_b",
value: "value_b".into(),
start_position: Point { row: 1, column: 0 },
end_position: Point { row: 1, column: 7 },
};
let left = CSTNode::NonTerminal {
kind: "kind_a",
start_position: Point { row: 0, column: 0 },
end_position: Point { row: 1, column: 7 },
children: vec![child.clone()],
};
let right = CSTNode::NonTerminal {
kind: "kind_a",
start_position: Point { row: 0, column: 0 },
end_position: Point { row: 1, column: 7 },
children: vec![child.clone()],
};

Expand All @@ -224,19 +250,27 @@ mod tests {
let left_child = CSTNode::Terminal {
kind: "kind_b",
value: "value_b".into(),
start_position: Point { row: 0, column: 0 },
end_position: Point { row: 0, column: 7 },
};
let right_child = CSTNode::Terminal {
kind: "kind_c".into(),
value: "value_c".into(),
start_position: Point { row: 1, column: 0 },
end_position: Point { row: 1, column: 7 },
};

let left = CSTNode::NonTerminal {
kind: "kind_a",
children: vec![left_child.clone()],
start_position: Point { row: 1, column: 0 },
end_position: Point { row: 0, column: 7 },
};
let right = CSTNode::NonTerminal {
kind: "kind_a",
children: vec![right_child.clone()],
start_position: Point { row: 1, column: 0 },
end_position: Point { row: 0, column: 7 },
};

let matchings = ordered_tree_matching(&left, &right);
Expand All @@ -252,18 +286,26 @@ mod tests {
let common_child = CSTNode::Terminal {
kind: "kind_b",
value: "value_b".into(),
start_position: Point { row: 0, column: 0 },
end_position: Point { row: 0, column: 7 },
};
let unique_right_child = CSTNode::Terminal {
kind: "kind_c".into(),
value: "value_c".into(),
start_position: Point { row: 0, column: 0 },
end_position: Point { row: 0, column: 7 },
};

let left = CSTNode::NonTerminal {
kind: "kind_a",
start_position: Point { row: 0, column: 0 },
end_position: Point { row: 0, column: 7 },
children: vec![common_child.clone()],
};
let right = CSTNode::NonTerminal {
kind: "kind_a",
start_position: Point { row: 0, column: 0 },
end_position: Point { row: 0, column: 7 },
children: vec![common_child.clone(), unique_right_child],
};

Expand All @@ -279,15 +321,21 @@ mod tests {
fn perfect_matching_deep_nodes() {
let common_child = CSTNode::Terminal {
kind: "kind_b",
start_position: Point { row: 0, column: 0 },
end_position: Point { row: 0, column: 7 },
value: "value_b".into(),
};

let left = CSTNode::NonTerminal {
kind: "kind_a",
start_position: Point { row: 0, column: 0 },
end_position: Point { row: 0, column: 7 },
children: vec![common_child.clone()],
};
let right = CSTNode::NonTerminal {
kind: "kind_a",
start_position: Point { row: 0, column: 0 },
end_position: Point { row: 0, column: 7 },
children: vec![common_child.clone()],
};

Expand All @@ -303,20 +351,28 @@ mod tests {
fn perfect_matching_deeper_nodes() {
let leaf = CSTNode::Terminal {
kind: "kind_b",
start_position: Point { row: 0, column: 0 },
end_position: Point { row: 0, column: 7 },
value: "value_b".into(),
};

let intermediate = CSTNode::NonTerminal {
kind: "intermediate".into(),
start_position: Point { row: 0, column: 0 },
end_position: Point { row: 0, column: 7 },
children: vec![leaf],
};

let left = CSTNode::NonTerminal {
kind: "kind_a",
start_position: Point { row: 0, column: 0 },
end_position: Point { row: 0, column: 7 },
children: vec![intermediate.clone()],
};
let right = CSTNode::NonTerminal {
kind: "kind_a",
start_position: Point { row: 0, column: 0 },
end_position: Point { row: 0, column: 7 },
children: vec![intermediate.clone()],
};

Expand Down
2 changes: 2 additions & 0 deletions matching/src/unordered_tree_matching.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ pub fn unordered_tree_matching<'a>(left: &'a CSTNode, right: &'a CSTNode) -> cra
CSTNode::Terminal {
kind: kind_left,
value: value_left,
..
},
CSTNode::Terminal {
kind: kind_right,
value: value_right,
..
},
) => {
let is_perfetch_match = kind_left == kind_right && value_left == value_right;
Expand Down
Loading

0 comments on commit 411671d

Please sign in to comment.