Skip to content

Latest commit

 

History

History
86 lines (62 loc) · 10.6 KB

File metadata and controls

86 lines (62 loc) · 10.6 KB

Changelog

3.0.0

Breaking Changes

  • Issue #1: ordinary unmapped target properties and fields now default to errors; explicit target policies and IgnoreTarget/UseTargetDefault opt-outs remain supported, while unmapped source members remain ignored by default. Unmapped-member diagnostics identify the exact source or target member. #1

Changed

  • Issue #7: documented opt-in strict source-member completeness across mapper, method, and assembly scopes, including staged LITEMAPPER1003 severities, editorconfig overrides, intentional IgnoreSource exceptions, and the rationale for the default Ignore policy. #7
  • Issue #6: existing-target updates now have documented non-transactional semantics with deterministic target-member evaluation and assignment order. Earlier assignments remain when a later mapping operation fails, while per-member captures prevent repeated source getter/path evaluation where guards and assignments both need the value. #6
  • Issue #5: closed constructed static generic external registration containers are now supported; unbound generic registrations and generic methods remain rejected. Declaration, registration, constructor, accessibility, and diagnostic-contract coverage was expanded across the Roslyn host matrix. #5
  • Issue #4: clarified that ordinary unmapped-target suppression or downgrade does not suppress valid generation or prove complete mapping; mandatory target obligations remain hard errors, and CI guidance recommends treating configurable LITEMAPPER1001 as an error when full coverage is required. #4
  • Issue #3: generated nested and collection helper names are allocated deterministically within each mapper, reserve handwritten/generated helper signatures, reuse identical closed identities, and disambiguate preferred-name collisions independently of syntax-tree or equivalent compilation order. #3
  • Issue #2: assembly-wide LiteMapperDefaultsAttribute values and UseMapperAttribute registrations now participate explicitly in incremental mapper planning and emission invalidation. Same-driver regressions cover affected generated content and diagnostics while preserving unrelated cached output where Roslyn permits. #2

Fixed

  • Issue #11: existing-target mappings with NullableMismatch.Throw now evaluate and enforce nullable preconditions in deterministic per-member order, preserving earlier assignments when a later member fails. #11
  • Issue #12: declared cycle tracking now identifies mappings by symbol identity instead of method name, preventing overload false positives, invalid tracker arguments, and unnecessary tracking state. #12
  • Issue #13: direct nullable sources passed to nested updaters are evaluated once, preventing duplicate source getter or path evaluation. #13

2.0.0

Added

  • Added GuardNonNullSource to mapper and method options. For example, [LiteMapper(GuardNonNullSource = true)] generates an ArgumentNullException guard for a non-nullable root source parameter.
  • Added positional tuple-to-tuple mapping when arity matches and every element is convertible. For example, (Number: 7, Text: "seven") can map to (long Id, string Label) as (7L, "seven"); automatic tuple-to-object and object-to-tuple structural mapping remain unsupported.
  • Added an installable Mammoth.LiteMapper agent skill with source-backed guidance for declarations, configuration, nullability, converters, collections, recursion, diagnostics, and package usage.
  • Added Windows and Linux CI matrix jobs for Roslyn 4.8, 4.14, and 5.9, plus clean-package consumer coverage for netstandard2.0, .NET 8, .NET 9, and .NET 10 with C# 9, C# 14, and latest.

Changed

  • Non-nullable root source parameters no longer receive a runtime null guard by default. Enable GuardNonNullSource when runtime rejection is required.
  • Converter and mapping selection now applies method-level options, local-before-registered precedence, exact and nullable source-pair rules, inherited accessibility, and explicit Use configuration consistently at root, member, collection-element, and dictionary boundaries.
  • Unmarked handwritten local methods participate only when explicitly selected, marked with [MappingConverter] or [DefaultMapping], or matched by the documented Map{TargetMember} convention. Registering an external mapper container explicitly opts its compatible methods into selection.
  • Unknown-count enumerable sources are enumerated once when producing arrays. LiteMapper uses an O(n) temporary growing buffer before creating the final array; counted sources allocate the final array directly.
  • Package consumer tests now map all Mammoth.LiteMapper* packages exclusively to the local package source, preventing another feed from masking a missing package.
  • Diagnostic compatibility changed: LITEMAPPER2005, LITEMAPPER2006, and LITEMAPPER2007 now represent ambiguous conversion, disabled explicit operators, and disabled narrowing numeric conversion. Unreachable diagnostics LITEMAPPER4003, LITEMAPPER6002, and LITEMAPPER6003 were removed; unsupported custom collections continue to use LITEMAPPER4006, and invalid option values use LITEMAPPER0008.

Fixed

  • Fixed converter-result conversions, including checked and unchecked numeric conversions, user-defined operators, nullable results, and once-only null checks. For example, a converter returning int? can now map to long under the configured Error or Throw policy without evaluating the converter twice.
  • Fixed cross-type nullability for boxed values, nullable enums, collection elements, configured source paths, and patch updates. For example, From? value Ready = 1 maps by name to To? value Ready = 9 while preserving null.
  • Fixed inherited member and converter discovery across base classes and interfaces, including diamond inheritance, hiding, ambiguity, and normal overload binding. For example, ISource : IBase now maps an inherited Value == 3 to Target.Value == 3.
  • Fixed nested existing-target updates, including get-only identity preservation, writable replacement, local and registered updater selection, nullable path policies, and recursive tracker forwarding.
  • Fixed constructor, record, init, required, readonly-member, optional-default, and value-type construction behavior, including recursive and nullable conversions used by constructor arguments.
  • Fixed collection materialization and updates for arrays, list and read-only interfaces, sets, dictionaries, nullable elements, comparer preservation, collision detection, and configured nested paths.
  • Fixed enum mapping for aliases, signed flags, named composites, declared numeric overflow, unknown values, and once-only configured-path evaluation.
  • Fixed diagnostic severity handling, invalid-member configuration, unsupported generated types, async declaration detection on newer Roslyn hosts, generated identifier collisions, and mapper isolation so one invalid method does not suppress unrelated valid mappings.
  • Fixed incremental output isolation and deterministic ordering across source-file insertion, removal, and unrelated declaration changes.
  • Fixed package, trimming, Native AOT, sample, and benchmark process execution so stdout and stderr are drained concurrently and one bounded timeout covers child exit and retained pipes.

Performance

  • Eligible direct flat new-object mappings now request MethodImplOptions.AggressiveInlining when the compilation exposes the exact public framework capability. For example, a straight Source.Value to Target.Value copy receives the hint, while nullable, guarded, constructor-bound, collection, recursive, helper-based, and update mappings do not.
  • On the recorded .NET 10 benchmark environment, paired measurements report 4.465 ns for LiteMapper and 4.307 ns for manual mapping, with 40-byte allocation for both. Disassembly shows the LiteMapper mapping body inlined into one 70-byte method, removing the previous separate mapper call.

Security

  • Updated the Source Link dependency to a patched release that resolves the affected Microsoft.Build.Tasks.Git dependency without suppressing NuGet audit diagnostics.

1.0.0

Initial LiteMapper 1.0 implementation completed against SPECIFICATION.md.

Added

  • Public Mammoth.LiteMapper abstraction API, including mapper/configuration attributes, option enums, and LiteMapperCycleException.
  • Roslyn incremental source generator for compile-time C# object mapping with deterministic generated output.
  • Static, instance, extension-method, new-object, and existing-target mapper method support.
  • Flat, nested, collection, dictionary, enum, nullable, constructor, record, init, required, value-type, and recursive mapping support.
  • Explicit member configuration, ignore/default controls, local and registered converter resolution, default mapping selection, and configuration precedence.
  • Compile-time diagnostics for invalid declarations, unsupported mapping shapes, ambiguous mappings, invalid configuration, nullability, collections, existing-target mappings, recursion, enums, and internal generator failures.
  • Package layout for Mammoth.LiteMapper, Mammoth.LiteMapper.Abstractions, and Mammoth.LiteMapper.Generator, with analyzer assets kept out of consumer runtime output.
  • Package-consumer, trimming, Native AOT, API compatibility, deterministic package-content, generated-source, runtime, incremental, and capability validation.
  • Compiling Basic, Collections, and ASP.NET Core samples.
  • BenchmarkDotNet flat-object benchmark comparing manual mapping, LiteMapper, Mapperly, Mapster, and AutoMapper.
  • Source-backed usage guide at docs/USAGE.md.

Notes

  • Normal consumers install Mammoth.LiteMapper; the generator is delivered as an analyzer asset.
  • Supported generated paths use direct C# and no runtime reflection, runtime type scanning, dynamic dispatch, or runtime mapper registry.
  • Release-quality benchmark interpretation remains separate from the dry-run benchmark smoke validation recorded during implementation.