Starting a new macro for comparing fields.

This will help us assert that all fields are tested and that only expected fields are present.
This commit is contained in:
Tom Alexander 2023-10-06 13:08:15 -04:00
parent e686666ea0
commit d06e4de7b0
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
4 changed files with 71 additions and 0 deletions

View File

@ -13,6 +13,8 @@ use super::util::get_property_boolean;
use super::util::get_property_numeric;
use super::util::get_property_quoted_string;
use super::util::get_property_unquoted_atom;
use crate::compare::elisp_fact::EmacsField;
use crate::compare::macros::compare_properties;
use crate::types::AngleLink;
use crate::types::AstNode;
use crate::types::BabelCall;
@ -2688,6 +2690,9 @@ fn compare_code<'b, 's>(
));
}
let foo: Result<Option<(DiffStatus, Option<String>)>, Box<dyn std::error::Error>> =
compare_properties!(emacs, EmacsField::Required(":value"));
Ok(DiffResult {
status: this_status,
name: rust.get_elisp_name(),

View File

@ -550,3 +550,9 @@ impl<'s> ElispFact<'s> for PlainText<'s> {
"plain-text".into()
}
}
#[derive(Debug)]
pub(crate) enum EmacsField<'s> {
Required(&'s str),
Optional(&'s str),
}

59
src/compare/macros.rs Normal file
View File

@ -0,0 +1,59 @@
/// Create iterators for ast nodes where it only has to iterate over children
macro_rules! compare_properties {
($emacs:expr, $($emacs_field:expr),+) => {
{
let mut this_status = DiffStatus::Good;
let mut message: Option<String> = None;
let children = $emacs.as_list()?;
let attributes_child = children
.iter()
.nth(1)
.ok_or("Should have an attributes child.")?;
let attributes_map = attributes_child.as_map()?;
let mut emacs_keys: BTreeSet<&str> = attributes_map.keys().map(|s| *s).collect();
$(
match $emacs_field {
EmacsField::Required(name) if emacs_keys.contains(name) => {
emacs_keys.remove(name);
},
EmacsField::Optional(name) if emacs_keys.contains(name) => {
emacs_keys.remove(name);
},
EmacsField::Required(name) => {
this_status = DiffStatus::Bad;
message = Some(format!(
"Emacs token lacks required field: {}",
name
));
},
EmacsField::Optional(_name) => {},
}
),+
if !emacs_keys.is_empty() {
let unexpected_keys: Vec<&str> = emacs_keys.into_iter().collect();
let unexpected_keys = unexpected_keys.join(", ");
this_status = DiffStatus::Bad;
message = Some(format!(
"Emacs token had extra field(s): {}",
unexpected_keys
));
}
$(
println!("{:?}", $emacs_field);
),+
match this_status {
DiffStatus::Good => {
Ok(None)
},
_ => {
Ok(Some((this_status, message)))
}
}
}
};
}
pub(crate) use compare_properties;

View File

@ -1,6 +1,7 @@
mod compare;
mod diff;
mod elisp_fact;
mod macros;
mod parse;
mod sexp;
mod util;