use macro_rules_rt::{match_all, Rule}; use pretty_assertions::assert_eq; use syn::Result; #[derive(Clone, Debug, PartialEq)] enum Part { Unchanged(String), Changed(Changed), } impl Part { fn from(value: match_all::MatchAllPart) -> Self { match value { match_all::MatchAllPart::Unchanged(u) => Self::Unchanged(u.to_string()), match_all::MatchAllPart::Changed(c) => Self::Changed(Changed::from(c)), } } } #[derive(Clone, Debug, PartialEq)] struct Changed { source_str: String, replacement_str: String, replacements: Vec, } impl Changed { fn from(value: match_all::Changed) -> Self { let source_str = value.input().to_string(); let replacement_str = value.output(); let replacements = value.iter().map(Replacement::from).collect(); Self { source_str, replacement_str, replacements, } } } #[derive(Clone, Debug, PartialEq)] enum Replacement { Match(String), Transform(String), } impl Replacement { fn from(value: match_all::ChangedPart) -> Self { match value { match_all::ChangedPart::Match(m) => Self::Match(m.to_string()), match_all::ChangedPart::Transform(t) => Self::Transform(t.to_string()), } } } fn unchanged(source: &str) -> Part { Part::Unchanged(source.to_string()) } fn changed(source: &str, replacement: &str, replacements: &[Replacement]) -> Part { Part::Changed(Changed { source_str: source.to_string(), replacement_str: replacement.to_string(), replacements: replacements.to_vec(), }) } fn m(s: &str) -> Replacement { Replacement::Match(s.to_string()) } fn t(s: &str) -> Replacement { Replacement::Transform(s.to_string()) } #[track_caller] fn check_raw(from: &str, to: &str, input: &str, expect: &[Part]) -> Result<()> { let rule = Rule::new(from.parse()?, to.parse()?)?; let m = rule.match_all(input)?; let actual: Vec<_> = m.iter().map(Part::from).collect(); assert_eq!(actual, expect); Ok(()) } #[track_caller] fn check(from: &str, to: &str, input: &str, expect: &[Part]) { check_raw(from, to, input, expect).unwrap() } #[test] fn test_changed() { let e = [changed("1+2", "@", &[m("@")])]; check("$e:expr", "@", "1+2", &e) } #[test] fn test_unchanged_and_changed() { let e = [ unchanged("@@"), changed("1+2", "x", &[m("x")]), unchanged("@@"), ]; check("$e:expr", "x", "@@1+2@@", &e) } #[test] fn test_transform() { let e = [changed( "/// xxx", "# [ docx = \" xxx\" ]", &[t("# ["), m("docx = "), t("\" xxx\" ]")], )]; check("doc = ", "docx = ", "/// xxx", &e) } #[test] fn test_unchanged_and_transform() { let e = [ unchanged("@@\n"), changed( "/// xxx", "# [ docx = \" xxx\" ]", &[t("# ["), m("docx = "), t("\" xxx\" ]")], ), ]; check("doc = ", "docx = ", "@@\n/// xxx", &e) }