feat: support lifecycle hooks on [Scan], with generic dispatch#118
feat: support lifecycle hooks on [Scan], with generic dispatch#118vbreuss wants to merge 4 commits into
Conversation
A [Scan] can now name OnActivated/OnRelease, applied to every match and resolved through the same pipeline as an explicit registration's hook. For an open-generic marker the hook may be generic: the match's closed marker form binds its type argument, so [Scan(typeof(IView<>), OnActivated = nameof(WireView))] dispatches WireView<IMainViewModel>(view, vm) with the matching view model resolved from the graph and no reflection. A match that closes the marker more than once is ambiguous and reported as AWT198.
🚀 Benchmark ResultsDetails
Details
Details
|
…t falsely rejected A generic lifecycle hook on an open-generic [Scan] marker binds its type argument from the match's single closed marker form. AWT198 (ambiguous marker) was decided during scan expansion, where only the hook name is known, so it fired for any match closing the marker more than once even when the named hook was non-generic and needed no type argument, and it kept only the first-seen closing per implementation. Move the AWT198 decision to ResolveHook, where the method arity is known: a generic hook with more than one distinct closing is ambiguous, a non-generic one is unaffected. Collect the closed marker forms in ScanHookMarkers instead of judging them, and union them across every registration of an implementation in coalescing, so two open-generic scans binding the same generic hook to different closings surface as AWT198 rather than an order-dependent silent dispatch.
…s (AWT199) Review of the scan lifecycle hook feature surfaced several coalescing and binding defects, fixed here: - Track closed marker forms per hook slot (OnActivated/OnRelease) instead of one per-implementation union, so a generic hook is only considered ambiguous among registrations naming the same hook in the same slot. Two scans hooking different slots of the same type no longer trigger a false AWT198. - Merge scan hooks across scans: a later scan fills a slot the winning scan left unset, so an OnActivated scan and an OnRelease scan matching the same type both apply. Same-slot conflicts with different methods now report the new AWT199 warning (first scan wins), mirroring AWT142. - Validate generic constraints before constructing a hook method, so a constraint-violating closing falls through to AWT164 instead of leaking a CS error into the generated source. - Decide AWT198 from actual bindability: closings whose arity, constraints, or first parameter cannot bind no longer count, so unusable generic hooks report AWT164 and constraints can settle a formerly ambiguous match down to a single bindable form. - Reword the AWT198 message to name the hook and the actual set of bindable closed forms, which is accurate for both the single-marker double-closing and the cross-marker case. Explicit-over-scan override intentionally stays diagnostic-free: an explicit registration replaces a scan registration wholesale, hooks included, which is the sanctioned remediation path for AWT198. The scanning docs now state this and no longer claim AWT166 covers hook conflicts. Adds regression tests for each fix plus runtime coverage for generic OnRelease hooks, arity-2 markers, base-class open markers, and the two-scan hook merge.
…plicit override corner A review follow-up pass: add a generator test proving that two markers closing to the identical type argument dedupe into a single constructed hook dispatch with no AWT198, and extend the scanning docs to state that an explicit registration of just the concrete type strips the scan hooks even where the scan still supplies its marker mapping.
|


A [Scan] can now name OnActivated/OnRelease, applied to every match and resolved through the same pipeline as an explicit registration's hook.
For an open-generic marker the hook may be generic: the match's closed marker form binds its type argument, so [Scan(typeof(IView<>), OnActivated = nameof(WireView))] dispatches WireView(view, vm) with the matching view model resolved from the graph and no reflection. A match that closes the marker more than once is ambiguous and reported as AWT198.
[Scan]#112