Add State Pattern source generator with deterministic transitions, comprehensive documentation and examples#117
Conversation
Co-authored-by: JerrettDavis <2610199+JerrettDavis@users.noreply.github.com>
Co-authored-by: JerrettDavis <2610199+JerrettDavis@users.noreply.github.com>
… Examples project) Co-authored-by: JerrettDavis <2610199+JerrettDavis@users.noreply.github.com>
Co-authored-by: JerrettDavis <2610199+JerrettDavis@users.noreply.github.com>
Co-authored-by: JerrettDavis <2610199+JerrettDavis@users.noreply.github.com>
Co-authored-by: JerrettDavis <2610199+JerrettDavis@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Adds a new deterministic State Pattern source generator to PatternKit, enabling enum-based finite state machines via attributes with generated State, CanFire, Fire, and optional FireAsync APIs.
Changes:
- Introduces
StateMachineGeneratorincremental generator that collects transitions/guards/entry-exit hooks and emits generated state machine code. - Adds State generator attribute surface area (
StateMachine,StateTransition,StateGuard,StateEntry,StateExit) plus policy enums and diagnostics registration. - Adds comprehensive unit tests and an examples demo for the new generator.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| test/PatternKit.Generators.Tests/StateMachineGeneratorTests.cs | Adds coverage for state machine generation across target types, hooks/guards, and core diagnostics. |
| src/PatternKit.Generators/StateMachineGenerator.cs | Implements the new State pattern source generator, diagnostics, validation, and code emission. |
| src/PatternKit.Generators/AnalyzerReleases.Unshipped.md | Registers new PKST001–PKST008 diagnostics for the State generator. |
| src/PatternKit.Generators.Abstractions/State/StateTransitionAttribute.cs | Adds transition attribute to declare (From, Trigger) -> To edges. |
| src/PatternKit.Generators.Abstractions/State/StateMachineAttribute.cs | Adds host attribute and policy configuration enums for generation. |
| src/PatternKit.Generators.Abstractions/State/StateGuardAttribute.cs | Adds guard attribute for conditional transitions. |
| src/PatternKit.Generators.Abstractions/State/StateExitAttribute.cs | Adds state exit hook attribute. |
| src/PatternKit.Generators.Abstractions/State/StateEntryAttribute.cs | Adds state entry hook attribute. |
| src/PatternKit.Examples/Generators/State/OrderFlowDemo.cs | Adds an end-to-end demo of the generated API and lifecycle ordering. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@copilot apply changes based on the comments in this thread |
|
@copilot this PR should also include the real-world demos and comprehensive users-docs as present for our other generators. |
… handling, add tests Co-authored-by: JerrettDavis <2610199+JerrettDavis@users.noreply.github.com>
…ne generator Co-authored-by: JerrettDavis <2610199+JerrettDavis@users.noreply.github.com>
Added comprehensive documentation and examples in commit abe2239: Documentation:
Examples:
All documentation and examples are now at the same level as other PatternKit generators. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 12 out of 12 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.
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
Test Results398 tests 398 ✅ 2m 49s ⏱️ Results for commit abe2239. |
Code Coverage |
🔍 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 #117 +/- ##
==========================================
+ Coverage 82.88% 87.10% +4.21%
==========================================
Files 185 192 +7
Lines 17793 18532 +739
Branches 2536 2664 +128
==========================================
+ Hits 14748 16142 +1394
- Misses 2371 2390 +19
+ Partials 674 0 -674
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:
|
Implements a complete source generator for the State pattern as a deterministic finite state machine. The generator produces self-contained code with no runtime dependencies, using enum-based states/triggers and ValueTask for async operations.
Architecture
Attributes (
PatternKit.Generators.Abstractions/State)[StateMachine(stateType, triggerType)]- Marks host type, configures method names and policies[StateTransition(From, Trigger, To)]- Defines state transitions on methods[StateGuard(From, Trigger)]- Guards transitions with bool/ValueTask conditions[StateEntry(state)]/[StateExit(state)]- Lifecycle hooksGenerator (
PatternKit.Generators/StateMachineGenerator.cs)Usage
Implementation Notes
Review Feedback Addressed
All PR review feedback has been implemented:
StringComparer.Ordinalto transition ordering for culture-independent deterministic outputGenerateAsync = falseis explicitly set and reports PKST008 diagnosticLocation.Noneto actual method source locationsGetAwaiter().GetResult()GetEnumValueNameto handle all enum underlying typesCancellationToken.NoneDocumentation and Examples
Comprehensive Documentation (
docs/generators/state-machine.md- 25KB+)Examples README (
src/PatternKit.Examples/Generators/State/README.md- 13KB+)Expanded Real-World Examples (
OrderFlowDemo.cs)Run()- Happy path order processingCancellationDemo()- Order cancellation from multiple statesGuardFailureDemo()- Business rule validationAsyncCancellationDemo()- Timeout handling with CancellationTokenStateBasedLogicDemo()- Dynamic action discovery based on stateGetStateDescription(),GetAvailableTriggers())Testing
Added 26 comprehensive tests covering:
Full test suite: 1,957 tests passing with no regressions.
Original prompt
This section details on the original issue you should resolve
<issue_title>Generator: Create State Pattern</issue_title>
<issue_description>## Summary
Add a source generator that produces a complete implementation of the State pattern as a deterministic state machine with:
ValueTask)The generator lives in
PatternKit.Generatorsand emits self-contained C# with no runtime PatternKit dependency.Motivation / Problem
State pattern implementations tend to devolve into:
We want a generator that produces:
Supported Targets (must-have)
The generator must support:
partial classpartial structpartial record classpartial record structThe annotated type represents the state machine host, exposing
Fire(...)/FireAsync(...)and aStateproperty.Proposed User Experience
A) Enum-based states/triggers
Generated (representative shape):
B) Type-based states (optional v2)
V1 scope can restrict states/triggers to enums for simplicity and performance.
Attributes / Surface Area
Namespace:
PatternKit.Generators.StateCore
[StateMachine(Type stateType, Type triggerType)]on the hoststring FireMethodName = "Fire"string FireAsyncMethodName = "FireAsync"string CanFireMethodName = "CanFire"bool GenerateAsync(default: inferred)bool ForceAsync(default: false)StateMachineInvalidTriggerPolicy InvalidTrigger(default: Throw)StateMachineGuardFailurePolicy GuardFailure(default: Throw)[StateTransition]on methods that execute on a transitionTState FromTTrigger TriggerTState To[StateGuard]on methods that determine whether a transition is allowedFrom,Trigger[StateEntry]/[StateExit]on hook methodsTState StatePolicies:
InvalidTriggerPolicy: Throw | Ignore | ReturnFalse (if using TryFire)GuardFailurePolicy: Throw | Ignore | ReturnFalseSemantics (must-have)
Deterministic transition resolution
(FromState, Trigger).Guard evaluation
If a guard exists for
(FromState, Trigger):GuardFailurePolicyExecution order
When a transition occurs:
FromState(if any)[StateTransition]) (if any)State = ToStateToState(if any)This order is deterministic and must be documented.
Async
ValueTask), generateFireAsync.ValueTaskacross generated signatures.Concurrency
V1 scope:
Lockingmode can be added later. If we include in v1, it must be explicit and tested.Diagnostics (must-have)
Stable IDs, actionable:
PKST001Type marked[StateMachine]must bepartial.PKST002State type must be anenum(v1).PKST003Trigger type must be anenum(v1).PKST004Duplicate transition detected for (From, Trigger).PKST005Transition method signature invalid.PKST006Guard method signature invalid (must return bool / ValueTask if async guards supported).PKST007Entry/Exit hook signature invalid.PKST008Async method detected but async generation disabled; enableGenerateAsync/ForceAsync.#...
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.