From 84ec2f2023b888b58dc1e2ddb77118343f44fa81 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Mon, 9 Oct 2023 13:00:47 -0400 Subject: [PATCH] Introduce functions to compare children and assert there are no children. --- src/compare/diff.rs | 15 +++++++++++++- src/compare/util.rs | 48 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/src/compare/diff.rs b/src/compare/diff.rs index 24cbe2bb..f76efd75 100644 --- a/src/compare/diff.rs +++ b/src/compare/diff.rs @@ -15,6 +15,8 @@ use super::elisp_fact::ElispFact; use super::elisp_fact::GetElispFact; use super::sexp::unquote; use super::sexp::Token; +use super::util::assert_no_children; +use super::util::compare_children; use super::util::compare_standard_properties; use super::util::get_property; use super::util::get_property_boolean; @@ -336,7 +338,7 @@ fn artificial_diff_scope<'b, 's>( .into()) } -fn compare_ast_node<'b, 's>( +pub(crate) fn compare_ast_node<'b, 's>( source: &'s str, emacs: &'b Token<'s>, rust: AstNode<'b, 's>, @@ -2906,6 +2908,15 @@ fn compare_radio_target<'b, 's>( let mut child_status = Vec::new(); let mut message = None; + compare_children( + source, + emacs, + &rust.children, + &mut child_status, + &mut this_status, + &mut message, + )?; + if let Some((new_status, new_message)) = compare_properties!( emacs, rust, @@ -3220,6 +3231,8 @@ fn compare_export_snippet<'b, 's>( let mut this_status = DiffStatus::Good; let mut message = None; + assert_no_children(emacs, &mut this_status, &mut message)?; + if let Some((new_status, new_message)) = compare_properties!( emacs, rust, diff --git a/src/compare/util.rs b/src/compare/util.rs index ff3c4719..28f7bad6 100644 --- a/src/compare/util.rs +++ b/src/compare/util.rs @@ -1,8 +1,12 @@ use std::str::FromStr; +use super::diff::DiffEntry; +use super::diff::DiffStatus; use super::elisp_fact::GetElispFact; use super::sexp::Token; +use crate::compare::diff::compare_ast_node; use crate::compare::sexp::unquote; +use crate::types::AstNode; use crate::types::GetStandardProperties; use crate::types::StandardProperties; @@ -252,3 +256,47 @@ where .map_or(Ok(None), |r| r.map(Some))?; Ok(parsed_number) } + +pub(crate) fn compare_children<'b, 's, 'x, RC>( + source: &'s str, + emacs: &'b Token<'s>, + rust_children: &'x Vec, + child_status: &mut Vec>, + this_status: &mut DiffStatus, + message: &mut Option, +) -> Result<(), Box> +where + AstNode<'b, 's>: From<&'x RC>, +{ + let emacs_children = emacs.as_list()?; + let emacs_children_length = emacs_children.len() - 2; + if emacs_children_length != rust_children.len() { + *this_status = DiffStatus::Bad; + *message = Some(format!( + "Child length mismatch (emacs != rust) {:?} != {:?}", + emacs_children_length, + rust_children.len() + )); + } + for (emacs_child, rust_child) in emacs_children.iter().skip(2).zip(rust_children.iter()) { + child_status.push(compare_ast_node(source, emacs_child, rust_child.into())?); + } + Ok(()) +} + +pub(crate) fn assert_no_children<'b, 's>( + emacs: &'b Token<'s>, + this_status: &mut DiffStatus, + message: &mut Option, +) -> Result<(), Box> { + let emacs_children_length = emacs.as_list()?.len(); + // 2, one for the name of the node and one for the properties. Children would come after that. + if emacs_children_length != 2 { + *this_status = DiffStatus::Bad; + *message = Some(format!( + "Should have no children but emacs has {:?} children.", + emacs_children_length - 2, + )); + } + Ok(()) +}