Marten#4486: Dispatcher-coverage regression guard in Marten.AotSmoke#4487
Merged
Merged
Conversation
Extends Marten.AotSmoke from the AOT-clean-surface smoke into the dispatcher-coverage sentinel #4486 carves out of #4471. Adds three new fixture projection shapes alongside the existing SmokeProjection so AotSmoke now exercises every canonical SG emission pattern: Pattern A — projection subclass; SG emits a partial declaration merged into the user's class: SmokeProjection — explicit Evolve override (deliberate bypass) ApplyProjection (new) — conventional Apply method Pattern B — self-aggregating aggregate; SG emits a sibling XEvolver class + [assembly: GeneratedEvolver(typeof(X), typeof(XEvolver))] registration. Aggregate type does NOT need to be partial: SelfAggregatingApply (new) — conventional Apply on the aggregate SelfAggregatingEvolve(new) — explicit Evolve on the aggregate ProjectionOptions.SingleStreamProjection<T>() calls AssembleAndAssertValidity() at registration time; post-#276 that throws InvalidProjectionException whenever the SG didn't emit for a shape, so any regression in the SG's discovery rules trips the exit code here. Sanity-checked: stripping `partial` from ApplyProjection makes `dotnet run` exit 134 with the expected "No source-generated dispatcher found for ApplyProjection" message. The build is NOT the sentinel — the SG silently skips emission when its preconditions (e.g. partial on Pattern A) aren't met, so no CS0260 fires. The runtime fail-fast catches it. Marten.AotSmoke.csproj needed an Analyzer-only PackageReference to JasperFx.Events.SourceGenerator. Marten.csproj sets PrivateAssets="all" on the SG so the analyzer doesn't flow transitively — same wiring CoreTests / DocumentDbTests / MultiTenancyTests / ValueTypeTests use for their own SG-emit-expected types. AOT contract preserved — IsAotCompatible=true, TrimMode=full, and the promoted IL warnings all keep holding. Verified: build is clean on net9.0 and net10.0; `dotnet run` exits 0 with the expected "Marten AOT smoke OK" line on both frameworks. Closes #4486. Closes #4471. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #4486. Closes #4471 (companion to PR #4485 which landed the static inventory).
Extends
Marten.AotSmokefrom "AOT-clean-surface smoke" into the dispatcher-coverage sentinel #4486 carves out of #4471. The static inventory ataudit/projections-inventory.md(#4485) documents the existing state; this PR is the regression guard that catches a future SG discovery-rule break before CI's downstream tests even start.What gets exercised
Three new fixture types alongside the existing
SmokeProjection, covering every canonical SG emission pattern ×Apply-vs-Evolvemethod convention:SmokeProjection(existing)EvolveoverrideApplyProjection(new)ApplyEvolve(...)SelfAggregatingApply(new)ApplySelfAggregatingApplyEvolverclass +[assembly: GeneratedEvolver(...)]SelfAggregatingEvolve(new)Evolveon aggregateSelfAggregatingEvolveEvolverclass +[assembly: GeneratedEvolver(...)]How the sentinel works
ProjectionOptions.SingleStreamProjection<T>()callssource.AssembleAndAssertValidity()at registration time. Post-#276 that throwsInvalidProjectionExceptionwhenever the SG didn't emit a dispatcher for the shape. So if a future SG change drops support for one of these canonical patterns,dotnet run --project Marten.AotSmokeexits non-zero and CI catches it.The build is not the sentinel. Sanity-checked locally: stripping
partialfromApplyProjectionlets the build pass (the SG silently skips emission when its preconditions don't hold — no CS0260 fires) but the runtime then throws atProjections.Add<ApplyProjection>(...)with the expected"No source-generated dispatcher found for ApplyProjection"message and the process exits 134.Csproj change
Marten.AotSmoke.csprojneeded an Analyzer-onlyPackageReferencetoJasperFx.Events.SourceGenerator.Marten.csprojsetsPrivateAssets="all"on the SG so the analyzer doesn't flow transitively — same wiringCoreTests/DocumentDbTests/MultiTenancyTests/ValueTypeTestsuse for their own SG-emit-expected types.AOT contract preserved
IsAotCompatible=true,TrimMode=full, and the promoted-to-error IL warning list (IL2026;IL2046;IL2055;IL2065;IL2067;IL2070;IL2072;IL2075;IL2090;IL2091;IL2111;IL3050;IL3051) all keep holding with the new fixtures and registrations.Test plan
dotnet run --project Marten.AotSmoke -f net9.0→ exit 0, expected "Marten AOT smoke OK" linedotnet run --project Marten.AotSmoke -f net10.0→ exit 0, samepartialfromApplyProjection→ build still passes (SG silently skips) → runtime throwsInvalidProjectionExceptionand exits 134. Restored.🤖 Generated with Claude Code