Description
Overview
Disclaimer: I'm not using this package. Just leaving some feedback here to help the ecosystem 🙂
The incremental generators in this project unfortunately have some (big) issues: they are completely not incremental, and they are extremely inefficient. The latter is because they introduce a whole bunch of generator state tables that will never compare as equal anyway (as they're capturing values that cannot be equated), meaning they'll generate source again every single time.
To clarify:
- These generators as is are completely incorrect
- They need to be rewritten to use an attribute as trigger, and use
ForAttributeWithMetadataName
If the objection is "but using an attribute is less convenient for users", sure. Maybe. But that's the only way to make this correct and it's a design principle that should not be considered optional for generators. Performance has to come first, because poorly performing generators (like these ones below) impact the entire IDE experience.
You should also enable this property to get the Roslyn analyzer help spot all of these issues (or, most of them):
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
The offending generators:
StructId/src/StructId.Analyzer/BaseGenerator.cs
Lines 27 to 64 in ff93ea8
StructId/src/StructId.Analyzer/DapperGenerator.cs
Lines 36 to 87 in ff93ea8
StructId/src/StructId.Analyzer/EntityFrameworkGenerator.cs
Lines 50 to 67 in ff93ea8
StructId/src/StructId.Analyzer/NewtonsoftJsonGenerator.cs
Lines 18 to 19 in ff93ea8
StructId/src/StructId.Analyzer/TemplatedGenerator.cs
Lines 81 to 155 in ff93ea8
This model is also completely not incremental:
Analyzers
Performance issues in this project are not exclusive to generators, but analyzers are also not optimal. However, these should be lower priority than fixing the generators, since at least analyzers don't directly block the IDE (though they should still be fixed).
For instance, here's an offending analyzer:
StructId/src/StructId.Analyzer/RecordAnalyzer.cs
Lines 25 to 42 in ff93ea8
Targeting all syntax nodes and then doing GetDeclaredSymbol
on each of them is not efficient. You should use an appropriate callback method, like one for an INamedTypeSymbol
, and use that. If you need to also compare against well known types, you should gather them in a compilation start action, and then flow them into a nested symbol callback.
Solution
Like I mentioned above, all these generators need to be rewritten to use an attribute as trigger, and use ForAttributeWithMetadataName
. Not wanting to use an attribute for convenience is not a valid argument for having a generator that is outright breaking all design principles of incremental generators, and introducing performance issues that will impact the whole IDE.
If it heps, you can check out some other incremental generators and analyzers for reference, such as:
- https://github.com/Sergio0694/ComputeSharp
- https://github.com/CommunityToolkit/dotnet (MVVM Toolkit)
- 🧪 [Experiment] DependencyPropertyGenerator CommunityToolkit/Labs-Windows#624 (
DependencyProperty
generator)