-
Notifications
You must be signed in to change notification settings - Fork 0
Add Memento pattern source generator for classes, structs, and records #88
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- Created MementoAttribute with configuration options - Implemented MementoGenerator for class/struct/record class/record struct - Generated immutable memento structs with Capture and RestoreNew methods - Generated optional caretaker classes for undo/redo history - Added diagnostic support (PKMEM001-PKMEM006) - All 13 generator tests passing Co-authored-by: JerrettDavis <2610199+JerrettDavis@users.noreply.github.com>
- Created EditorStateDemo showing text editor with undo/redo - Created GameStateDemo showing game state save/load - Added comprehensive README with usage examples - Moved MementoAttribute to Abstractions project for accessibility - Fixed generator to skip computed/read-only properties - All 13 generator tests passing Co-authored-by: JerrettDavis <2610199+JerrettDavis@users.noreply.github.com>
- Added null checks for FirstOrDefault in test assertions - Fixed potential NullReferenceException in generated source access - All 13 Memento tests passing Co-authored-by: JerrettDavis <2610199+JerrettDavis@users.noreply.github.com>
Dependency Reviewβ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
Test Results123 testsβββ123 β
ββ19s β±οΈ Results for commit 8641aca. β»οΈ This comment has been updated with latest results. |
π 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. |
Codecov Reportβ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #88 +/- ##
==========================================
+ Coverage 86.81% 89.77% +2.95%
==========================================
Files 139 143 +4
Lines 11295 11890 +595
Branches 1548 1615 +67
==========================================
+ Hits 9806 10674 +868
- Misses 1101 1216 +115
+ Partials 388 0 -388
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:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR implements a comprehensive source generator for the Memento pattern, enabling compile-time generation of immutable snapshot structures and optional undo/redo caretakers for classes, structs, record classes, and record structs.
Changes:
- Adds MementoGenerator with support for four type kinds (class, struct, record class, record struct) with customizable member selection, capture strategies, and six diagnostic codes (PKMEM001-006)
- Generates immutable memento structs with versioning, Capture methods, and RestoreNew/Restore methods based on type mutability
- Generates optional caretaker classes with configurable capacity, FIFO eviction, duplicate suppression, and standard undo/redo semantics
- Provides EditorStateDemo and GameStateDemo showcasing text editor and game state scenarios with generated mementos
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| src/PatternKit.Generators/MementoGenerator.cs | Core source generator implementing memento struct and caretaker generation with member analysis and restore logic |
| src/PatternKit.Generators.Abstractions/MementoAttribute.cs | Attribute definitions for [Memento], [MementoIgnore], [MementoInclude], and [MementoStrategy] with enums for inclusion mode and capture strategies |
| src/PatternKit.Generators/AnalyzerReleases.Unshipped.md | Adds six diagnostic IDs (PKMEM001-006) for memento-specific errors and warnings |
| test/PatternKit.Generators.Tests/MementoGeneratorTests.cs | Comprehensive test suite covering basic generation, caretaker, member selection, diagnostics, and capacity handling |
| src/PatternKit.Examples/Generators/Memento/README.md | Detailed documentation with usage examples, configuration options, diagnostics reference, and best practices |
| src/PatternKit.Examples/Generators/Memento/EditorStateDemo.cs | Text editor demonstration using record class with undo/redo functionality |
| src/PatternKit.Examples/Generators/Memento/GameStateDemo.cs | Game state demonstration using mutable class with save/load and checkpoint functionality |
π‘ Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@copilot apply changes based on the comments in this thread |
- Fixed namespace mismatch in demo files (MementoDemo -> Memento) - Updated GameStateDemo to use generated memento methods instead of manual copying - Improved computed property detection to exclude init-only properties on non-record types - Enhanced positional constructor detection with parameter name and type matching - Added verification for settable members in RestoreNew for non-record types - Refactored foreach loops to use explicit .Where() filtering - Updated test assertions to use regex for flexible matching All 13 Memento generator tests passing. Co-authored-by: JerrettDavis <2610199+JerrettDavis@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.
π‘ Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@copilot apply changes based on the comments in this thread Ignore the note about the gitversion bump. That was required, but we can make a comment about it. Fix the others. |
- Removed unused PatternKit.Creational.Builder import from MementoGeneratorTests - Simplified GameStateDemo undo/redo methods to avoid inefficient intermediate memento - Now directly copies state from history instead of creating unnecessary memento instance All 13 Memento generator tests passing. Co-authored-by: JerrettDavis <2610199+JerrettDavis@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.
π‘ Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@copilot apply changes based on the comments in this thread |
- Removed unused System.Collections.Immutable import - Fixed global namespace handling to use empty string instead of "GlobalNamespace" - Added length check in ToCamelCase to prevent exception with single-char names - Conditionally emit namespace declaration only when not in global namespace All 13 Memento generator tests passing. Co-authored-by: JerrettDavis <2610199+JerrettDavis@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.
π‘ Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Code Coverage |
Memento Pattern Source Generator - Code Quality Improvements β
Summary of Latest Changes
Addressed 3 code quality issues from the latest review, improving correctness and robustness.
π Changes Made
1. Removed Unused Import (Comment #2711024069)
System.Collections.Immutableimport fromMementoGenerator.cs2. Fixed Global Namespace Handling (Comment #2711024075)
"GlobalNamespace"string for types in global namespacenamespace GlobalNamespace;creating a namespace instead of using globalstring.Emptyfor global namespace types3. Fixed Single-Character Name Handling (Comment #2711024084)
name.Substring(1)would throwArgumentOutOfRangeExceptionfor single-character names|| name.Length == 1to early returnβ Validation
π― Impact
These changes improve:
Previous Changes Summary
Previously addressed:
Original prompt
This section details on the original issue you should resolve
<issue_title>Generator: Create Memento Pattern (supports class/struct/record + optional undo/redo caretaker)</issue_title>
<issue_description>## Summary
Add a source generator that produces a complete implementation of the Memento pattern for consumer types β including classes, structs, record classes, and record structs β focused on:
Motivation / Problem
Memento implementations are repetitive and correctness-sensitive:
This is ideal for source generation: emit correct, optimized code once, consistently.
Supported Originator Kinds (must-have)
The generator must support:
classstructrecord classrecord structEach kind has different restore semantics:
Mutable originators (class/struct with settable members)
Immutable originators (records with
initor positional parameters)restore should support returning a new instance:
RestoreNew(...)orApply(...)optionally support
with-expression restore when feasible:with { ... }for the included membersWe should not force mutation on records that are designed to be immutable.
Proposed User Experience
Minimal: snapshot only
Generated (shape):
Snapshot + caretaker (undo/redo)
Generated:
Notes
Member Selection
Support both modes:
Include-all (default, configurable)
Include-explicit
[MementoInclude]Attributes:
[Memento][MementoIgnore][MementoInclude]Capture Strategies for Mutable References (footgun prevention)
Default strategy should be explicit and safe:
stringtreated as safe immutableByReferencewith a warning unless configured otherwisePer-member strategy attribute:
Strategies:
ByReferenceClone(requires a known mechanism)DeepCopy(only when generator can safely emit it)Serialize(opt-in, future)Custom(partial hook)Restore Semantics (by originator type)
For class / struct (mutable)
Generate both:
void Restore(TOriginator originator)(in-place)TOriginator RestoreNew()(convenience)For record class / record struct
Generate:
TOriginator RestoreNew()(always)Apply(TOriginator originator)only if the record has writable members (rare / discouraged)Additionally:
if feasible, prefer
with-expression:originator with { Prop = value, ... }otherwise, use the best available constructor/positional parameters:
The generator must emit diagnostics if it cannot safely construct a new record instance.
Caretaker Generation (Undo/Redo)
Caretaker should be optional and support dete...
β¨ Let Copilot coding agent set things up for you β coding agent works faster and does higher quality work when set up for your repo.