This commit is contained in:
Tom Alexander 2023-10-06 16:32:49 -04:00
parent 368c6a457e
commit fbe3c76ab7
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
3 changed files with 53 additions and 32 deletions

View File

@ -15,7 +15,7 @@ pub(crate) enum EmacsField<'s> {
///
/// This is for when you want to acknowledge that a field exists in the emacs token, but you do not have any validation for it when using the compare_properties!() macro. Ideally, this should be kept to a minimum since this represents untested values.
#[allow(dead_code)]
pub(crate) fn impl_compare_noop<'b, 's, 'x, R, RG>(
pub(crate) fn compare_noop<'b, 's, 'x, R, RG>(
_emacs: &'b Token<'s>,
_rust_node: R,
_emacs_field: &'x str,

View File

@ -3,9 +3,7 @@ use std::borrow::Cow;
use std::collections::BTreeSet;
use std::collections::HashSet;
use super::compare_field::compare_identity;
use super::compare_field::compare_property_quoted_string;
use super::compare_field::impl_compare_noop;
use super::elisp_fact::ElispFact;
use super::elisp_fact::GetElispFact;
use super::sexp::unquote;
@ -2607,9 +2605,14 @@ fn compare_italic<'b, 's>(
rust: &'b Italic<'s>,
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
let children = emacs.as_list()?;
let this_status = DiffStatus::Good;
let mut this_status = DiffStatus::Good;
let mut child_status = Vec::new();
let message = None;
let mut message = None;
if let Some((new_status, new_message)) = compare_properties!(emacs)? {
this_status = new_status;
message = new_message;
}
for (emacs_child, rust_child) in children.iter().skip(2).zip(rust.children.iter()) {
child_status.push(compare_ast_node(source, emacs_child, rust_child.into())?);
@ -2632,9 +2635,14 @@ fn compare_underline<'b, 's>(
rust: &'b Underline<'s>,
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
let children = emacs.as_list()?;
let this_status = DiffStatus::Good;
let mut this_status = DiffStatus::Good;
let mut child_status = Vec::new();
let message = None;
let mut message = None;
if let Some((new_status, new_message)) = compare_properties!(emacs)? {
this_status = new_status;
message = new_message;
}
for (emacs_child, rust_child) in children.iter().skip(2).zip(rust.children.iter()) {
child_status.push(compare_ast_node(source, emacs_child, rust_child.into())?);
@ -2666,16 +2674,6 @@ fn compare_verbatim<'b, 's>(
EmacsField::Required(":value"),
|r| Some(r.contents),
compare_property_quoted_string
),
(
EmacsField::Required(":value"),
|r| Some(r.contents),
compare_property_quoted_string
),
(
EmacsField::Required(":foo"),
compare_identity,
impl_compare_noop
)
)? {
this_status = new_status;
@ -2731,9 +2729,14 @@ fn compare_strike_through<'b, 's>(
rust: &'b StrikeThrough<'s>,
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
let children = emacs.as_list()?;
let this_status = DiffStatus::Good;
let mut this_status = DiffStatus::Good;
let mut child_status = Vec::new();
let message = None;
let mut message = None;
if let Some((new_status, new_message)) = compare_properties!(emacs)? {
this_status = new_status;
message = new_message;
}
for (emacs_child, rust_child) in children.iter().skip(2).zip(rust.children.iter()) {
child_status.push(compare_ast_node(source, emacs_child, rust_child.into())?);

View File

@ -1,16 +1,34 @@
macro_rules! compare_noop {
($($field:expr),+) => {
$(
EmacsField::Required(":foo"),
compare_identity,
impl_compare_noop
),+
};
}
pub(crate) use compare_noop;
/// Create iterators for ast nodes where it only has to iterate over children
/// Assert only the listed properties exist on the Emacs AST node and compare their values to the values on the rust AST node.
///
/// Example invocation:
/// ```
/// if let Some((new_status, new_message)) = compare_properties!(
/// emacs,
/// rust,
/// (
/// EmacsField::Required(":key"),
/// |r| Some(r.key),
/// compare_property_quoted_string
/// ),
/// (
/// EmacsField::Required(":value"),
/// |r| Some(r.contents),
/// compare_property_quoted_string
/// ),
/// (EmacsField::Required(":pre-blank"), compare_identity, compare_noop)
/// )? {
/// this_status = new_status;
/// message = new_message;
/// }
/// ```
///
/// Or if the node has no properties aside from :standard-properties, we can still assert that the node has no unexpected properties:
/// ```
/// if let Some((new_status, new_message)) = compare_properties!(emacs)? {
/// this_status = new_status;
/// message = new_message;
/// }
/// ```
macro_rules! compare_properties {
($emacs:expr, $rust:expr, $(($emacs_field:expr, $rust_value_getter:expr, $compare_fn: expr)),+) => {
{