From 7986e5d3129d41670de401c0964d55497d02ea89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Pedro=20Henrique?= Date: Fri, 27 Oct 2023 04:06:00 +0000 Subject: [PATCH] chore: initial change on struct --- .devcontainer/devcontainer.json | 31 ++++ bin/src/main.rs | 227 ++++++++++++++------------ matching/src/matching.rs | 2 +- matching/src/matchings.rs | 56 ++++++- matching/src/ordered_tree_matching.rs | 77 +++++---- merge/src/lib.rs | 16 +- merge/src/odered_merge.rs | 74 ++++----- model/src/cst_node.rs | 12 +- parsing/src/parse.rs | 85 +++++----- 9 files changed, 333 insertions(+), 247 deletions(-) create mode 100644 .devcontainer/devcontainer.json diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..f8fff10 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,31 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/rust +{ + "name": "Rust", + // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile + "image": "mcr.microsoft.com/devcontainers/rust:1-1-bullseye" + + // Use 'mounts' to make the cargo cache persistent in a Docker Volume. + // "mounts": [ + // { + // "source": "devcontainer-cargo-cache-${devcontainerId}", + // "target": "/usr/local/cargo", + // "type": "volume" + // } + // ] + + // Features to add to the dev container. More info: https://containers.dev/features. + // "features": {}, + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [], + + // Use 'postCreateCommand' to run commands after the container is created. + // "postCreateCommand": "rustc --version", + + // Configure tool-specific properties. + // "customizations": {}, + + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "root" +} diff --git a/bin/src/main.rs b/bin/src/main.rs index f57071a..284edd4 100644 --- a/bin/src/main.rs +++ b/bin/src/main.rs @@ -3,29 +3,31 @@ use merge::merge; use model::{CSTNode, Language}; use parsing::ParserConfiguration; -fn run_semi_structured_merge_on_revisions( - language: Language, - base: &str, - left: &str, - right: &str, -) -> Result { - let base_tree = parsing::parse_string(base, ParserConfiguration::from_language(language))?; - let left_tree = parsing::parse_string(left, ParserConfiguration::from_language(language))?; - let right_tree = parsing::parse_string(right, ParserConfiguration::from_language(language))?; - - let matchings_left_base = ordered_tree_matching(&left_tree, &base_tree); - let matchings_right_base = ordered_tree_matching(&right_tree, &base_tree); - let matchings_left_right = ordered_tree_matching(&left_tree, &right_tree); - - Ok(merge( - &base_tree, - &left_tree, - &right_tree, - &matchings_left_base, - &matchings_right_base, - &matchings_left_right, - )) -} +// fn run_semi_structured_merge_on_revisions<'a>( +// language: Language, +// base: &'a str, +// left: &'a str, +// right: &'a str, +// ) -> Result, &'static str> { +// let parser_configuration = ParserConfiguration::from_language(language); + +// let base_tree = parsing::parse_string(base, &parser_configuration)?; +// let left_tree = parsing::parse_string(left, &parser_configuration)?; +// let right_tree = parsing::parse_string(right, &parser_configuration)?; + +// let matchings_left_base = ordered_tree_matching(&left_tree, &base_tree); +// let matchings_right_base = ordered_tree_matching(&right_tree, &base_tree); +// let matchings_left_right = ordered_tree_matching(&left_tree, &right_tree); + +// Ok(merge( +// &base_tree, +// &left_tree, +// &right_tree, +// &matchings_left_base, +// &matchings_right_base, +// &matchings_left_right, +// )) +// } fn main() { let base = r#" @@ -46,9 +48,25 @@ fn main() { } "#; - let result = run_semi_structured_merge_on_revisions(Language::Java, base, left, right); + let parser_configuration = ParserConfiguration::from_language(Language::Java); + let base_tree = parsing::parse_string(base, &parser_configuration).unwrap(); + let left_tree = parsing::parse_string(left, &parser_configuration).unwrap(); + let right_tree = parsing::parse_string(right, &parser_configuration).unwrap(); - println!("{:#?}", pretty_print(result.unwrap())) + let matchings_left_base = ordered_tree_matching(&left_tree, &base_tree); + let matchings_right_base = ordered_tree_matching(&right_tree, &base_tree); + let matchings_left_right = ordered_tree_matching(&left_tree, &right_tree); + + let result = merge( + &base_tree, + &left_tree, + &right_tree, + &matchings_left_base, + &matchings_right_base, + &matchings_left_right, + ); + + println!("{:#?}", pretty_print(result)) } pub fn pretty_print(node: CSTNode) -> String { @@ -66,82 +84,83 @@ pub fn pretty_print(node: CSTNode) -> String { } } -#[cfg(test)] -mod tests { - use model::language::Language; - use model::CSTNode; - use parsing::ParserConfiguration; - - use crate::run_semi_structured_merge_on_revisions; - - fn parse_java_string(contents: &str) -> CSTNode { - parsing::parse_string(contents, ParserConfiguration::from_language(Language::Java)).unwrap() - } - - #[test] - fn it_merges_three_java_revisions_that_are_equal() { - let code = r#" - public static interface HelloWorld { - void sayHello(String name); - void sayBye(String name); - } - "#; - - let result = run_semi_structured_merge_on_revisions(Language::Java, code, code, code); - - assert_eq!(parse_java_string(code), result.unwrap()) - } - - #[test] - fn it_merges_three_java_revisions_that_adds_the_same_node() { - let base = r#" - public static interface HelloWorld { - void sayBye(String name); - } - "#; - - let parents = r#" - public static interface HelloWorld { - void sayHello(String name); - void sayBye(String name); - } - "#; - - let merge = r#" - public static interface HelloWorld { - void sayHello(String name); - void sayBye(String name); - } - "#; - - let result = run_semi_structured_merge_on_revisions(Language::Java, base, parents, parents); - - assert_eq!(parse_java_string(merge), result.unwrap()) - } - - #[test] - fn it_merges_three_java_revisions_that_removes_the_same_node() { - let base = r#" - public static interface HelloWorld { - void sayHello(String name); - void sayBye(String name); - } - "#; - - let parents = r#" - public static interface HelloWorld { - void sayBye(String name); - } - "#; - - let merge = r#" - public static interface HelloWorld { - void sayBye(String name); - } - "#; - - let result = run_semi_structured_merge_on_revisions(Language::Java, base, parents, parents); - - assert_eq!(parse_java_string(merge), result.unwrap()) - } -} +// #[cfg(test)] +// mod tests { +// use model::language::Language; +// use model::CSTNode; +// use parsing::ParserConfiguration; + +// use crate::run_semi_structured_merge_on_revisions; + +// fn parse_java_string<'a>(contents: &'a str) -> CSTNode<'a> { +// let parser_configuration = ParserConfiguration::from_language(Language::Java); +// parsing::parse_string(contents, &parser_configuration).unwrap() +// } + +// #[test] +// fn it_merges_three_java_revisions_that_are_equal() { +// let code = r#" +// public static interface HelloWorld { +// void sayHello(String name); +// void sayBye(String name); +// } +// "#; + +// let result = run_semi_structured_merge_on_revisions(Language::Java, code, code, code); + +// assert_eq!(parse_java_string(code), result.unwrap()) +// } + +// #[test] +// fn it_merges_three_java_revisions_that_adds_the_same_node() { +// let base = r#" +// public static interface HelloWorld { +// void sayBye(String name); +// } +// "#; + +// let parents = r#" +// public static interface HelloWorld { +// void sayHello(String name); +// void sayBye(String name); +// } +// "#; + +// let merge = r#" +// public static interface HelloWorld { +// void sayHello(String name); +// void sayBye(String name); +// } +// "#; + +// let result = run_semi_structured_merge_on_revisions(Language::Java, base, parents, parents); + +// assert_eq!(parse_java_string(merge), result.unwrap()) +// } + +// #[test] +// fn it_merges_three_java_revisions_that_removes_the_same_node() { +// let base = r#" +// public static interface HelloWorld { +// void sayHello(String name); +// void sayBye(String name); +// } +// "#; + +// let parents = r#" +// public static interface HelloWorld { +// void sayBye(String name); +// } +// "#; + +// let merge = r#" +// public static interface HelloWorld { +// void sayBye(String name); +// } +// "#; + +// let result = run_semi_structured_merge_on_revisions(Language::Java, base, parents, parents); + +// assert_eq!(parse_java_string(merge), result.unwrap()) +// } +// } diff --git a/matching/src/matching.rs b/matching/src/matching.rs index 90e3426..655eb2b 100644 --- a/matching/src/matching.rs +++ b/matching/src/matching.rs @@ -2,7 +2,7 @@ use model::CSTNode; #[derive(Clone, Debug, PartialEq, Eq)] pub struct Matching<'a> { - pub matching_node: &'a CSTNode, + pub matching_node: &'a CSTNode<'a>, pub score: usize, pub is_perfect_match: bool, } diff --git a/matching/src/matchings.rs b/matching/src/matchings.rs index 26beb62..73da1cb 100644 --- a/matching/src/matchings.rs +++ b/matching/src/matchings.rs @@ -7,27 +7,27 @@ use crate::matching::Matching; use crate::matching_entry::MatchingEntry; #[derive(Debug)] -pub struct Matchings { - matching_entries: HashMap, MatchingEntry>, +pub struct Matchings<'a> { + matching_entries: HashMap>, MatchingEntry>, } -impl Matchings { +impl<'a> Matchings<'a> { pub fn empty() -> Self { Matchings { matching_entries: HashMap::new(), } } - pub fn new(matching_entries: HashMap, MatchingEntry>) -> Self { + pub fn new(matching_entries: HashMap>, MatchingEntry>) -> Self { Matchings { matching_entries } } pub fn find_matching_for(&self, a_node: &CSTNode) -> Option { self.matching_entries .iter() - .find(|(UnorderedPair(left, right), ..)| left == a_node || right == a_node) + .find(|(UnorderedPair(left, right), ..)| left == &a_node || right == &a_node) .map(|(UnorderedPair(left, right), matching)| { - let matching_node = if left == a_node { right } else { left }; + let matching_node = if left == &a_node { right } else { left }; Matching { matching_node, score: matching.score, @@ -36,7 +36,11 @@ impl Matchings { }) } - pub fn get_matching_entry(&self, left: CSTNode, right: CSTNode) -> Option<&MatchingEntry> { + pub fn get_matching_entry( + &self, + left: &'a CSTNode<'a>, + right: &'a CSTNode<'a>, + ) -> Option<&MatchingEntry> { self.matching_entries.get(&UnorderedPair(left, right)) } } @@ -77,4 +81,42 @@ mod tests { Matchings::new(matchings).find_matching_for(&a_node) ) } + + #[test] + fn returns_a_match_if_a_matching_for_the_node_is_found() { + let a_node = CSTNode::Terminal { + kind: "kind_b".into(), + value: "value_b".into(), + }; + let b_node = CSTNode::Terminal { + kind: "kind_a".into(), + value: "value_a".into(), + }; + + let mut matchings_map = HashMap::new(); + matchings_map.insert( + UnorderedPair(a_node.clone(), b_node.clone()), + MatchingEntry::new(1, false), + ); + + let matchings = Matchings::new(matchings_map); + + assert_eq!( + Some(Matching { + matching_node: &b_node, + score: 1, + is_perfect_match: false + }), + matchings.find_matching_for(&a_node) + ); + + assert_eq!( + Some(Matching { + matching_node: &a_node, + score: 1, + is_perfect_match: false + }), + matchings.find_matching_for(&b_node) + ) + } } diff --git a/matching/src/ordered_tree_matching.rs b/matching/src/ordered_tree_matching.rs index b79978a..c8f87f5 100644 --- a/matching/src/ordered_tree_matching.rs +++ b/matching/src/ordered_tree_matching.rs @@ -11,25 +11,25 @@ enum Direction { } #[derive(Clone)] -struct Entry( +struct Entry<'a>( pub Direction, - pub HashMap, MatchingEntry>, + pub HashMap>, MatchingEntry>, ); -impl Default for Entry { +impl<'a> Default for Entry<'a> { fn default() -> Self { Self(Direction::TOP, Default::default()) } } -pub fn ordered_tree_matching(left: &CSTNode, right: &CSTNode) -> Matchings { +pub fn ordered_tree_matching<'a>(left: &'a CSTNode, right: &'a CSTNode) -> Matchings<'a> { return Matchings::new(ordered_tree_matching_helper(left, right)); } -fn ordered_tree_matching_helper( - left: &CSTNode, - right: &CSTNode, -) -> HashMap, MatchingEntry> { +fn ordered_tree_matching_helper<'a>( + left: &'a CSTNode, + right: &'a CSTNode, +) -> HashMap>, MatchingEntry> { match (left, right) { ( CSTNode::NonTerminal { @@ -84,7 +84,7 @@ fn ordered_tree_matching_helper( let mut i = m; let mut j = n; - let mut children = Vec::<&HashMap, MatchingEntry>>::new(); + let mut children = Vec::<&HashMap, MatchingEntry>>::new(); while i >= 1 && j >= 1 { match matrix_t.get(i).unwrap().get(j).unwrap().0 { @@ -102,10 +102,7 @@ fn ordered_tree_matching_helper( let matching = MatchingEntry::new(matrix_m[m][n] + root_matching, left == right); let mut result = HashMap::new(); - result.insert( - UnorderedPair::new(left.to_owned(), right.to_owned()), - matching, - ); + result.insert(UnorderedPair::new(left, right), matching); children.into_iter().for_each(|child_matchings| { child_matchings.iter().for_each(|(key, matching)| { result.insert(key.to_owned(), matching.to_owned()); @@ -126,7 +123,7 @@ fn ordered_tree_matching_helper( let mut result = HashMap::new(); let is_perfetch_match = kind_left == kind_right && value_left == value_right; result.insert( - UnorderedPair::new(left.to_owned(), right.to_owned()), + UnorderedPair::new(left, right), MatchingEntry::new(is_perfetch_match.into(), is_perfetch_match), ); result @@ -134,7 +131,7 @@ fn ordered_tree_matching_helper( (_, _) => { let mut result = HashMap::new(); result.insert( - UnorderedPair::new(left.to_owned(), right.to_owned()), + UnorderedPair::new(left, right), MatchingEntry::new(0, false), ); result @@ -150,11 +147,11 @@ mod tests { #[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".to_owned(), + kind: "kind", value: "value".to_owned(), }; let right = CSTNode::Terminal { - kind: "kind".to_owned(), + kind: "kind", value: "value".to_owned(), }; @@ -162,18 +159,18 @@ mod tests { assert_eq!( Some(&MatchingEntry::new(1, true)), - matchings.get_matching_entry(left, right) + matchings.get_matching_entry(left.clone(), right.clone()) ) } #[test] fn two_terminal_nodes_have_a_match_with_score_zero_if_they_have_different_value() { let left = CSTNode::Terminal { - kind: "kind".to_owned(), + kind: "kind", value: "value_a".to_owned(), }; let right = CSTNode::Terminal { - kind: "kind".to_owned(), + kind: "kind", value: "value_b".to_owned(), }; @@ -181,18 +178,18 @@ mod tests { assert_eq!( Some(&MatchingEntry::new(0, false)), - matchings.get_matching_entry(left, right) + matchings.get_matching_entry(left.clone(), right.clone()) ) } #[test] fn two_terminal_nodes_have_a_match_with_score_zero_if_they_have_different_kind() { let left = CSTNode::Terminal { - kind: "kind_a".to_owned(), + kind: "kind_a", value: "value".to_owned(), }; let right = CSTNode::Terminal { - kind: "kind_b".to_owned(), + kind: "kind_b", value: "value".to_owned(), }; @@ -200,18 +197,18 @@ mod tests { assert_eq!( Some(&MatchingEntry::new(0, false)), - matchings.get_matching_entry(left, right) + matchings.get_matching_entry(left.clone(), right.clone()) ) } #[test] fn two_terminal_nodes_have_a_match_with_score_zero_if_they_have_different_kind_and_value() { let left = CSTNode::Terminal { - kind: "kind_a".to_owned(), + kind: "kind_a", value: "value_a".to_owned(), }; let right = CSTNode::Terminal { - kind: "kind_b".to_owned(), + kind: "kind_b", value: "value_a".to_owned(), }; @@ -219,7 +216,7 @@ mod tests { assert_eq!( Some(&MatchingEntry::new(0, false)), - matchings.get_matching_entry(left, right) + matchings.get_matching_entry(left.clone(), right.clone()) ) } @@ -230,11 +227,11 @@ mod tests { value: "value_b".into(), }; let left = CSTNode::NonTerminal { - kind: "kind_a".to_owned(), + kind: "kind_a", children: vec![child.clone()], }; let right = CSTNode::NonTerminal { - kind: "kind_a".to_owned(), + kind: "kind_a", children: vec![child.clone()], }; @@ -258,11 +255,11 @@ mod tests { }; let left = CSTNode::NonTerminal { - kind: "kind_a".to_owned(), + kind: "kind_a", children: vec![left_child.clone()], }; let right = CSTNode::NonTerminal { - kind: "kind_a".to_owned(), + kind: "kind_a", children: vec![right_child.clone()], }; @@ -283,11 +280,11 @@ mod tests { }; let left = CSTNode::NonTerminal { - kind: "kind_a".to_owned(), + kind: "kind_a", children: vec![common_child.clone()], }; let right = CSTNode::NonTerminal { - kind: "kind_a".to_owned(), + kind: "kind_a", children: vec![common_child.clone(), unique_right_child], }; @@ -295,7 +292,7 @@ mod tests { assert_eq!( Some(&MatchingEntry::new(2, false)), - matchings.get_matching_entry(left, right) + matchings.get_matching_entry(left.clone(), right.clone()) ) } @@ -307,11 +304,11 @@ mod tests { }; let left = CSTNode::NonTerminal { - kind: "kind_a".to_owned(), + kind: "kind_a", children: vec![common_child.clone()], }; let right = CSTNode::NonTerminal { - kind: "kind_a".to_owned(), + kind: "kind_a", children: vec![common_child.clone()], }; @@ -319,7 +316,7 @@ mod tests { assert_eq!( Some(&MatchingEntry::new(2, true)), - matchings.get_matching_entry(left, right) + matchings.get_matching_entry(left.clone(), right.clone()) ) } @@ -336,11 +333,11 @@ mod tests { }; let left = CSTNode::NonTerminal { - kind: "kind_a".to_owned(), + kind: "kind_a", children: vec![intermediate.clone()], }; let right = CSTNode::NonTerminal { - kind: "kind_a".to_owned(), + kind: "kind_a", children: vec![intermediate.clone()], }; @@ -353,7 +350,7 @@ mod tests { assert_eq!( Some(&MatchingEntry::new(3, true)), - matchings.get_matching_entry(left, right) + matchings.get_matching_entry(left.clone(), right.clone()) ) } } diff --git a/merge/src/lib.rs b/merge/src/lib.rs index 5cebc8b..3f2f784 100644 --- a/merge/src/lib.rs +++ b/merge/src/lib.rs @@ -4,14 +4,14 @@ use matching::Matchings; use model::CSTNode; use odered_merge::ordered_merge; -pub fn merge( - base: &CSTNode, - left: &CSTNode, - right: &CSTNode, - base_left_matchings: &Matchings, - base_right_matchings: &Matchings, - left_right_matchings: &Matchings, -) -> CSTNode { +pub fn merge<'a>( + base: &'a CSTNode<'a>, + left: &'a CSTNode<'a>, + right: &'a CSTNode<'a>, + base_left_matchings: &'a Matchings<'a>, + base_right_matchings: &'a Matchings<'a>, + left_right_matchings: &'a Matchings<'a>, +) -> CSTNode<'a> { return ordered_merge( base, left, diff --git a/merge/src/odered_merge.rs b/merge/src/odered_merge.rs index 8ab7136..28274fc 100644 --- a/merge/src/odered_merge.rs +++ b/merge/src/odered_merge.rs @@ -1,14 +1,14 @@ use matching::Matchings; use model::CSTNode; -pub fn ordered_merge( - base: &CSTNode, - left: &CSTNode, - right: &CSTNode, - base_left_matchings: &Matchings, - base_right_matchings: &Matchings, - left_right_matchings: &Matchings, -) -> CSTNode { +pub fn ordered_merge<'a>( + base: &'a CSTNode<'a>, + left: &'a CSTNode<'a>, + right: &'a CSTNode<'a>, + base_left_matchings: &'a Matchings<'a>, + base_right_matchings: &'a Matchings<'a>, + left_right_matchings: &'a Matchings<'a>, +) -> CSTNode<'a> { match (base, left, right) { ( CSTNode::Terminal { @@ -119,7 +119,7 @@ pub fn ordered_merge( && has_bidirectional_matching_left_right.is_none() && has_matching_base_right { - result_children.push(cur_left.unwrap().to_owned()); + result_children.push(cur_left.unwrap()); if !base_right_matchings .find_matching_for(cur_right.unwrap()) @@ -127,8 +127,8 @@ pub fn ordered_merge( .is_perfect_match { result_children.push(CSTNode::Conflict { - left: Box::new(None), - right: Box::new(Some(cur_right.unwrap().to_owned())), + left: None, + right: Some(cur_right.unwrap()), }) } @@ -146,8 +146,8 @@ pub fn ordered_merge( .is_perfect_match { result_children.push(CSTNode::Conflict { - left: Box::new(Some(cur_left.unwrap().to_owned())), - right: Box::new(None), + left: Some(cur_left.unwrap()), + right: None, }) } @@ -158,8 +158,8 @@ pub fn ordered_merge( && has_bidirectional_matching_left_right.is_none() { result_children.push(CSTNode::Conflict { - left: Box::new(Some(cur_left.unwrap().to_owned())), - right: Box::new(Some(cur_right.unwrap().to_owned())), + left: Some(cur_left.unwrap()), + right: Some(cur_right.unwrap()), }); cur_left = children_left_it.next(); @@ -175,8 +175,8 @@ pub fn ordered_merge( .is_perfect_match { result_children.push(CSTNode::Conflict { - left: Box::new(Some(cur_left.unwrap().to_owned())), - right: Box::new(None), + left: Some(cur_left.unwrap()), + right: None, }); } @@ -192,8 +192,8 @@ pub fn ordered_merge( .is_perfect_match { result_children.push(CSTNode::Conflict { - left: Box::new(None), - right: Box::new(Some(cur_right.unwrap().to_owned())), + left: None, + right: Some(cur_right.unwrap()), }); } @@ -212,7 +212,7 @@ pub fn ordered_merge( } CSTNode::NonTerminal { - kind: kind.to_string(), + kind, children: result_children, } } @@ -642,14 +642,14 @@ mod tests { }], }, CSTNode::Conflict { - left: Box::new(None), - right: Box::new(Some(CSTNode::NonTerminal { + left: None, + right: Some(&CSTNode::NonTerminal { kind: "subtree".into(), children: vec![CSTNode::Terminal { kind: "kind_c".into(), value: "value_c".into(), }], - })), + }), }, ], }, @@ -668,14 +668,14 @@ mod tests { }], }, CSTNode::Conflict { - left: Box::new(Some(CSTNode::NonTerminal { + left: Some(&CSTNode::NonTerminal { kind: "subtree".into(), children: vec![CSTNode::Terminal { kind: "kind_c".into(), value: "value_c".into(), }], - })), - right: Box::new(None), + }), + right: None, }, ], }, @@ -713,14 +713,14 @@ mod tests { CSTNode::NonTerminal { kind: "kind".into(), children: vec![CSTNode::Conflict { - left: Box::new(Some(CSTNode::Terminal { + left: Some(&CSTNode::Terminal { kind: "kind_a".into(), value: "value_a".into(), - })), - right: Box::new(Some(CSTNode::Terminal { + }), + right: Some(&CSTNode::Terminal { kind: "kind_b".into(), value: "value_b".into(), - })), + }), }], }, ) @@ -830,15 +830,14 @@ mod tests { kind: "kind".into(), children: vec![ CSTNode::Conflict { - left: Some(CSTNode::NonTerminal { + left: Some(&CSTNode::NonTerminal { kind: "subtree".into(), children: vec![CSTNode::Terminal { kind: "kind_c".into(), value: "value_c".into(), }], - }) - .into(), - right: None.into(), + }), + right: None, }, CSTNode::Terminal { kind: "kind_a".into(), @@ -856,15 +855,14 @@ mod tests { kind: "kind".into(), children: vec![ CSTNode::Conflict { - left: None.into(), - right: Some(CSTNode::NonTerminal { + left: None, + right: Some(&CSTNode::NonTerminal { kind: "subtree".into(), children: vec![CSTNode::Terminal { kind: "kind_c".into(), value: "value_c".into(), }], - }) - .into(), + }), }, CSTNode::Terminal { kind: "kind_a".into(), diff --git a/model/src/cst_node.rs b/model/src/cst_node.rs index fda0eb7..dd2b13a 100644 --- a/model/src/cst_node.rs +++ b/model/src/cst_node.rs @@ -1,15 +1,15 @@ #[derive(Debug, PartialEq, Clone, Eq, Hash, PartialOrd, Ord)] -pub enum CSTNode { +pub enum CSTNode<'a> { Terminal { - kind: String, + kind: &'a str, value: String, }, NonTerminal { - kind: String, - children: Vec, + kind: &'a str, + children: Vec<&'a CSTNode<'a>>, }, Conflict { - left: Box>, - right: Box>, + left: Option<&'a CSTNode<'a>>, + right: Option<&'a CSTNode<'a>>, }, } diff --git a/parsing/src/parse.rs b/parsing/src/parse.rs index 88aef4b..bdab2fe 100644 --- a/parsing/src/parse.rs +++ b/parsing/src/parse.rs @@ -2,7 +2,7 @@ use crate::tree_sitter_parser::ParserConfiguration; use model::CSTNode; use tree_sitter::Node; -fn explore_node(node: Node, src: &str, config: &ParserConfiguration) -> CSTNode { +fn explore_node<'a>(node: Node, src: &'a str, config: &'a ParserConfiguration) -> CSTNode<'a> { if node.child_count() == 0 || config.stop_compilation_at.contains(node.kind()) { CSTNode::Terminal { kind: node.kind().into(), @@ -20,7 +20,10 @@ fn explore_node(node: Node, src: &str, config: &ParserConfiguration) -> CSTNode } } -pub fn parse_string(src: &str, config: ParserConfiguration) -> Result { +pub fn parse_string<'a>( + src: &'a str, + config: &'a ParserConfiguration, +) -> Result, &'static str> { let mut parser = tree_sitter::Parser::new(); parser .set_language(config.language) @@ -28,7 +31,7 @@ pub fn parse_string(src: &str, config: ParserConfiguration) -> Result Result::Ok(explore_node(parsed.root_node(), src, &config)), + Some(parsed) => Result::Ok(explore_node(parsed.root_node(), src, config)), None => Result::Err("It was not possible to parse the tree."), } } @@ -44,90 +47,88 @@ mod tests { void sayHello(String name); } "#; - let result = parse_string( - code, - ParserConfiguration { - language: tree_sitter_java::language(), - stop_compilation_at: [].into_iter().collect(), - }, - ); + let parser_configuration = ParserConfiguration { + language: tree_sitter_java::language(), + stop_compilation_at: [].into_iter().collect(), + }; + let result = parse_string(code, &parser_configuration); let expected = CSTNode::NonTerminal { kind: "program".into(), - children: vec![CSTNode::NonTerminal { + children: vec![&CSTNode::NonTerminal { kind: "interface_declaration".into(), children: vec![ - CSTNode::NonTerminal { + &CSTNode::NonTerminal { kind: "modifiers".into(), children: vec![ - CSTNode::Terminal { + &CSTNode::Terminal { kind: "public".into(), value: "public".into(), }, - CSTNode::Terminal { + &CSTNode::Terminal { kind: "static".into(), value: "static".into(), }, ], }, - CSTNode::Terminal { + &CSTNode::Terminal { kind: "interface".into(), value: "interface".into(), }, - CSTNode::Terminal { + &CSTNode::Terminal { kind: "identifier".into(), value: "HelloWorld".into(), }, - CSTNode::NonTerminal { + &CSTNode::NonTerminal { kind: "interface_body".into(), children: vec![ - CSTNode::Terminal { + &CSTNode::Terminal { kind: "{".into(), value: "{".into(), }, - CSTNode::NonTerminal { + &CSTNode::NonTerminal { kind: "method_declaration".into(), children: vec![ - CSTNode::Terminal { + &CSTNode::Terminal { kind: "void_type".into(), value: "void".into(), }, - CSTNode::Terminal { + &CSTNode::Terminal { kind: "identifier".into(), value: "sayHello".into(), }, - CSTNode::NonTerminal { + &CSTNode::NonTerminal { kind: "formal_parameters".into(), children: vec![ - CSTNode::Terminal { + &CSTNode::Terminal { kind: "(".into(), value: "(".into(), }, - CSTNode::NonTerminal { + &CSTNode::NonTerminal { kind: "formal_parameter".into(), children: vec![ - CSTNode::Terminal { + &CSTNode::Terminal { kind: "type_identifier".into(), value: "String".into(), }, - CSTNode::Terminal { + &CSTNode::Terminal { kind: "identifier".into(), value: "name".into(), }, ], }, - CSTNode::Terminal { + &CSTNode::Terminal { kind: ")".into(), value: ")".into(), }, ], }, - CSTNode::Terminal { + &CSTNode::Terminal { kind: ";".into(), value: ";".into(), }, ], }, - CSTNode::Terminal { + &CSTNode::Terminal { kind: "}".into(), value: "}".into(), }, @@ -142,41 +143,39 @@ mod tests { #[test] fn it_stops_the_compilation_when_reach_a_configured_node() { let code = "public static interface HelloWorld {void sayHello(String name);}"; - let result = parse_string( - code, - ParserConfiguration { - language: tree_sitter_java::language(), - stop_compilation_at: ["interface_body"].into_iter().collect(), - }, - ); + let parser_configuration = ParserConfiguration { + language: tree_sitter_java::language(), + stop_compilation_at: ["interface_body"].into_iter().collect(), + }; + let result = parse_string(code, &parser_configuration); let expected = CSTNode::NonTerminal { kind: "program".into(), - children: vec![CSTNode::NonTerminal { + children: vec![&CSTNode::NonTerminal { kind: "interface_declaration".into(), children: vec![ - CSTNode::NonTerminal { + &CSTNode::NonTerminal { kind: "modifiers".into(), children: vec![ - CSTNode::Terminal { + &CSTNode::Terminal { kind: "public".into(), value: "public".into(), }, - CSTNode::Terminal { + &CSTNode::Terminal { kind: "static".into(), value: "static".into(), }, ], }, - CSTNode::Terminal { + &CSTNode::Terminal { kind: "interface".into(), value: "interface".into(), }, - CSTNode::Terminal { + &CSTNode::Terminal { kind: "identifier".into(), value: "HelloWorld".into(), }, - CSTNode::Terminal { + &CSTNode::Terminal { kind: "interface_body".into(), value: "{void sayHello(String name);}".into(), },