Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

## Fixes

- Issue #24: partial mappers with framework attributes or `UseMapper` on another part now generate once; genuine duplicate `LiteMapper` configuration still reports one fatal diagnostic. [#24](https://github.com/PrimordialCode/Mammoth.LiteMapper/issues/24)
- Issue #23: explicit omitted-`Source` converters receive the root object before automatic source-member matching in new-object, constructor-bound, and update mappings. Unrelated source names and patch getters no longer override that selection. [#23](https://github.com/PrimordialCode/Mammoth.LiteMapper/issues/23)
- Issue #22: generated nested and collection helpers preserve the calling mapper instance for stateful converters and mappings, while instance-free helpers remain static. Static entry methods no longer select instance-only mappings. [#22](https://github.com/PrimordialCode/Mammoth.LiteMapper/issues/22)
- Issue #21: nested and collection helpers retain each entry method's effective mapping policies and nullable shape. Equivalent recursive helpers remain shared while preserving the initiating entry's cycle metadata. [#21](https://github.com/PrimordialCode/Mammoth.LiteMapper/issues/21)
Expand Down
7 changes: 7 additions & 0 deletions DECISIONS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Mammoth.LiteMapper Decision Log

## Issue #24: discover the marker-owning partial declaration once (2026-10-09)

- Context: broad attributed-type discovery sees the merged LiteMapper marker on every attributed partial part. Repeated planning yields duplicate diagnostics and source hint collisions that discard unrelated generated output.
- Decision: retain the existing incremental syntax-provider identity and select the declaration containing the symbol's first LiteMapper marker before planning. The owner check also handles genuinely repeated markers, allowing existing merged-symbol validation to report LITEMAPPER0013 once. No compilation-wide collect/deduplicate stage or mutable generator state is introduced. A first ForAttributeWithMetadataName candidate recreated output identities for cross-file removal and tree reordering on Roslyn 4.8; the narrower owner filter preserves the established caching contract without weakening existing tests.
- Contract: sections 7, 19.2, 19.3, 19.7, 20.2, and 21.4 already require one file per mapper, duplicate-configuration validation, and incremental isolation. All members and registrations still come from the merged symbol; no public API or specification semantics change is required.
- Evidence: 24 initial tests on unchanged production yielded 23 failures and one unattributed-part control, zero skips; the Basic sample separately failed with CS8785 and three CS8795 errors. Focused cases cover declaration shapes, aliases, registrations, warning/fault diagnostic counts, duplicate markers, ordering, and same-driver changes.

## Issue #23: resolve explicit root input before member matching (2026-10-08)

- Context: new-object planning rejected absent source-member matches before resolving a root converter. Constructor/update planning also allowed automatic ambiguity or patch captures to override the explicit selection.
Expand Down
8 changes: 8 additions & 0 deletions IMPLEMENTATION_PLAN.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Mammoth.LiteMapper Implementation Plan

## Issue #24: one discovery per partial mapper (2026-10-09)

- Scope: a single marker-owning declaration per mapper symbol, retaining the established incremental candidate identity. Other partial declarations may carry framework attributes or UseMapper registrations without duplicating planning, diagnostics, or generated source. Genuine duplicate LiteMapper markers remain invalid.
- Test-first: 24 focused same-file/multi-file partial-declaration, registration, diagnostic, planning-count, alias, ordering, and same-driver cases produced 23 failures and one control on unchanged production. The Basic sample independently failed CS8785/CS8795 after adding another attributed partial part. Clean-package validation exercises the same sample.
- Implementation: a minimal discovery-boundary change that preserves merged symbol validation and existing per-mapper emission equality. No compilation-wide deduplication or mutable generator state.
- Validation: focused and full generator tests, runtime/integration checks, source samples and available packaging checks; independent review and exact-head ordinary PR CI. Record unavailable toolchain stages separately.
- Boundary: issue #24 only, no public API or specification semantics change. Stop at draft PR/human review; no merge, release, tag, package publication, or workflow dispatch.

## Issue #23: explicit root-source converter priority (2026-10-08)

- Scope: select omitted-`Source` explicit `Use` configuration before automatic source-member matching in new-object, constructor-bound, and existing-target planning. Keep source-path selection and converter validation intact.
Expand Down
10 changes: 10 additions & 0 deletions STATUS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Mammoth.LiteMapper Status

## GitHub issue #24 partial-discovery checkpoint (2026-10-09)

- Base: isolated cloud worktree from develop 1583ddbcff4e14e677d92acba86d222567196824 after PR #37 merged. Issue #24 is open with no dependencies/sub-issues or competing PR. The user authorized one next issue; exec:agent and ready:agent were added and read back. AgentStack CLI is absent; authorized connector fallback is used without issue comments or claim writes.
- Red-first: all 24 new tests compile against unchanged production with 23 failures and one unattributed-part control, zero skips. The Basic sample separately fails with duplicate-source CS8785 and missing implementations for all three mappers (CS8795).
- Implementation: filter semantic discovery to the declaration that owns the merged symbol's first LiteMapper marker. Other attributed parts still contribute members and registrations, while duplicate markers produce one existing LITEMAPPER0013. The Basic sample and clean-package sample checks cover an unrelated attribute on another partial part; usage/changelog are synchronized.
- Candidate refinement: an initial ForAttributeWithMetadataName candidate recreated candidate identity in two existing caching tests. The narrower marker-owner filter preserves the existing syntax-provider pipeline and passes all 23 existing incremental-isolation tests without changing them. The new harness counts active tracked outputs separately from Removed entries; semantic planning may re-run once per mapper while unchanged emissions remain cached.
- Final local validation: Release solution build has zero warnings/errors. All 676 generator tests pass, including 24 new cases; runtime five and integration one pass, zero failures/skips. All three source sample smoke runs pass. Available packaging suite: 220 passed, two infrastructure failures, zero skips, including all 12 consumer framework/language combinations, clean package-backed samples, package/API checks, usage validation, and benchmark smoke. Generated Basic source was inspected: exactly one file per mapper, with the existing mapping body intact; the rebuilt sample passed again. Independent read-only review found no blocker; CRLF-aware diff validation passes. Exact-head ordinary CI belongs in the draft PR.
- Environment: the fresh cloud workspace lacked .NET. With user approval, official Microsoft SDK 10.0.401 and runtimes 8.0.31/9.0.20 were downloaded, verified against published SHA-512 hashes, and installed in the task workspace; runtime 10.0.12 is included. An initial restore failed to write the default read-only NuGet cache; configuring workspace-local cache paths allowed explicit solution restore to complete. PowerShell and clang are absent; 49 PowerShell-dependent cases were not run locally. Trimming and Native AOT fail at ILLink ComputeManagedAssemblies task-host creation (MSB4216 / Unix-domain SocketException 13), before publish behavior is established. No local trimming/AOT success is claimed and no assertion, dependency, warning, or prerequisite was weakened. No security or credential settings changed.
- Boundary: issue #24 only, then draft PR/human review. No user-computer access, merge, release, tag push, package publication, or workflow dispatch.

## GitHub issue #23 root converter priority checkpoint (2026-10-08)

- Base: isolated cloud worktree from develop d80ff4cc6a5e515896b6054a454a1ee2910450a5 after PR #36 merged. Issue #23 is open with no dependencies/sub-issues or competing PR. The user requested the next issue; exec:agent and ready:agent were added and read back, preserving existing labels. AgentStack CLI is absent; authorized connector fallback is used without issue comments or claim writes.
Expand Down
2 changes: 2 additions & 0 deletions docs/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ Normal consumers reference the primary package only:

A generated mapper is a partial method inside a class marked with `[LiteMapper]`.

Apply `[LiteMapper]` once across the mapper's partial declarations. Other parts may contain mapping methods, `[UseMapper]` registrations, or unrelated attributes. LiteMapper combines those parts into one generated file. Repeating `[LiteMapper]` is invalid and reports `LITEMAPPER0013`. The Basic sample includes a separate partial part with `[DebuggerDisplay]`.

From `samples/Mammoth.LiteMapper.Samples.Basic/Program.cs`:

```csharp
Expand Down
5 changes: 5 additions & 0 deletions samples/Mammoth.LiteMapper.Samples.Basic/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ public static partial class StaticMapper
private static string BuildDisplayName(StaticSource source) => "Name: " + source.Name;
}

[System.Diagnostics.DebuggerDisplay("Static mapper")]
public static partial class StaticMapper
{
}

[LiteMapper]
public sealed partial class InstanceMapper
{
Expand Down
5 changes: 4 additions & 1 deletion src/Mammoth.LiteMapper.Generator/LiteMapperGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,10 @@ private static bool IsTypeWithAttributes(SyntaxNode node)
{
var typeSyntax = (TypeDeclarationSyntax)context.Node;
var symbol = context.SemanticModel.GetDeclaredSymbol(typeSyntax, cancellationToken) as INamedTypeSymbol;
if (symbol == null || !HasAttribute(symbol, LiteMapperAttributeName))
// Only the part owning the first marker plans the merged mapper. Other
// attributed parts must not duplicate source or configuration diagnostics.
var marker = symbol?.GetAttributes().FirstOrDefault(static attribute => IsAttribute(attribute, LiteMapperAttributeName))?.ApplicationSyntaxReference;
if (symbol == null || marker == null || marker.SyntaxTree != typeSyntax.SyntaxTree || !typeSyntax.Span.Contains(marker.Span))
{
return null;
}
Expand Down
Loading
Loading