-
Notifications
You must be signed in to change notification settings - Fork 0
Add Composer pattern source generator #103
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
Co-authored-by: JerrettDavis <2610199+JerrettDavis@users.noreply.github.com>
Co-authored-by: JerrettDavis <2610199+JerrettDavis@users.noreply.github.com>
…nc support 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>
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
Test Results292 tests 292 ✅ 1m 19s ⏱️ Results for commit 2c64338. ♻️ 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 #103 +/- ##
==========================================
+ Coverage 82.67% 87.37% +4.70%
==========================================
Files 166 169 +3
Lines 15767 16150 +383
Branches 2199 2273 +74
==========================================
+ Hits 13035 14111 +1076
+ Misses 2155 2039 -116
+ Partials 577 0 -577
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 adds a comprehensive source generator for the Composer pattern, enabling deterministic composition of ordered pipeline components (middleware, handlers, policies) into executable pipelines. The generator supports both synchronous and asynchronous execution with compile-time validation.
Changes:
- Adds
ComposerGeneratorwith incremental generation usingForAttributeWithMetadataNamefor efficient compilation - Implements 9 diagnostics (PKCOM001-009) covering partial validation, ordering, signatures, and async mismatches
- Provides attributes for pipeline configuration:
[Composer],[ComposeStep],[ComposeTerminal],[ComposeIgnore] - Generates both sync (
Invoke) and async (InvokeAsync) methods withValueTask<T>support - Supports class, struct, record class, and record struct as pipeline hosts
- Handles struct pipelines specially to avoid lambda capture issues
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 13 comments.
Show a summary per file
| File | Description |
|---|---|
| src/PatternKit.Generators/ComposerGenerator.cs | Main generator implementation with validation, diagnostics, and code generation for sync/async pipelines |
| src/PatternKit.Generators.Abstractions/Composer/ComposerAttribute.cs | Pipeline host attribute with configuration options for method names, async generation, and wrap order |
| src/PatternKit.Generators.Abstractions/Composer/ComposeStepAttribute.cs | Step marking attribute with order and optional name properties |
| src/PatternKit.Generators.Abstractions/Composer/ComposeTerminalAttribute.cs | Terminal step marker requiring exactly one per pipeline |
| src/PatternKit.Generators.Abstractions/Composer/ComposeIgnoreAttribute.cs | Exclusion marker for methods that should not be composed |
| test/PatternKit.Generators.Tests/ComposerGeneratorTests.cs | Comprehensive test suite covering basic scenarios, diagnostics, type variants, and configuration options |
| test/PatternKit.Generators.Tests/packages.lock.json | Updated lock file with transitive dependency System.Reflection.Metadata from test infrastructure |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@copilot apply changes based on the comments in this thread |
…generation logic 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 7 out of 7 changed files in this pull request and generated 2 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 |
Co-authored-by: JerrettDavis <2610199+JerrettDavis@users.noreply.github.com>
Code Coverage |
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 7 out of 7 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.
Minor Cleanup from PR Review
Changes
Removed unused import (line 5)
System.Collections.Immutableimport that was not used anywhere in the fileFixed misleading test name (line 775)
TrulyMixedSyncAndAsync_GeneratesBothtoTrulyMixedSyncAndAsync_GeneratesAsyncOnlynameof()reference to match new test nameTest Results
Original prompt
This section details on the original issue you should resolve
<issue_title>Generator: Create Composer Pattern</issue_title>
<issue_description># Generator: Create Composer Pattern
Summary
Add a source generator that produces a boilerplate-free Composer pattern implementation: a deterministic way to compose ordered components (steps, middleware, handlers, policies) into a single executable pipeline.
This is not a classic GoF pattern, but it’s an extremely common architectural pattern in modern .NET systems (middleware pipelines, validation pipelines, retry stacks, message processing chains, etc.). The goal is to provide a canonical, strongly-typed composition primitive that other PatternKit generators can reuse.
The generator lives in
PatternKit.Generatorsand emits self-contained C# with no runtime PatternKit dependency.Primary goals:
Compose) and an executor (Invoke).ValueTask).Motivation / Problem
Teams repeatedly re-implement composition:
next-style)Hand-rolled composition leads to:
A generator can:
Supported Targets (must-have)
The generator must support:
partial classpartial structpartial record classpartial record structThe annotated type represents a pipeline host that declares:
Proposed User Experience
A) Request → Response middleware composition
Generated (representative shape):
B) Void pipeline (actions)
V1 can restrict to pipelines with an explicit input type; void pipelines can be v2 if you prefer.
Attributes / Surface Area
Namespace:
PatternKit.Generators.ComposerCore
[Composer]on the pipeline hoststring InvokeMethodName = "Invoke"string InvokeAsyncMethodName = "InvokeAsync"bool GenerateAsync(default: inferred)bool ForceAsync(default: false)ComposerWrapOrder WrapOrder(default: OuterFirst)[ComposeStep]on component methodsint Orderstring? Name[ComposeTerminal]on terminal methodEnums:
ComposerWrapOrder:OuterFirst|InnerFirstOptional:
[ComposeIgnore](exclude method)Semantics (must-have)
Ordering
Order.Wrapping
next.Order=0is outermost (documented).Signatures
Pipeline step signature must match one of:
TOut Step(in TIn input, Func<TIn, TOut> next)ValueTask<TOut> StepAsync(TIn input, Func<TIn, ValueTask<TOut>> next, CancellationToken ct = default)Terminal signature must match:
TOut Terminal(in TIn input)ValueTask<TOut> TerminalAsync(TIn input, CancellationToken ct = default)Rules:
ForceAsync=true.Allocation expectations
Invokeshould not allocate per call in sync mode.Diagnostics (must-have)
Stable IDs, actionable:
PKCOM001Type marked[Composer]must bepartial.PKCOM002No[ComposeStep]methods f...💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.