feat(mix_generator)!: generate named-constructors-only MixWidget variants - #999
feat(mix_generator)!: generate named-constructors-only MixWidget variants#999leoafarias wants to merge 1 commit into
Conversation
|
Validated this against the real Remix recipes it's meant to unblock — 25 Two things before we can migrate. 1.
|
|
Refining the Style equality is only forced on one path: So a memoising thunk would deliver the win on the common path, and degrade to today's behaviour (materialise all, once) only for Sorry for the two-parter — wanted the correction on the record before anyone acts on the broader version. |
|
Closing this — it solves the wrong problem, and I want the reasoning on the record. First, retracting my own two comments above. I asked for lazy variant registration in What the published generator already does
const FortalButton({...}); // <- the only thing we want removed
const FortalButton.classic({...}); // <- already works
const FortalButton.solid({...}); // <- already works
// ...all six named constructors
final FortalButtonVariant variant; // <- want this private
style: fortalButtonStyler(variant: this.variant, size: this.size) // <- already correctNamed constructors ship today, and the variant already reaches the recipe through its own parameter. The gap between that and the goal is subtractive: drop the unnamed constructor, rename the field to Why this PR goes the wrong wayIt reframes the enum as a Mix The What replaces itA
No This is a breaking change to the Branch |
…ants An enum `variant` factory parameter already derived one named constructor per enum value, but the widget also kept an unnamed constructor and exposed `variant` as a public field. That gave every variant widget two ways to say the same thing, and modelled a recipe discriminator as widget state. The variant is now curated off the widget's public surface: no unnamed constructor, no public `variant` parameter, no public `variant` field. Each named constructor pins its enum value into a private `_variant` field, and `build()` forwards that field back into the recipe's own `variant` parameter. Recipes are untouched — they keep selecting the style themselves, so no `EnumVariant`, `variantsFromEnum`, or `applyVariant` is involved and the `mix` and `mix_annotations` packages need no change. Dynamic selection stays available by calling the recipe directly and passing the result through the target's `style` parameter. Selection semantics are unchanged: `variant` must still be selected by `factoryParameters` for the constructors to be generated. BREAKING CHANGE: generated widgets backed by an enum `variant` factory parameter no longer expose an unnamed constructor or a public `variant` field.
|
Force-pushed a full rewrite: |
Final decision — #999, #998, and what's changing nextThanks for the rewrite and the blast-radius report. Both were genuinely useful — 1. Decision: named-only is declined. #999 is closed unmerged.Your But "Confirmed named-only" was never confirmed. The decision is the opposite: The deciding evidence is from your own report:
That's the case against named-only, measured. When a variant comes from state, Supporting reasons:
#998 is closed too. Its core ask was the named-only shape; the capability it 2. What you can do today — no Mix release needed
The ~74 call-site conversions, ~20 field-read deletions, 38 example sites, and 26 Generation requires all five of: recipe is a function; parameter named exactly Note the versions in your earlier comment — 3. Coming next: a breaking change in
|
|
Closing unmerged per the decision above. The variant constructor capability ships today in the published Design record for all of this is in #1000. |
Rewritten — reduced to the actual change
This PR previously implemented a Mix
NamedVariantdomain (variants:annotation,EnumVariant,variantsFromEnum,applyVariant) at +1239/−73 acrossmix,mix_annotations, andmix_generator. That was the wrong shape, and I've replaced it with the minimal change: +147/−64 inmix_generatoronly.Previous design preserved at
9181d3d's parent — commit161214a6on the force-push record above.Why it shrank
The published generator already emitted the named constructors. For Remix's
FortalButtononmix_generator 2.2.0-beta.2:The variant already reached the recipe through its own parameter. The gap to the goal was subtractive — drop the unnamed constructor, make the field private. Framing it as a NamedVariant domain instead pulled in a
mixcore release, required rewriting every consuming recipe intovariantsFromEnum+ per-variant helpers, and introduced a per-frame allocation regression (6 stylers built per rebuild for a 6-variant widget, vs 1). None of that was needed.What this now does
When a function-backed recipe declares a named, non-nullable enum parameter called
variant, the generated widget becomes named-constructors-only:variantparameter, no publicvariantfield_variantfield each named constructor pinsbuild()forwards it back into the recipe's ownvariantparameterRecipes are untouched. They keep their existing
switch (variant)bodies and keep doing the selecting, so there is noEnumVariant, novariantsFromEnum, noapplyVariant— and no change tomixormix_annotations. Onlymix_generatorneeds a release.Selection semantics are unchanged:
variantmust still be selected byfactoryParametersfor the constructors to be generated; it is then curated back off the public surface. Nullable, positional, and non-enumvariantparameters keep the ordinary single-constructor behavior, as does an enum value that collides with a generated widget type parameter.Dynamic selection remains available by calling the recipe directly:
Breaking change
Generated widgets backed by an enum
variantparameter lose their unnamed constructor and publicvariantfield. This breaks the2.2.0-betaline, which is acceptable on a beta — and Remix, effectively the only consumer, is migrating to named constructors regardless.Verification
mix_generator: 348 tests passing,dart analyze lib/ test/clean,dart formatcleanmixormix_annotations, so their test suites are unaffectedRetractions
Two earlier comments of mine on this PR asked for lazy variant registration in
variantsFromEnumto avoid a per-rebuild allocation regression. Both are void — that regression only existed in the design being removed. Nomixcore change is required.Closes #998, whose proposal (convention-based
EnumVariantdiscovery) is superseded by this simpler mechanism.