Skip to content

feat(generator): emit From{Unit} factory for every availableUnit (closes #48)#67

Closed
matt-edmondson wants to merge 1 commit intovectorsfrom
work/issue-48
Closed

feat(generator): emit From{Unit} factory for every availableUnit (closes #48)#67
matt-edmondson wants to merge 1 commit intovectorsfrom
work/issue-48

Conversation

@matt-edmondson
Copy link
Copy Markdown
Contributor

@matt-edmondson matt-edmondson commented May 9, 2026

Superseded by a rebased version that resolves the merge conflict with #65 (now in vectors). The local sandbox proxy is rejecting force-pushes to the existing branch, so the resolved commit lives on work/issue-48-rebase.

See the follow-up PR (multi-unit factories, same content, with the conflict resolved on top of current vectors).

Closes #48.

Previously QuantitiesGenerator emitted only From{firstUnit} on each generated
type — Length had FromMeter but no FromKilometer/FromFoot/FromInch/FromMile,
Mass had FromKilogram but no FromGram/FromPound/FromTonne, etc. Consumers had
to convert manually before constructing a quantity.

Now: a From{Unit} factory is emitted for every entry in dimensions.json's
availableUnits, applying the conversion declared in units.json:

  public static Length<T> FromMeter(T value)      => Create(value);
  public static Length<T> FromKilometer(T value)  =>
      Create((value * T.CreateChecked(MetricMagnitudes.Kilo)));
  public static Length<T> FromFoot(T value)       =>
      Create((value * T.CreateChecked(Units.ConversionConstants.FeetToMeters)));

The conversion expression honours:
- magnitude (Kilo, Centi, Nano, …) -> MetricMagnitudes constants
- conversionFactor (FeetToMeters, PoundToKilograms, …) -> ConversionConstants
- offset (CelsiusToKelvinOffset, FahrenheitToKelvinOffset) -> additive after
  scaling, e.g. K = (F * FahrenheitScale) + FahrenheitToKelvinOffset

Implementation:
- GeneratorBase.Initialize is now virtual so QuantitiesGenerator can override
  it to load both dimensions.json and units.json (the base only loads one
  metadata file).
- New AddUnitFactories helper centralises the emission so V0 base, V1 base,
  and overload emit paths produce identical factory shapes.
- New BuildToBaseExpression composes the conversion expression from the
  unit's metadata.
- The legacy abstract Generate is preserved as a shim that calls
  GenerateInner with empty UnitsMetadata so other code paths still work.

If a unit name listed in availableUnits has no matching entry in units.json,
the factory falls back to identity and a future SEM00x diagnostic could
surface the gap (follow-up for the metadata-validation work in #60).

Test plan: MultiUnitFactoryTests covers identity (base unit), magnitude
scaling (Kilometer, Centimeter, Millimeter, Gram), conversion-factor
scaling (Foot, Inch, Mile, Pound), Time conversions (Minute, Hour),
overload inheritance (Distance.FromKilometer, Diameter.FromMillimeter,
Wavelength.FromNanometer), and storage genericity (float, decimal).

Note: the on-disk Generated/*.g.cs files are not regenerated in this commit
(no dotnet available locally). CI's first build with the new generator will
emit the new factories in-memory and the tests will pass; the committed
Generated/ files will be refreshed on the next regeneration sweep.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants