Replace ISourceGenerator with IIncrementalGenerator (#11302)#12271
Replace ISourceGenerator with IIncrementalGenerator (#11302)#12271msynk wants to merge 1 commit intobitfoundation:developfrom
Conversation
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
Migrates the Bit source generators from legacy ISourceGenerator/syntax receivers to Roslyn incremental generators to reduce redundant work during builds and improve IDE responsiveness (per #11302).
Changes:
- Replaced syntax receivers with
IIncrementalGeneratorpipelines for HttpClientProxy, AutoInject, and SetParameters generators. - Introduced flat/serializable record-struct models (
ControllerEntry,BitProperty,BlazorParameter,AutoInjectMember) to support incremental caching. - Added
IsExternalInitpolyfills to enablerecord structusage while targetingnetstandard2.0.
Reviewed changes
Copilot reviewed 24 out of 24 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/SourceGenerators/Bit.SourceGenerators/IsExternalInit.cs | Adds IsExternalInit polyfill for netstandard2.0 record/init support. |
| src/SourceGenerators/Bit.SourceGenerators/HttpClientProxy/IController.cs | Removes legacy mutable controller model used by the syntax receiver. |
| src/SourceGenerators/Bit.SourceGenerators/HttpClientProxy/HttpClientProxySyntaxReceiver.cs | Removes legacy ISyntaxContextReceiver implementation. |
| src/SourceGenerators/Bit.SourceGenerators/HttpClientProxy/HttpClientProxySourceGenerator.cs | Reworks HttpClientProxy generation as an incremental generator; uses encoded action data for value-based equality. |
| src/SourceGenerators/Bit.SourceGenerators/HttpClientProxy/ControllerEntry.cs | Adds flat, equatable controller model for incremental transform/output. |
| src/SourceGenerators/Bit.SourceGenerators/HttpClientProxy/ControllerAction.cs | Removes legacy mutable action model. |
| src/SourceGenerators/Bit.SourceGenerators/HttpClientProxy/ActionParameter.cs | Removes legacy mutable parameter model. |
| src/SourceGenerators/Bit.SourceGenerators/Blazor/BlazorSetParametersSourceGenerator.cs | Replaces receiver-based SetParameters generator with incremental attribute-driven pipeline. |
| src/SourceGenerators/Bit.SourceGenerators/Blazor/BlazorParameterPropertySyntaxReceiver.cs | Removes legacy receiver. |
| src/SourceGenerators/Bit.SourceGenerators/Blazor/BitProperty.cs | Replaces Roslyn-symbol-based class with flat record struct used for caching. |
| src/SourceGenerators/Bit.SourceGenerators/AutoInject/AutoInjectSyntaxReceiver.cs | Removes legacy receiver. |
| src/SourceGenerators/Bit.SourceGenerators/AutoInject/AutoInjectSourceGenerator.cs | Reworks AutoInject generation as incremental; introduces direct/derived entry modeling and encoded base-member caching. |
| src/SourceGenerators/Bit.SourceGenerators/AutoInject/AutoInjectRazorComponentHandler.cs | Updates handler to accept serialized member/type info instead of Roslyn symbols. |
| src/SourceGenerators/Bit.SourceGenerators/AutoInject/AutoInjectNormalClassHandler.cs | Updates handler to accept serialized member/type info and preserve nullable default behavior. |
| src/SourceGenerators/Bit.SourceGenerators/AutoInject/AutoInjectMember.cs | Adds serialized member model for incremental processing. |
| src/BlazorUI/Bit.BlazorUI.SourceGenerators/IsExternalInit.cs | Adds IsExternalInit polyfill for netstandard2.0 record/init support. |
| src/BlazorUI/Bit.BlazorUI.SourceGenerators/Component/ComponentSyntaxContextReceiver.cs | Removes legacy receiver. |
| src/BlazorUI/Bit.BlazorUI.SourceGenerators/Component/ComponentSourceGenerator.cs | Reworks component SetParameters generator as an incremental generator; captures parameter metadata as strings/bools. |
| src/BlazorUI/Bit.BlazorUI.SourceGenerators/Component/BlazorParameter.cs | Replaces Roslyn-symbol-based model with flat record struct. |
| src/BlazorUI/Bit.BlazorUI.SourceGenerators/AutoInject/AutoInjectSyntaxReceiver.cs | Removes legacy receiver. |
| src/BlazorUI/Bit.BlazorUI.SourceGenerators/AutoInject/AutoInjectSourceGenerator.cs | Reworks AutoInject generation as incremental for BlazorUI generators. |
| src/BlazorUI/Bit.BlazorUI.SourceGenerators/AutoInject/AutoInjectRazorComponentHandler.cs | Updates handler to accept serialized member/type info instead of Roslyn symbols. |
| src/BlazorUI/Bit.BlazorUI.SourceGenerators/AutoInject/AutoInjectNormalClassHandler.cs | Updates handler to accept serialized member/type info instead of Roslyn symbols. |
| src/BlazorUI/Bit.BlazorUI.SourceGenerators/AutoInject/AutoInjectMember.cs | Adds serialized member model for incremental processing. |
| if (!first.IsPartial) | ||
| { | ||
| spc.ReportDiagnostic(Diagnostic.Create(NonPartialClassError, Location.None, first.ClassName)); | ||
| continue; |
There was a problem hiding this comment.
Non-partial class diagnostics are reported with Location.None, which makes the error hard to trace back to the offending class. Use the declaring syntax reference location (e.g., the first ClassDeclarationSyntax from DeclaringSyntaxReferences) so the diagnostic is placed on the class declaration.
| if (!entry.IsPartial) | ||
| { | ||
| context.ReportDiagnostic(Diagnostic.Create(NonPartialClassError, classDeclarationSyntax.GetLocation(), @class.Name)); | ||
| return false; | ||
| spc.ReportDiagnostic(Diagnostic.Create(NonPartialClassError, Location.None, entry.ClassName)); | ||
| continue; |
There was a problem hiding this comment.
Non-partial class diagnostics are reported with Location.None here too; consider reporting on the class declaration location (from DeclaringSyntaxReferences) so users can navigate directly to the source of the error.
| if (!first.IsPartial) | ||
| { | ||
| spc.ReportDiagnostic(Diagnostic.Create(NonPartialClassError, Location.None, first.ClassName)); | ||
| continue; |
There was a problem hiding this comment.
The diagnostic for non-partial classes is created with Location.None, which reduces IDE usability. Prefer attaching the diagnostic to the class declaration location (from DeclaringSyntaxReferences) so the error highlights the correct code.
| if (!entry.IsPartial) | ||
| { | ||
| spc.ReportDiagnostic(Diagnostic.Create(NonPartialClassError, Location.None, entry.ClassName)); | ||
| continue; |
There was a problem hiding this comment.
Same as above: reporting this diagnostic with Location.None makes it hard to find the offending derived class. Use the class declaration syntax location where possible.
|
Nice migration overall👍 I looked at the pr briefly with the help of ai and found two things that stood out and could be improved. First, it would be good to reduce the current .Collect() / final grouping pattern where possible. Even though this is using incremental APIs, batching a lot of data before generation limits the actual benefits of incremental generators. Second, HttpClientProxy would likely benefit from being generated per controller instead of as one combined output. As it is now, a small API change can trigger regeneration of the entire proxy, whereas per-controller generation would give much better granularity and reduce excessive regeneration. |
closes #11302