Skip to content

Commit 53a8098

Browse files
committed
Milestone 11: enum mapping
- Added support for enum-to-enum mapping with direct switch expressions and checked/unchecked casting. - Integrated enum handling into the existing conversion resolver, eliminating the need for runtime mapper abstractions. - Introduced diagnostics for unmapped enum members, alias conflicts, and value overflows. - Completed tests for by-name and by-value enum mapping strategies, ensuring compliance with specified policies. - Updated implementation plan and decision log to reflect the completion of Milestone 11.
1 parent 997a21a commit 53a8098

7 files changed

Lines changed: 738 additions & 15 deletions

File tree

‎DECISIONS.md‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,16 @@
224224
- Specification references: 3.2, 16.1, 16.3, 19.7, 24.4.
225225
- Consequences: Update generated source remains private/direct and shares helper generation with new-object mappings; exact update local formatting is not public API.
226226

227+
### DEC-0024
228+
229+
- Date: 2026-06-18
230+
- Milestone: 11
231+
- Status: Accepted
232+
- Context: Enum mappings need direct generated behavior without adding runtime mapper abstractions, registries, or reflection.
233+
- Decision: Integrate enum handling into the existing conversion resolver and emit direct switch expressions or checked/unchecked casts. For `[Flags]` by-name runtime composites, emit direct bit-test reconstruction over mapped atomic flags.
234+
- Specification references: 13, 19.7, 24.1, 28.4.
235+
- Consequences: Enum mapping remains deterministic generated source and private implementation detail; generated flags composite validation uses `System.Convert.ToUInt64` and ordinary bit operations rather than runtime reflection or dynamic dispatch.
236+
227237
## Pending specification questions
228238

229239
### PENDING-0001

‎IMPLEMENTATION_PLAN.md‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,11 @@
201201
- Focused validation: enum tests.
202202
- Full validation: full solution tests.
203203
- Completion criteria: enum behavior and throws match section 13.
204-
- Risks: alias and flags decomposition edge cases.
204+
- Status: Completed on 2026-06-18 with by-name enum switch generation, checked/unchecked by-value conversion, `UnmatchedEnumValues` policy handling, source/target alias validation, zero-member validation, flags atomic validation, runtime flags composite reconstruction, runtime unknown-value throws, custom converter precedence, enum diagnostics, and a checked-in generated-source snapshot.
205+
- Deviations: enum rendering is integrated into the existing conversion resolver and top-level direct-conversion path rather than a separate planner type.
206+
- Remaining tasks: none for Milestone 11.
207+
- Validation commands: `dotnet test tests\Mammoth.LiteMapper.Generator.Tests\Mammoth.LiteMapper.Generator.Tests.csproj --no-restore --filter Milestone11EnumMappingTests` initially failed for expected missing enum behavior, then passed with 7 tests after implementation and snapshot assertion; `dotnet test tests\Mammoth.LiteMapper.Generator.Tests\Mammoth.LiteMapper.Generator.Tests.csproj --no-restore` passed with 48 tests; `dotnet restore Mammoth.LiteMapper.sln` passed; `dotnet build Mammoth.LiteMapper.sln --no-restore` passed with 0 warnings; `dotnet test Mammoth.LiteMapper.sln --no-build` passed with 60 total tests; `git diff --check` passed.
208+
- Risks: broader TFM/language matrix remains a later capability/portability milestone; flags reconstruction currently uses generated direct bit tests and `System.Convert.ToUInt64` for runtime composite validation.
205209
- Out of scope: recursive cycle detection.
206210

207211
## Milestone 12: recursive type analysis and ThrowOnCycle

‎STATUS.md‎

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
# Mammoth.LiteMapper Status
22

3-
- Current milestone: Milestone 10, existing-target mapping and patch behavior.
3+
- Current milestone: Milestone 11, enum mapping.
44
- Current state: Complete.
5-
- Completed milestones: Milestone 1; Milestone 2; Milestone 3; Milestone 4; Milestone 5; Milestone 6; Milestone 7; Milestone 8; Milestone 9; Milestone 10.
5+
- Completed milestones: Milestone 1; Milestone 2; Milestone 3; Milestone 4; Milestone 5; Milestone 6; Milestone 7; Milestone 8; Milestone 9; Milestone 10; Milestone 11.
66
- Current work: None.
7-
- Work completed: Added generated existing-target mapping for void updates, destination-returning reference updates, nullable destination-returning replacement construction, `ref` struct updates, runtime null destination checks, direct scalar assignments, writable nested replacement, collection replacement, and `IgnoreNullSourceMembers` patch guards for direct source members and configured source paths.
8-
- Tests added or updated: Added `Milestone10ExistingTargetMappingTests` covering void/reference-returning updates, `ref` struct update, nullable destination-returning construction, null destination checks, nested source-path patch behavior, collection replacement, init-only rejection, get-only collection rejection, top-level array-update rejection, and `IgnoreNullSourceMembers` warning on new-object mappings. Added `Snapshots/Milestone10ExistingTarget.Mapper.g.cs`.
9-
- Diagnostics added: Added `LITEMAPPER5001` InvalidUpdateSignature, `LITEMAPPER5002` NullableVoidDestinationNotSupported, `LITEMAPPER5003` StructUpdateRequiresRef, `LITEMAPPER5004` InitOnlyMemberCannotBeUpdated, `LITEMAPPER5005` NestedUpdateMappingRequired, and `LITEMAPPER5006` IgnoreNullOnlyValidForUpdate.
10-
- Generated-source review: Representative Milestone 10 generated source is checked in and asserted. Reviewed output emits public partial update methods, direct destination assignments, `ArgumentNullException` guards for non-null destinations, nullable destination construction for returning updates, patch null-skipping guards, private deterministic collection/nested helpers, and no `System.Reflection`, `dynamic`, runtime registry, or runtime code generation.
11-
- Validation evidence: `dotnet test tests\Mammoth.LiteMapper.Generator.Tests\Mammoth.LiteMapper.Generator.Tests.csproj --no-restore --filter Milestone10ExistingTargetMappingTests` initially failed for expected missing update behavior, then passed with 4 tests after implementation and snapshot assertion; `dotnet test tests\Mammoth.LiteMapper.Generator.Tests\Mammoth.LiteMapper.Generator.Tests.csproj --no-restore` passed with 41 tests; `dotnet restore Mammoth.LiteMapper.sln` passed; `dotnet build Mammoth.LiteMapper.sln --no-restore` passed with 0 warnings; `dotnet test Mammoth.LiteMapper.sln --no-build` passed with 53 total tests; `git diff --check` passed.
12-
- Skipped validation: package-consumer, trimming, Native AOT, public package API compatibility, benchmarks, broader TFM/language/Roslyn matrix validation, enum mapping, recursive mapping and cycle tracking, explicit operators, numeric narrowing policy, target-specific emitted optimization, and compiling sample/documentation validation are later-milestone validations.
7+
- Work completed: Added enum-to-enum mapping for top-level and member conversions, by-name switch-expression rendering with runtime unknown-value throws, by-value checked/unchecked casting, `UnmatchedEnumValues` policy handling, source alias validation, target alias support, zero-member validation, `[Flags]` atomic validation, runtime flags composite reconstruction, and custom converter precedence over enum strategy.
8+
- Tests added or updated: Added `Milestone11EnumMappingTests` covering by-name mapping, by-value mapping, unknown runtime numeric values, source aliases, target aliases through name selection, zero members, flags and composite flags, declared numeric overflow, `UnmatchedEnumValues.Throw`, `UnmatchedEnumValues.ByValue`, and custom converter precedence. Added `Snapshots/Milestone11EnumMapping.Mapper.g.cs`.
9+
- Diagnostics added: Added `LITEMAPPER7001` EnumMemberNotMapped, `LITEMAPPER7002` EnumAliasConflict, `LITEMAPPER7003` EnumZeroMemberNotMapped, `LITEMAPPER7004` EnumFlagNotMapped, and `LITEMAPPER7005` EnumValueOverflow.
10+
- Generated-source review: Representative Milestone 11 generated source is checked in and asserted. Reviewed output emits public partial enum mapping methods, direct switch expressions, checked casts for by-value mappings, deterministic enum member ordering, `ArgumentOutOfRangeException` default arms for unknown runtime values, and no `System.Reflection`, `dynamic`, runtime registry, or runtime code generation.
11+
- Validation evidence: `dotnet test tests\Mammoth.LiteMapper.Generator.Tests\Mammoth.LiteMapper.Generator.Tests.csproj --no-restore --filter Milestone11EnumMappingTests` initially failed for expected missing enum behavior, then passed with 7 tests after implementation and snapshot assertion; `dotnet test tests\Mammoth.LiteMapper.Generator.Tests\Mammoth.LiteMapper.Generator.Tests.csproj --no-restore` passed with 48 tests; `dotnet restore Mammoth.LiteMapper.sln` passed; `dotnet build Mammoth.LiteMapper.sln --no-restore` passed with 0 warnings; `dotnet test Mammoth.LiteMapper.sln --no-build` passed with 60 total tests; `git diff --check` passed.
12+
- Skipped validation: package-consumer, trimming, Native AOT, public package API compatibility, benchmarks, broader TFM/language/Roslyn matrix validation, recursive mapping and cycle tracking, explicit operators, numeric narrowing policy, target-specific emitted optimization, and compiling sample/documentation validation are later-milestone validations.
1313
- Blockers: none known.
14-
- Known issues: configurable unmapped-member diagnostics use paired internal descriptors with the same stable IDs and should receive editorconfig override coverage in future diagnostics work; constructor-parameter explicit configuration and optional-parameter `UseTargetDefault` interactions need broader coverage when constructor binding is expanded beyond current member-initializer scenarios; recursive nested and collection type graphs currently lack cycle-tracker plumbing until Milestone 12; enum mapping remains pending until Milestone 11.
15-
- Next permitted action: Milestone 11, enum mapping.
14+
- Known issues: configurable unmapped-member diagnostics use paired internal descriptors with the same stable IDs and should receive editorconfig override coverage in future diagnostics work; constructor-parameter explicit configuration and optional-parameter `UseTargetDefault` interactions need broader coverage when constructor binding is expanded beyond current member-initializer scenarios; recursive nested and collection type graphs currently lack cycle-tracker plumbing until Milestone 12.
15+
- Next permitted action: Milestone 12, recursive type analysis and `ThrowOnCycle`.

‎src/Mammoth.LiteMapper.Generator/Diagnostics.cs‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ internal static class Diagnostics
4848
public static readonly DiagnosticDescriptor InitOnlyMemberCannotBeUpdated = Error("LITEMAPPER5004", "InitOnlyMemberCannotBeUpdated", "Update attempts to assign an init-only member");
4949
public static readonly DiagnosticDescriptor NestedUpdateMappingRequired = Error("LITEMAPPER5005", "NestedUpdateMappingRequired", "Get-only/existing nested mutation lacks explicit update mapping");
5050
public static readonly DiagnosticDescriptor IgnoreNullOnlyValidForUpdate = Warning("LITEMAPPER5006", "IgnoreNullOnlyValidForUpdate", "Patch null-skipping was configured on a new-object mapping");
51+
public static readonly DiagnosticDescriptor EnumMemberNotMapped = Error("LITEMAPPER7001", "EnumMemberNotMapped", "Source enum member '{0}' has no target mapping");
52+
public static readonly DiagnosticDescriptor EnumAliasConflict = Error("LITEMAPPER7002", "EnumAliasConflict", "Enum aliases for value '{0}' map inconsistently");
53+
public static readonly DiagnosticDescriptor EnumZeroMemberNotMapped = Error("LITEMAPPER7003", "EnumZeroMemberNotMapped", "Source enum zero member '{0}' has no target mapping");
54+
public static readonly DiagnosticDescriptor EnumFlagNotMapped = Error("LITEMAPPER7004", "EnumFlagNotMapped", "Source enum flag '{0}' has no target mapping");
55+
public static readonly DiagnosticDescriptor EnumValueOverflow = Error("LITEMAPPER7005", "EnumValueOverflow", "Enum value '{0}' cannot fit destination underlying type");
5156
public static readonly DiagnosticDescriptor UnmappedSourceMember = Info("LITEMAPPER1003", "UnmappedSourceMember", "Source member '{0}' is not mapped");
5257
public static readonly DiagnosticDescriptor UnmappedSourceMemberWarning = Warning("LITEMAPPER1003", "UnmappedSourceMember", "Source member '{0}' is not mapped");
5358
public static readonly DiagnosticDescriptor InternalGeneratorFailure = Error("LITEMAPPER9001", "InternalGeneratorFailure", "Unexpected failure while processing mapper '{0}'");

0 commit comments

Comments
 (0)