diff --git a/src/compare/compare_field.rs b/src/compare/compare_field.rs index e56e316..27a7922 100644 --- a/src/compare/compare_field.rs +++ b/src/compare/compare_field.rs @@ -424,7 +424,7 @@ pub(crate) fn compare_property_list_of_list_of_list_of_ast_nodes< 's, 'x, R, - RG: Fn(R) -> Option<&'b Vec>>>, + RG: Fn(R) -> Option<&'b Vec<(Option>>, Vec>)>>, >( source: &'s str, emacs: &'b Token<'s>, @@ -461,10 +461,41 @@ pub(crate) fn compare_property_list_of_list_of_list_of_ast_nodes< }; // Iterate the outer lists - for (value, rust_value) in value.iter().zip(rust_value.iter()) { - // Assert the middle list is a length of 1 because I've never seen it any other way. - let value = value.as_list()?; - if value.len() != 1 { + for (value, (rust_optional, rust_value)) in value.iter().zip(rust_value.iter()) { + let mut middle_value = value.as_list()?.iter(); + // First element of middle list is the mandatory value (the value past the colon). + let mandatory_value = middle_value.next(); + let mandatory_value = match mandatory_value { + Some(mandatory_value) => mandatory_value, + None => { + let this_status = DiffStatus::Bad; + let message = Some(format!( + "{} mismatch (emacs != rust) {:?} != {:?}", + emacs_field, value, rust_value + )); + return Ok(ComparePropertiesResult::SelfChange(this_status, message)); + } + }; + let mut child_status: Vec> = Vec::with_capacity(rust_value.len()); + + // Compare optional value + if let Some(rust_optional) = rust_optional { + if rust_optional.len() != middle_value.len() { + let this_status = DiffStatus::Bad; + let message = Some(format!( + "{} mismatch (emacs != rust) {:?} != {:?}", + emacs_field, value, rust_value + )); + return Ok(ComparePropertiesResult::SelfChange(this_status, message)); + } + for (e, r) in middle_value.zip(rust_optional) { + child_status.push(compare_ast_node(source, e, r.into())?); + } + } + + // Compare mandatory value + let mandatory_value = mandatory_value.as_list()?; + if rust_value.len() != mandatory_value.len() { let this_status = DiffStatus::Bad; let message = Some(format!( "{} mismatch (emacs != rust) {:?} != {:?}", @@ -472,14 +503,7 @@ pub(crate) fn compare_property_list_of_list_of_list_of_ast_nodes< )); return Ok(ComparePropertiesResult::SelfChange(this_status, message)); } - // Drill past the middle list to the inner list. - let value = value - .first() - .expect("The above if-statement asserts this exists."); - let value = value.as_list()?; - // Compare inner lists - let mut child_status: Vec> = Vec::with_capacity(rust_value.len()); - for (e, r) in value.iter().zip(rust_value) { + for (e, r) in mandatory_value.iter().zip(rust_value) { child_status.push(compare_ast_node(source, e, r.into())?); } let diff_scope = artificial_owned_diff_scope(emacs_field, child_status)?;