-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Labels
enhancementNew feature or requestNew feature or request
Description
Summary
Add a source generator that produces a complete implementation of the Template Method pattern for consumer-defined workflows.
The generator lives in PatternKit.Generators and emits self-contained, readable C# with no runtime PatternKit dependency.
Primary goals:
- Define a canonical sequence of steps (the “template”).
- Allow consumers to override hooks and optional steps safely.
- Support sync + async flows (favoring
ValueTask). - Provide deterministic ordering, diagnostics, and testability.
Motivation / Problem
Template Method is commonly re-implemented as:
- base classes with virtual methods (inheritance tax)
- ad-hoc pipelines with no clear contract for overrides
- scattered hooks with inconsistent error handling
We want a declarative, boilerplate-free way to define a workflow that:
- makes step order explicit
- makes override points explicit
- is friendly to records/immutability
- is reflection-free and generator-deterministic
Supported Targets (must-have)
The generator must support:
partial classpartial structpartial record classpartial record struct
The annotated type represents the workflow host (the place consumers call Execute/ExecuteAsync).
Proposed User Experience
Minimal template with required steps
[Template]
public partial class ImportWorkflow
{
[TemplateStep(Order = 0)]
private void Validate(ImportContext ctx);
[TemplateStep(Order = 1)]
private void Transform(ImportContext ctx);
[TemplateStep(Order = 2)]
private void Persist(ImportContext ctx);
}Generated (representative shape):
Execute(ImportContext ctx)invokes steps in deterministic order.ExecuteAsync(ImportContext ctx, CancellationToken ct = default)emitted when async steps/hooks exist orForceAsync=true.
Hooks + error handling
[Template(GenerateAsync = true)]
public partial class ImportWorkflow
{
[TemplateHook(HookPoint.BeforeAll)]
private void OnStart(ImportContext ctx);
[TemplateStep(0)]
private ValueTask ValidateAsync(ImportContext ctx, CancellationToken ct);
[TemplateStep(1)]
private void Transform(ImportContext ctx);
[TemplateHook(HookPoint.OnError)]
private void OnError(ImportContext ctx, Exception ex);
[TemplateHook(HookPoint.AfterAll)]
private void OnComplete(ImportContext ctx);
}Attributes / Surface Area
Namespace: PatternKit.Generators.Template
Core attributes
[Template]on the workflow host[TemplateStep]on methods that form the required step sequence[TemplateHook]on methods that plug into hook points
Suggested shapes:
TemplateAttribute
string ExecuteMethodName = "Execute"string ExecuteAsyncMethodName = "ExecuteAsync"bool GenerateAsync(default: inferred)bool ForceAsync(default: false)TemplateErrorPolicy ErrorPolicy(default:Rethrow)
TemplateStepAttribute
int Order(required in v1)bool Optional(default: false)string? Name(optional; for diagnostics)
TemplateHookAttribute
HookPoint HookPoint(BeforeAll, AfterAll, OnError)int? StepOrder(reserved for v2: BeforeStep/AfterStep targeting)
Step Semantics
- Steps execute in ascending
Order. - Duplicate orders are errors.
- Steps are invoked exactly once unless marked optional and suppressed (v2). In v1,
Optionalonly affects error-policy eligibility.
Async rules
- If any step/hook returns
ValueTaskor acceptsCancellationToken, generator emits async path. - Sync
Executecan exist alongside asyncExecuteAsync. - Generated async APIs use
ValueTask.
Error rules
- Default: throw after invoking
OnError(if present). - If
ErrorPolicy = HandleAndContinue, only allowed when all remaining steps are optional. Otherwise emit diagnostic.
Diagnostics (must-have)
Stable IDs, actionable:
PKTMP001Type marked[Template]must bepartial.PKTMP002No[TemplateStep]methods found.PKTMP003Duplicate step order detected.PKTMP004Step method signature invalid.PKTMP005Hook method signature invalid.PKTMP006Mixed sync/async signatures not supported (explain required shapes).PKTMP007CancellationToken required for async step but missing.PKTMP008HandleAndContinuenot allowed when non-optional steps remain.
Generated Code Layout
TypeName.Template.g.cs
Deterministic ordering:
- steps ordered by
Order, then by fully-qualified method name for tie-breaking in diagnostics.
Testing Expectations
- Deterministic ordering with multiple steps.
- Hooks fire at correct points.
- Error behavior:
OnErrorinvoked; default rethrow policy enforced. - Async path uses
ValueTaskand respects cancellation. - Diagnostics: duplicate order, invalid signatures.
Acceptance Criteria
-
[Template]works for class/struct/record class/record struct. - Generated
Executeruns steps deterministically. - Generated
ExecuteAsyncusesValueTaskand supports cancellation when needed. - Hooks supported: BeforeAll, AfterAll, OnError (v1).
- Diagnostics cover ordering + signature correctness
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request