From 4c6c4d9667bf688a4ad23e1a07ec61c94fa2f0df Mon Sep 17 00:00:00 2001 From: Ricardo Date: Thu, 22 Oct 2026 20:46:12 -0600 Subject: [PATCH] .fig export: warn when a set's variants disagree on a property default The format keeps one default per property of a set; the first variant's is written (CodeRabbit review on #1152). Co-Authored-By: Claude Opus 5.5 --- crates/format/src/fig/export.rs | 18 ++++++++++++++---- crates/format/src/fig/export_tests.rs | 11 +++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/crates/format/src/fig/export.rs b/crates/format/src/fig/export.rs index 85a4726a..65f30698 100644 --- a/crates/format/src/fig/export.rs +++ b/crates/format/src/fig/export.rs @@ -2002,13 +2002,23 @@ impl<'d> Exporter<'d> { ])); } } - let mut seen = std::collections::BTreeSet::new(); + // The format keeps one default per property of a set (a variant's copy holds none): the first + // variant's, with a warning when another variant's differs. + let mut seen: BTreeMap = BTreeMap::new(); for v in &variants { let NodeKind::Component { props, .. } = &v.kind else { continue }; for (name, d) in props { - if prop_type(d).is_some() && seen.insert(name.clone()) { - let index = defs.len(); - defs.extend(self.prop_def(set.id, name, d, index)); + if prop_type(d).is_none() { + continue; + } + match seen.get(name) { + Some(first) if first != d => self.warn("variants with different defaults for one property were written with the first variant's"), + Some(_) => {} + None => { + seen.insert(name.clone(), d.clone()); + let index = defs.len(); + defs.extend(self.prop_def(set.id, name, d, index)); + } } } } diff --git a/crates/format/src/fig/export_tests.rs b/crates/format/src/fig/export_tests.rs index e9d0a601..78eeb758 100644 --- a/crates/format/src/fig/export_tests.rs +++ b/crates/format/src/fig/export_tests.rs @@ -1382,3 +1382,14 @@ fn grid_track_sizes_are_written_and_read_back() { assert_eq!(l.column_tracks, columns); assert_eq!(l.row_tracks, vec![GridTrack::fixed(69.0)]); } + +#[test] +fn variants_that_disagree_on_a_default_are_a_warning() { + let (mut doc, _) = set_with_properties(); + let large = doc.nodes().find(|n| n.name == "Size=Large").unwrap().id; + if let NodeKind::Component { props, .. } = &mut doc.node_mut(large).unwrap().kind { + props.insert("Label".into(), PropDef::Text { default: "Large".into() }); + } + let (_, warnings) = export(&doc, None).unwrap(); + assert!(warnings.iter().any(|w| w.contains("different defaults")), "{warnings:?}"); +}