feat: add Data Mapper pattern#251
Conversation
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
Test Results 1 files 1 suites 2m 27s ⏱️ Results for commit f1dbb51. |
Code Coverage |
There was a problem hiding this comment.
Pull request overview
Adds a new Data Mapper pattern to PatternKit, including a fluent runtime mapper with validation hooks, a source generator to create mapper factories from attributed projections, and a production-shaped example integrated into the catalogs/docs/tests.
Changes:
- Introduce
IDataMapper<TDomain,TData>/DataMapper<TDomain,TData>runtime API with fluent builder, validation, and result/error types. - Add Roslyn incremental generator + abstractions attributes + diagnostics + generator tests for
[GenerateDataMapper]. - Add “Order Data Mapper” example with DI integration, plus catalog/toc/docs updates and example/test coverage.
Reviewed changes
Copilot reviewed 22 out of 22 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| test/PatternKit.Tests/Application/DataMapping/DataMapperTests.cs | Runtime unit tests for fluent mapper mapping, validation failures, builder enforcement, and cancellation. |
| test/PatternKit.Generators.Tests/DataMapperGeneratorTests.cs | Verifies generator emits factory code and reports PKMAP00x diagnostics. |
| test/PatternKit.Generators.Tests/AbstractionsAttributeCoverageTests.cs | Adds Data Mapper generator attributes to attribute coverage suite. |
| test/PatternKit.Examples.Tests/ProductionReadiness/PatternKitPatternCatalogTests.cs | Updates catalog expectations to include Data Mapper and adjusts pattern family counts. |
| test/PatternKit.Examples.Tests/DependencyInjection/PatternKitExampleDependencyInjectionTests.cs | Ensures Data Mapper example is registered and runnable via DI example suite. |
| test/PatternKit.Examples.Tests/DataMapperDemo/OrderDataMapperDemoTests.cs | End-to-end example tests for fluent/generated mapping paths, validation, and DI import. |
| src/PatternKit.Generators/DataMapping/DataMapperGenerator.cs | New incremental generator emitting DataMapper<,> factories from attributed projections. |
| src/PatternKit.Generators/AnalyzerReleases.Unshipped.md | Documents new generator diagnostics PKMAP001–PKMAP003. |
| src/PatternKit.Generators.Abstractions/DataMapping/DataMapperAttributes.cs | Adds [GenerateDataMapper], [DataMapperToData], [DataMapperToDomain] attributes for consumers. |
| src/PatternKit.Examples/ProductionReadiness/PatternKitPatternCatalog.cs | Registers Data Mapper as a documented pattern with links to runtime/generator/example assets. |
| src/PatternKit.Examples/ProductionReadiness/PatternKitExampleCatalog.cs | Adds the Order Data Mapper example descriptor to the example catalog. |
| src/PatternKit.Examples/DependencyInjection/PatternKitExampleServiceCollectionExtensions.cs | Wires the Order Data Mapper example into AddPatternKitExamples and adds a typed example record + registration method. |
| src/PatternKit.Examples/DataMapperDemo/OrderDataMapperDemo.cs | New order persistence demo using Data Mapper + Repository, with DI import extension and generated mapper host. |
| src/PatternKit.Core/Application/DataMapping/DataMapper.cs | Implements the runtime Data Mapper API, builder, result, and error model. |
| docs/patterns/toc.yml | Adds Data Mapper to the patterns TOC under Application Architecture. |
| docs/patterns/application/data-mapper.md | New pattern documentation describing usage and integration guidance. |
| docs/guides/pattern-coverage.md | Adds Data Mapper to the pattern coverage matrix. |
| docs/generators/toc.yml | Adds Data Mapper generator docs to generators TOC. |
| docs/generators/index.md | Adds Data Mapper to the generator index table. |
| docs/generators/data-mapper.md | New generator documentation including usage, diagnostics, and DI snippet. |
| docs/examples/toc.yml | Adds Order Data Mapper Pattern to examples TOC. |
| docs/examples/order-data-mapper-pattern.md | New example documentation describing import, behavior, and source locations. |
Comments suppressed due to low confidence (1)
src/PatternKit.Generators/DataMapping/DataMapperGenerator.cs:127
- Generated type declaration always emits
partial class/partial structbased onTypeKind, ignoringtype.IsRecord. If a consumer applies[GenerateDataMapper]to apartial recordhost (allowed byAttributeTargets.Class), the generated partial declaration will not match and will fail to compile. Consider emittingpartial record class/partial record structwhentype.IsRecordis true (or reporting a diagnostic to disallow records).
sb.Append(GetAccessibility(type.DeclaredAccessibility)).Append(' ');
if (type.IsStatic)
sb.Append("static ");
else if (type.IsAbstract && type.TypeKind == TypeKind.Class)
sb.Append("abstract ");
else if (type.IsSealed && type.TypeKind == TypeKind.Class)
sb.Append("sealed ");
sb.Append("partial ").Append(type.TypeKind == TypeKind.Struct ? "struct" : "class").Append(' ').Append(type.Name).AppendLine();
sb.AppendLine("{");
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| var ns = type.ContainingNamespace.IsGlobalNamespace ? null : type.ContainingNamespace.ToDisplayString(); | ||
| var domainName = domainType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); | ||
| var dataName = dataType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); | ||
| var sb = new StringBuilder(); | ||
| sb.AppendLine("// <auto-generated/>"); | ||
| sb.AppendLine("#nullable enable"); | ||
| sb.AppendLine(); | ||
| if (ns is not null) | ||
| { | ||
| sb.Append("namespace ").Append(ns).AppendLine(";"); | ||
| sb.AppendLine(); | ||
| } | ||
|
|
||
| sb.Append(GetAccessibility(type.DeclaredAccessibility)).Append(' '); | ||
| if (type.IsStatic) | ||
| sb.Append("static "); | ||
| else if (type.IsAbstract && type.TypeKind == TypeKind.Class) | ||
| sb.Append("abstract "); | ||
| else if (type.IsSealed && type.TypeKind == TypeKind.Class) | ||
| sb.Append("sealed "); | ||
| sb.Append("partial ").Append(type.TypeKind == TypeKind.Struct ? "struct" : "class").Append(' ').Append(type.Name).AppendLine(); | ||
| sb.AppendLine("{"); |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #251 +/- ##
==========================================
+ Coverage 90.88% 96.17% +5.28%
==========================================
Files 320 324 +4
Lines 29577 29850 +273
Branches 4116 4163 +47
==========================================
+ Hits 26880 28707 +1827
+ Misses 1206 1143 -63
+ Partials 1491 0 -1491
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
🔍 PR Validation ResultsVersion: `` ✅ Validation Steps
📊 ArtifactsDry-run artifacts have been uploaded and will be available for 7 days. This comment was automatically generated by the PR validation workflow. |
Summary
Validation
Local examples build is blocked by the existing Roslyn analyzer/compiler mismatch (CS9057), so hosted CI validates the examples path.