feat: add LayeredCraft.OptimizedEnums.EFCore package#10
Conversation
Adds a new source generator package that emits EF Core value converters and property builder extension methods for OptimizedEnum types. Decorate a sealed partial OptimizedEnum class with [OptimizedEnumEfCore] to get ByValue and ByName converters, plus a ConfigureOptimizedEnums() convention hook, generated at compile time with zero reflection. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2f81960c81
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
src/LayeredCraft.OptimizedEnums.EFCore.Generator/Templates/OptimizedEnumEfCore.scriban
Outdated
Show resolved
Hide resolved
src/LayeredCraft.OptimizedEnums.EFCore.Generator/Emitters/EfCoreEmitter.cs
Outdated
Show resolved
Hide resolved
- Remove unused EfCoreSyntaxProvider_FilterErrors constant from TrackingNames - Fix O(n²) Insert(0,...) pattern in GetContainingTypeSimpleNames with Add+Reverse - Thread CancellationToken through all async EF Core calls in integration tests Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds a new LayeredCraft.OptimizedEnums.EFCore source generator package plus a dedicated test suite and technical spec to support zero-reflection, AOT-safe EF Core value conversions for OptimizedEnum types.
Changes:
- Introduces
LayeredCraft.OptimizedEnums.EFCore.Generatorincremental generator with attribute injection + per-enum converter/extension emission + shared conventions hook. - Adds EF Core generator snapshot tests (Verify) and EF integration tests (InMemory + PostgreSQL via Testcontainers).
- Adds EF Core package technical specification and central package versions for EF Core/Npgsql/Testcontainers.
Reviewed changes
Copilot reviewed 73 out of 73 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/xunit.runner.json | xUnit runner configuration for the new EFCore test project. |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/ModuleInitializer.cs | Initializes Verify.SourceGenerators for the EFCore test suite. |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/LayeredCraft.OptimizedEnums.EFCore.Tests.csproj | New multi-targeted EFCore test project setup + dependencies. |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/IntegrationTests/TestEnums.cs | Test OptimizedEnum types used by EF integration tests. |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/IntegrationTests/TestDbContext.cs | InMemory + relational DbContexts and manual converters for integration tests. |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/IntegrationTests/RelationalTests.cs | PostgreSQL/Testcontainers integration coverage for keys/indexes. |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/IntegrationTests/ConversionTests.cs | InMemory integration coverage for conversions and null behavior. |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/GeneratorTests/GeneratorVerifyTests.cs | Snapshot test cases for generator outputs + diagnostics. |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/GeneratorTests/GeneratorTestHelpers.cs | Roslyn harness to run generators and Verify outputs. |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.ByValue_WithNamespace#OptimizedEnumEfCoreConventions.g.verified.cs | Verify snapshot: conventions output (ByValue, namespaced). |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.ByValue_WithNamespace#OptimizedEnumEfCoreAttribute.g.verified.cs | Verify snapshot: injected attribute source (ByValue, namespaced). |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.ByValue_WithNamespace#MyApp.Domain.OrderStatus.g.verified.cs | Verify snapshot: core OptimizedEnum generation for OrderStatus. |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.ByValue_WithNamespace#MyApp.Domain.OrderStatus.EFCore.g.verified.cs | Verify snapshot: EFCore converters/extensions for OrderStatus. |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.ByName_WithNamespace#OptimizedEnumEfCoreConventions.g.verified.cs | Verify snapshot: conventions output (ByName, namespaced). |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.ByName_WithNamespace#OptimizedEnumEfCoreAttribute.g.verified.cs | Verify snapshot: injected attribute source (ByName, namespaced). |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.ByName_WithNamespace#MyApp.Domain.OrderStatus.g.verified.cs | Verify snapshot: core OptimizedEnum generation for OrderStatus (ByName case). |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.ByName_WithNamespace#MyApp.Domain.OrderStatus.EFCore.g.verified.cs | Verify snapshot: EFCore converters/extensions for OrderStatus (ByName default). |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.ByValue_GlobalNamespace#Priority.g.verified.cs | Verify snapshot: core OptimizedEnum generation for global-ns Priority. |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.ByValue_GlobalNamespace#Priority.EFCore.g.verified.cs | Verify snapshot: EFCore converters/extensions for global-ns Priority (ByValue). |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.ByValue_GlobalNamespace#OptimizedEnumEfCoreConventions.g.verified.cs | Verify snapshot: conventions output (ByValue, global-ns). |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.ByValue_GlobalNamespace#OptimizedEnumEfCoreAttribute.g.verified.cs | Verify snapshot: injected attribute source (ByValue, global-ns). |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.ByName_GlobalNamespace#Priority.g.verified.cs | Verify snapshot: core OptimizedEnum generation for Priority (ByName case). |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.ByName_GlobalNamespace#Priority.EFCore.g.verified.cs | Verify snapshot: EFCore converters/extensions for Priority (ByName). |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.ByName_GlobalNamespace#OptimizedEnumEfCoreConventions.g.verified.cs | Verify snapshot: conventions output (ByName, global-ns). |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.ByName_GlobalNamespace#OptimizedEnumEfCoreAttribute.g.verified.cs | Verify snapshot: injected attribute source (ByName, global-ns). |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.ByValue_StringValueType#OptimizedEnumEfCoreConventions.g.verified.cs | Verify snapshot: conventions output (ByValue, string TValue). |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.ByValue_StringValueType#OptimizedEnumEfCoreAttribute.g.verified.cs | Verify snapshot: injected attribute source (ByValue, string TValue). |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.ByValue_StringValueType#MyApp.Domain.Color.g.verified.cs | Verify snapshot: core OptimizedEnum generation for Color (string TValue). |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.ByValue_StringValueType#MyApp.Domain.Color.EFCore.g.verified.cs | Verify snapshot: EFCore converters/extensions for Color (ByValue). |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.ByName_StringValueType#OptimizedEnumEfCoreConventions.g.verified.cs | Verify snapshot: conventions output (ByName, string TValue). |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.ByName_StringValueType#OptimizedEnumEfCoreAttribute.g.verified.cs | Verify snapshot: injected attribute source (ByName, string TValue). |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.ByName_StringValueType#MyApp.Domain.Color.g.verified.cs | Verify snapshot: core OptimizedEnum generation for Color (ByName case). |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.ByName_StringValueType#MyApp.Domain.Color.EFCore.g.verified.cs | Verify snapshot: EFCore converters/extensions for Color (ByName). |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.NestedType#OptimizedEnumEfCoreConventions.g.verified.cs | Verify snapshot: conventions output for nested OptimizedEnum type. |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.NestedType#OptimizedEnumEfCoreAttribute.g.verified.cs | Verify snapshot: injected attribute source for nested-type scenario. |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.NestedType#MyApp.Domain.Outer.Status.g.verified.cs | Verify snapshot: core OptimizedEnum generation for nested Outer.Status. |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.NestedType#MyApp.Domain.Outer.Status.EFCore.g.verified.cs | Verify snapshot: EFCore converters/extensions for nested Outer.Status. |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.IntermediateAbstractBase#OptimizedEnumEfCoreConventions.g.verified.cs | Verify snapshot: conventions output for intermediate-base scenario. |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.IntermediateAbstractBase#OptimizedEnumEfCoreAttribute.g.verified.cs | Verify snapshot: injected attribute source for intermediate-base scenario. |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.IntermediateAbstractBase#MyApp.Domain.OrderStatus.g.verified.cs | Verify snapshot: core OptimizedEnum generation via abstract base. |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.IntermediateAbstractBase#MyApp.Domain.OrderStatus.EFCore.g.verified.cs | Verify snapshot: EFCore converters/extensions via abstract base. |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.Error_NotOptimizedEnum#OptimizedEnumEfCoreConventions.g.verified.cs | Verify snapshot: conventions output for OE3001 failure case. |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.Error_NotOptimizedEnum#OptimizedEnumEfCoreAttribute.g.verified.cs | Verify snapshot: attribute source for OE3001 failure case. |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.Error_NotOptimizedEnum.verified.txt | Verify snapshot: OE3001 diagnostic output. |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.Error_NotPartial#OptimizedEnumEfCoreConventions.g.verified.cs | Verify snapshot: conventions output for OE3002 failure case. |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.Error_NotPartial#OptimizedEnumEfCoreAttribute.g.verified.cs | Verify snapshot: attribute source for OE3002 failure case. |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.Error_NotPartial.verified.txt | Verify snapshot: OE3002 (and OE0001) diagnostic output. |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.Error_UnknownStorageType#OptimizedEnumEfCoreConventions.g.verified.cs | Verify snapshot: conventions output for OE3003 failure case. |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.Error_UnknownStorageType#OptimizedEnumEfCoreAttribute.g.verified.cs | Verify snapshot: attribute source for OE3003 failure case. |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.Error_UnknownStorageType#MyApp.Domain.OrderStatus.g.verified.cs | Verify snapshot: core OptimizedEnum output during OE3003 case. |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.Error_UnknownStorageType.verified.txt | Verify snapshot: OE3003 diagnostic output. |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.Error_AbstractClass#OptimizedEnumEfCoreConventions.g.verified.cs | Verify snapshot: conventions output for OE3004 failure case. |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.Error_AbstractClass#OptimizedEnumEfCoreAttribute.g.verified.cs | Verify snapshot: attribute source for OE3004 failure case. |
| tests/LayeredCraft.OptimizedEnums.EFCore.Tests/Snapshots/GeneratorVerifyTests.Error_AbstractClass.verified.txt | Verify snapshot: OE3004 diagnostic output. |
| src/LayeredCraft.OptimizedEnums.EFCore.Generator/LayeredCraft.OptimizedEnums.EFCore.Generator.csproj | New generator package project + packing into analyzers. |
| src/LayeredCraft.OptimizedEnums.EFCore.Generator/OptimizedEnumEfCoreGenerator.cs | Incremental generator wiring: attribute injection + outputs. |
| src/LayeredCraft.OptimizedEnums.EFCore.Generator/TrackingNames.cs | Incremental generator tracking names for diagnostics/perf tooling. |
| src/LayeredCraft.OptimizedEnums.EFCore.Generator/AttributeSource.cs | Post-init injected attribute + storage enum source text. |
| src/LayeredCraft.OptimizedEnums.EFCore.Generator/Providers/EfCoreSyntaxProvider.cs | Attribute discovery + model building + diagnostics (OE3001-4). |
| src/LayeredCraft.OptimizedEnums.EFCore.Generator/Models/EfCoreInfo.cs | Immutable model for EFCore generation inputs. |
| src/LayeredCraft.OptimizedEnums.EFCore.Generator/Models/EquatableArray.cs | Utility for stable incremental equality. |
| src/LayeredCraft.OptimizedEnums.EFCore.Generator/Models/LocationInfo.cs | Location capture/translation utilities for diagnostics. |
| src/LayeredCraft.OptimizedEnums.EFCore.Generator/Diagnostics/DiagnosticInfo.cs | Diagnostic wrapper + reporting helpers. |
| src/LayeredCraft.OptimizedEnums.EFCore.Generator/Diagnostics/DiagnosticDescriptors.cs | EFCore generator diagnostics definitions (OE3001-4, OE9003). |
| src/LayeredCraft.OptimizedEnums.EFCore.Generator/Emitters/EfCoreEmitter.cs | Renders per-enum and conventions outputs via Scriban. |
| src/LayeredCraft.OptimizedEnums.EFCore.Generator/Emitters/TemplateHelper.cs | Embedded Scriban template loading + caching. |
| src/LayeredCraft.OptimizedEnums.EFCore.Generator/Templates/OptimizedEnumEfCore.scriban | Template for per-enum converters + extension methods. |
| src/LayeredCraft.OptimizedEnums.EFCore.Generator/Templates/OptimizedEnumEfCoreConventions.scriban | Template for shared ConfigureOptimizedEnums() convention hook. |
| src/LayeredCraft.OptimizedEnums.EFCore.Generator/AnalyzerReleases.Unshipped.md | Roslyn analyzer release tracking for new diagnostics. |
| src/LayeredCraft.OptimizedEnums.EFCore.Generator/AnalyzerReleases.Shipped.md | Placeholder shipped analyzer tracking file. |
| LayeredCraft.OptimizedEnums.slnx | Adds EFCore generator + EFCore tests projects to solution. |
| docs/specs/efcore-package-spec.md | Full technical specification for the EFCore package. |
| Directory.Packages.props | Adds central versions for EF Core + Npgsql + Testcontainers. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
src/LayeredCraft.OptimizedEnums.EFCore.Generator/Templates/OptimizedEnumEfCore.scriban
Show resolved
Hide resolved
src/LayeredCraft.OptimizedEnums.EFCore.Generator/Templates/OptimizedEnumEfCore.scriban
Show resolved
Hide resolved
...ayeredCraft.OptimizedEnums.EFCore.Generator/Templates/OptimizedEnumEfCoreConventions.scriban
Show resolved
Hide resolved
- Change extension class from `public` to `internal` to avoid inconsistent-accessibility errors when the annotated enum is internal - Add `_` separator in BuildConverterPrefix to prevent collisions between nested-type paths that would otherwise concatenate ambiguously (e.g. A.BC.Status and AB.C.Status both produced ABCStatus before) - Update spec: document why nullable PropertyBuilder<T?> overloads are omitted (CS0111 — reference-type generics make T and T? the same instantiation) and why no ValueComparer is generated (EF Core's default comparer is sufficient for immutable singletons; standalone HasComparer API does not exist) - Update verified snapshots to match new output Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add docs/usage/ef-core.md covering installation, storage strategies, all three registration approaches, nullable properties, PK/FK/index usage, string-valued enums, abstract bases, nested types, AOT safety, generated code examples, and v1 limitations - Add OE3001–OE3004 and OE9003 EFCore diagnostics section to docs/advanced/diagnostics.md - Add EFCore install instructions to docs/getting-started/installation.md - Update README: add EFCore section with quick-start example; replace "coming soon" with NuGet/download badges - Add "Entity Framework Core" to zensical.toml nav under Usage - Add docs/usage/ef-core.md and docs/specs/ folder to .slnx Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Delete the specs folder and its contents, add docs/specs/ to .gitignore, and remove the /docs/specs/ folder entry from the solution file. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
@codex review |
|
@claude review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c4dc8a9f3f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
src/LayeredCraft.OptimizedEnums.EFCore.Generator/Templates/OptimizedEnumEfCore.scriban
Show resolved
Hide resolved
j-d-ha
left a comment
There was a problem hiding this comment.
Looks Great! One small request around docs.
…o 1.3.0 Extension methods must be in top-level static classes (CS1109), and converters emitted at namespace scope cannot reference free type parameters from a generic containing type. Emit OE3004 with a clear message when the annotated enum's containing type chain includes a generic type. Also captures ContainingTypeDeclarations in the model (full partial-class declarations for each containing type) for future use if the preamble/suffix pattern is needed for other generated members. Bump VersionPrefix from 1.2.1 to 1.3.0 for the new EFCore package release. Update diagnostics.md and ef-core.md to document the generic container limitation under OE3004. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove Package Manager (PowerShell) tab from installation section - Expand ConfigureConventions snippet to show full DbContext context, making it clear where the method override belongs Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
j-d-ha
left a comment
There was a problem hiding this comment.
🚀 Looks great! Love this and will be using it.
Summary
LayeredCraft.OptimizedEnums.EFCore— a new source generator package that emits zero-reflection, AOT-safe EF Core value converters forOptimizedEnumtypessealed partialOptimizedEnum class with[OptimizedEnumEfCore(ByValue|ByName)]to get{Prefix}ValueConverter,{Prefix}NameConverter, enum-specificHasXxxConversionByValue/ByName()extension methods, and a sharedConfigureOptimizedEnums()convention hook — all generated at compile timeTest plan
🤖 Generated with Claude Code