Set IsAotCompatible=true on JasperFx + JasperFx.Events (#213)#247
Merged
Conversation
First deliverable on the AOT compliance pillar (#213). Flipping the flag turns on the IL2026 / IL2070 / IL2075 / IL3050 analyzers against our own build, so the punch list of reflective surfaces that still need [RequiresDynamicCode] / [RequiresUnreferencedCode] / [DynamicallyAccessedMembers] annotations surfaces in our CI rather than downstream consumers'. Tests still pass on net9.0 + net10.0 across CoreTests (407), EventTests (255), CodegenTests (366), and CommandLineTests (280). Initial fallout (net9.0; net10.0 mirrors): JasperFx — 236 warnings 104 Core (64 Reflection, 30 IoC, 10 TypeScanning) 54 CodeGeneration (22 Services, 8 Snapshots, 8 GeneratedType, etc.) 46 CommandLine (12 Parsing, 10 CommandFactory, 6 Internal, etc.) 16 ServiceContainer.cs 6 JasperFxOptions.cs 10 misc (Resources, Environment, Descriptors, etc.) JasperFx.Events — 134 warnings 30 Projections/EventProjectionApplication.cs 60 Aggregation/* (JasperFxAggregationProjectionBase, AggregateApplication.*, CreateMethodCollection, AggregateVersioning, ApplyMethodCollection) 12 Internals + IEventRegistry 16 Daemon, CommandLine, StreamAction, Tags, misc These are the inputs for the rest of the AOT pillar: - The CommandLine slice will be addressed in the follow-up audit (#213 sub-item — "Audit reflective discovery in JasperFx.CommandLine for IJasperFxCommand"). - The AOT-clean smoke-test consumer project (next pillar sub-item) will pin the build clean once each slice has been annotated or migrated. - The Reflection / IoC / Aggregation slices want follow-up issues filed against the pillar to track per-area annotation work.
This was referenced May 12, 2026
This was referenced May 12, 2026
Closed
Closed
thechucklingatom
pushed a commit
to thechucklingatom/jasperfx
that referenced
this pull request
May 19, 2026
Second deliverable on the AOT compliance pillar (JasperFx#213). Walks the JasperFx.CommandLine subsystem and either annotates each reflective entry point with [RequiresUnreferencedCode] / [RequiresDynamicCode] or suppresses analyzer warnings with a [UnconditionalSuppressMessage] that names the already-annotated entry point. Public surfaces annotated ICommandCreator.CreateCommand / CreateModel ActivatorCommandCreator — Activator.CreateInstance(Type) DependencyInjectionCommandCreator — ActivatorUtilities + GetProperties ICommandFactory — BuildRun / RegisterCommands / BuildAllCommands / ApplyExtensions CommandFactory — RegisterCommand[s], BuildRun, BuildAllCommands, HelpRun, Build, ApplyExtensions, RegisterCommandsFromExtensionAssemblies CommandExecutor — ExecuteCommand[Async]<T>, Execute / ExecuteAsync CommandLineHostingExtensions — RunJasperFxCommands*, ApplyJasperFxExtensions, ApplyFactoryDefaults OaktonShims — ApplyOaktonExtensions, RunOaktonCommands (legacy aliases) InputParser — GetHandlers / BuildHandler UsageGraph(Type) + BuildInput Suppressed at the call site (justified by entry-point annotations) CommandFactory.TryRegisterFromGeneratedManifest — emits via JasperFx.SourceGenerator CommandExecutor.execute — Spectre WriteException only on error path EnumerableArgument.Handle / EnumerableFlag.Handle — CloseAndBuildAs reachable only from annotated entry points ArrayConversion.ConverterFor — Array.CreateInstance via Conversions StringConverterProvider.ConverterFor — Type.GetConstructor via Conversions DescribeCommand.ReferencedAssemblies.WriteToConsole — diagnostic-only JasperFxCommand<T> / JasperFxAsyncCommand<T> constructors — UsageGraph reads T's members which are preserved via the annotated RegisterCommand entry point Source-generated path preserved CommandFactory.TryRegisterFromGeneratedManifest is the AOT-clean fast path. Apps that include JasperFx.SourceGenerator emit the JasperFx.Generated.DiscoveredCommands manifest as ordinary source, which survives trimming naturally. The reflective fallback (RegisterCommands / RegisterCommandsFromExtensionAssemblies) is exactly what the annotations warn AOT consumers about. Effect on the IL warning punch list Before (after JasperFx#213 flag-flip in PR JasperFx#247): JasperFx total per TFM: 236 warnings, of which CommandLine slice: 46 After this PR: JasperFx total per TFM: 188 warnings, of which CommandLine slice: 0 Remaining warnings sit in Core/Reflection (128), Core/IoC (60), CodeGeneration/Services (44), ServiceContainer.cs (32), and a long tail of smaller areas — each is a follow-up issue against JasperFx#213. CommandLineTests (280), CoreTests (407), CodegenTests (366) all pass on net9.0 + net10.0. Runtime behavior is unchanged; the annotations are analyzer-only.
thechucklingatom
pushed a commit
to thechucklingatom/jasperfx
that referenced
this pull request
May 19, 2026
Carries the AOT pillar Tier 1 work (JasperFx#213) that landed in JasperFx#247 (IsAotCompatible=true on JasperFx + JasperFx.Events) and JasperFx#250 (CommandLine reflective surface annotated + AOT-clean smoke test in CI). Downstream consumers — Weasel 9 (alpha.8 → alpha.11 refresh queued via weasel#273), Polecat 4 (alpha.8 today), Marten 9 — can pick this up to get the AOT analyzer flag and the precise CommandLine punch list. Other packages (JasperFx.RuntimeCompiler, JasperFx.SourceGeneration, JasperFx.Events.SourceGenerator) keep their current alpha — nothing changed in those projects this cycle. NugetPush is `SkipDuplicate` so the re-published artifacts at their existing versions are no-ops.
thechucklingatom
pushed a commit
to thechucklingatom/jasperfx
that referenced
this pull request
May 19, 2026
Final AOT-pillar cleanup pass for JasperFx (JasperFx#213). After PRs JasperFx#256–JasperFx#259 closed the four largest slices (ServiceContainer, CodeGeneration/Services, Core/IoC, Core/Reflection), 74 warnings per TFM remained across the long tail. This PR brings the JasperFx project to **0 IL warnings** with `IsAotCompatible=true` enabled. Annotated reflective entry points AssemblyFinder.FindAssemblies (3 overloads) — [RUC] IJasperFxAssemblyLoadContext + impl — [RUC] AssemblyTypes(Assembly) — [RUC] TypeRepository.ForAssembly / FindTypes (3x) — [RUC] TypeQuery.Find(IEnumerable<Assembly>) — [RUC] AssemblyScanner.Start + assembly-scan APIs — [RUC] (matches IAssemblyScanner) IAssemblyScanner.AssembliesFrom* — [RUC] on interface CommandLineHostingExtensions.ApplyJasperFx* — already RUC; cascades JasperFxOptions.HasReferenceToJasperFxTool — [RUC] JasperFxOptions.DetermineCallingAssembly — [RUC] JasperFxOptions.establishApplicationAssembly — [RUC] JasperFxOptions.ReadHostEnvironment — [RUC] JasperFxServiceCollectionExtensions.AddJasperFx + CritterStackDefaults — [RUC] EnvironmentCheckExtensions (5 overloads) — [RUC] SnapshotGate.Read / SnapshotGate.Write — [RUC] + [RDC] (STJ JsonSerializer) ISystemPart.WriteToConsole — [RUC] on interface DescribeCommand.Execute — suppress + #pragma on async-state-machine WriteToConsole call CodeGeneration/Frames/MethodCall(Type,string) — [RUC] + [DAM(PublicMethods)] CodeGeneration/Frames/MethodCall.correctedReturnType — suppress IL2067 (well-known Task types) CodeGeneration/Frames/MethodCall.returnsValueTask — suppress IL2072 CodeGeneration/GeneratedAssembly.AddType — [DAM(PublicCtors|PublicMethods|NonPublicMethods)] CodeGeneration/GeneratedAssembly.AttachAssembly — [RUC] CodeGeneration/GeneratedType.CompiledType property — [DAM(PublicCtors)] CodeGeneration/GeneratedType.InheritsFrom<T>/<Type> — [DAM(PublicCtors|Methods)] CodeGeneration/GeneratedType.Implements<T>/(Type) — [DAM(PublicMethods)] CodeGeneration/GeneratedType.FindType + ApplySetterValues — [RUC]/suppress CodeGeneration/Model/Setter.SetInitialValue — [RUC] CodeGeneration/Model/Variable.VariablesForProperties<T> — [DAM(PublicProperties)] CodeGeneration/Model/Variable.DefaultArgName — suppress (cosmetic) CodeGeneration/Expressions/LambdaDefinition.Compile<TFunc> — [RUC] ServiceCollectionServerVariableSource.Matches — suppress (IVariableSource contract doesn't carry DAM) CodeGeneration/CodeGenerationExtensions.BuildExportedTypeIndex — suppress CodeGeneration/Services findFamily — re-applied IL2067 suppression (was lost in JasperFx#256 + JasperFx#257 merge) ServiceContainer.CouldResolve(Type) — [DAM(PublicCtors)] ServiceContainer.findFamily — re-applied IL2067 suppression (was lost in PR JasperFx#256 + JasperFx#257 merge resolution) Descriptors/OptionsDescription — [RUC] on ctor / For() / readProperties Descriptors/DatabaseDescriptor ctors — [RUC] (inherits OptionsDescription) CommandLine/Descriptions/ConfigurationPreview.WriteToConsole — [RUC] CommandLine/Descriptions/DescribeCommand.WriteToConsole (×2 overrides) — [RUC] CommandLine/CommandFactory.IsJasperFxCommandType — [DAM(Interfaces)] CommandLine/CommandFactory.TryRegisterFromGeneratedManifest — IL2072 suppress added Resources/ResourcesCommand.ExecuteOnEach — suppress IL3050 (Spectre WriteException on error-display path) JasperFxAssemblyAttribute ctor — [DAM(PublicCtors|NonPublicCtors)] Effect on the punch list Before: JasperFx total per TFM 74 warnings After: JasperFx total per TFM 0 warnings Cumulative since JasperFx#213 flag-flip (PR JasperFx#247): 236 (initial fallout) → 0 (all addressed) Note on JasperFx.Events The propagation of new annotations into the JasperFx.Events compilation surfaces ~246 warnings per TFM that aren't addressed here. That deserves its own focused PR + likely an issue under JasperFx#213. Verification CoreTests 407/407 pass on net9.0 + net10.0 CommandLineTests 280/280 pass on net9.0 + net10.0 CodegenTests 366/366 pass on net9.0 + net10.0 SmokeTestAot build clean, exits 0 Closes (most) the AOT pillar JasperFx#213 for JasperFx itself. Events follow-up deferred to a separate PR.
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.
First deliverable on the AOT compliance pillar for the Critter Stack 2026 wave. Sets
IsAotCompatible=trueon the two foundational packages so the IL2026 / IL2070 / IL2075 / IL3050 analyzers run against our own build. Reflective surfaces that still need[RequiresDynamicCode]/[RequiresUnreferencedCode]/[DynamicallyAccessedMembers]annotations surface here, not in downstream consumers' CI.Surface
Behavior
net9.0+net10.0:CoreTests— 407 passedEventTests— 255 passedCodegenTests— 366 passedCommandLineTests— 280 passedInitial fallout (net9.0 baseline; net10.0 mirrors)
JasperFx — 236 warnings
Core/ReflectionValueTypeInfo,GenericFactoryCache,TypeExtensionsCodeGeneration/Services+ miscServiceProviderPlan,ServiceFamily,ArrayPlan,GeneratedType,Snapshots/SnapshotGateCommandLine/*CommandFactory,Parsing/*,Internal,DependencyInjectionCommandCreator— scope of follow-up BCore/IoCGenericConnectionScanner,DefaultConventionScanner,ImplementationMapServiceContainer.csCore/TypeScanningAssemblyFinder,AssemblyTypesJasperFxOptions.csResources,Environment,Descriptors,CommandLineHostingExtensionsJasperFx.Events — 134 warnings
Projections/EventProjectionApplication.csAggregation/*JasperFxAggregationProjectionBase,AggregateApplication.{Register,Creating,ShouldDelete,Applies},CreateMethodCollection,ApplyMethodCollection,AggregateVersioningInternals/MethodCollection.cs,IEventRegistry.csDaemon,CommandLine,StreamAction,Tags,ReflectionExtensionsWhy this lands flag-only
Per the pillar definition, the goal is either AOT-clean or every dynamic surface annotated with precise
[RequiresDynamicCode]/[RequiresUnreferencedCode]. Annotating ~370 warning sites in a single PR would be unreviewable; each slice is naturally a follow-up.Immediate next steps (separate PRs, tracked under #213):
JasperFx.CommandLineaudit — assembly-scanning forIJasperFxCommand, ~46 warnings. Already queued as the next pillar deliverable.Core/Reflection,Core/IoC,Aggregation,Projections— best filed as follow-up issues against [Pillar] AOT compliance #213 so they can be tackled independently.🤖 Generated with Claude Code