diff --git a/src/compare/mod.rs b/src/compare/mod.rs index b8eeab1..d789550 100644 --- a/src/compare/mod.rs +++ b/src/compare/mod.rs @@ -16,3 +16,4 @@ pub(crate) use compare_field::EmacsField; pub(crate) use elisp_fact::ElispFact; pub use sexp::sexp; pub use sexp::Token; +pub(crate) use util::get_property_quoted_string; diff --git a/src/wasm/document.rs b/src/wasm/document.rs index 0232bb6..580061b 100644 --- a/src/wasm/document.rs +++ b/src/wasm/document.rs @@ -18,7 +18,7 @@ pub struct WasmDocument<'s, 'p> { additional_properties: Vec<(String, &'s str)>, pub(crate) children: Vec>, category: Option<&'p str>, - path: Option, + pub(crate) path: Option, } to_wasm!( diff --git a/src/wasm_test/compare.rs b/src/wasm_test/compare.rs index 5b66e4d..df59601 100644 --- a/src/wasm_test/compare.rs +++ b/src/wasm_test/compare.rs @@ -1,6 +1,7 @@ use std::borrow::Cow; use super::elisp_compare::WasmElispCompare; +use crate::compare::get_property_quoted_string; use crate::compare::ElispFact; use crate::compare::EmacsField; use crate::compare::Token; @@ -245,10 +246,39 @@ impl<'s, 'p> WasmElispCompare<'s, 'p> for WasmDocument<'s, 'p> { ( EmacsField::Required(":path"), |w| w.path.as_ref().and_then(|p| p.to_str()), - || true + wasm_compare_property_quoted_string ) ); - // todo: compare the rest Ok(result) } } + +fn wasm_compare_property_quoted_string< + 'b, + 's, + W, + WV: AsRef + std::fmt::Debug, + WG: Fn(W) -> Option, +>( + _source: &'s str, + emacs: &'b Token<'s>, + wasm_node: W, + emacs_field: &str, + wasm_value_getter: WG, +) -> Result, Box> { + let mut result = WasmDiffResult::default(); + let emacs_value = get_property_quoted_string(emacs, emacs_field)?; + let wasm_value = wasm_value_getter(wasm_node); + if wasm_value.as_ref().map(|s| s.as_ref()) != emacs_value.as_deref() { + result.status.push(WasmDiffStatus::Bad( + format!( + "Property mismatch. Property=({property}) Emacs=({emacs:?}) Wasm=({wasm:?}).", + property = emacs_field, + emacs = emacs_value, + wasm = wasm_value, + ) + .into(), + )) + } + Ok(result) +} diff --git a/src/wasm_test/macros.rs b/src/wasm_test/macros.rs index db834c5..1edfafc 100644 --- a/src/wasm_test/macros.rs +++ b/src/wasm_test/macros.rs @@ -15,7 +15,7 @@ macro_rules! wasm_compare { emacs_attributes_map.keys().map(|s| *s).collect(); { - // Compare name + // Compare name. let wasm_name = $wasm.get_elisp_name(); if emacs_name != wasm_name { @@ -31,7 +31,7 @@ macro_rules! wasm_compare { } { - // Compare children + // Compare children. result.extend(wasm_compare_list( $source, emacs_list_iter, @@ -40,7 +40,7 @@ macro_rules! wasm_compare { } { - // Compare fields + // Check for properties that are missing from the elisp node. $( match $emacs_field { EmacsField::Required(name) if emacs_keys.contains(name) => { @@ -63,6 +63,38 @@ macro_rules! wasm_compare { )* } + { + // Check for elisp properties that were not compared. + if !emacs_keys.is_empty() { + let unexpected_keys: Vec<&str> = emacs_keys.into_iter().collect(); + let unexpected_keys = unexpected_keys.join(", "); + result.status.push(WasmDiffStatus::Bad( + format!( + "Emacs node had extra field(s): ({field_names}).", + field_names = unexpected_keys, + ) + .into(), + )); + } + + } + + { + // Compare properties. + $( + let emacs_name = match $emacs_field { + EmacsField::Required(name) => { + name + }, + EmacsField::Optional(name) => { + name + }, + }; + let result = $compare_fn($source, $emacs, $wasm, emacs_name, $wasm_value_getter)?; + // TODO: record this result. + )* + } + result }}; }