Source Generators need to be able to call other source generators #48358
Replies: 6 comments 27 replies
-
We've so far intentionally tried to avoid this because of all of the problems you've mentioned. 😄
I worry about this a bit though: a serialization library needs to run "after" other any other thing trying to generate a type because it might have to serialize that type. So that implicitly means anything generating a type has to be in the first pass, not second pass. And the challenge here is if somebody writes a generator and didn't opt themselves into the first pass, then the user is now broken when they try to use both... |
Beta Was this translation helpful? Give feedback.
-
I'm convinced sequencing is something absolutely crucial, also w.r.t. breaking changes: for example, blazor/razor currently uses MSBuild-based source generation (a razor file is converted to a csharp file which then gets compiled normally). This is something that currently doesn't make use of roslyn-SGs, but in the future might very well do so. However, we can currently write source generators that use the MSBuild-SG-generated code, e.g. to inspect parameters of components ( My gut feeling says that generating a dependency graph (enforced to be cycle-free) should suffice to get rid of most problems. |
Beta Was this translation helpful? Give feedback.
-
Just faced this in a custom source generator, which generates a custom So definitely 👍 for some solution in this space. |
Beta Was this translation helpful? Give feedback.
-
If this would be possible, would it then also be possible to let source generators modify the code and not just add code? |
Beta Was this translation helpful? Give feedback.
-
Also stumbled upon this. Implementing a sort of RPC framework. For that im putting the arguments of the methods into MemoryPack classes and add some boiler plate using a source generator. Unfortunately the MemoryPack source generator does not see my generated Argument files and therefore it can't generate it. Now i'm contemplating if i should write a manualy code parser as a pre-build step, that generates the files, adds it to the prj and then the MemoryPack generator can do its work. |
Beta Was this translation helpful? Give feedback.
-
I have just hit this issue with the source generator in https://github.com/corvus-dotnet/corvus.jsonschema This emits code for serialization/validation using JSON Schema files as the basis. When you run the command line tool, the code it emits uses the This will not compile, so we have to fall back on runtime creation of Regular Expressions, which (I assume) will negatively impact start-up time. |
Beta Was this translation helpful? Give feedback.
-
There are plans to push for source generators to be used for all sorts of scenarios that are currently done at runtime. For example:
The runtime is looking into using SourceGenerators to generate interop stubs: https://github.com/dotnet/runtime/blob/master/docs/design/features/source-generator-pinvokes.md
There's a push to get serialization frameworks to use Source Generators to help with trimming among other scenarios: https://devblogs.microsoft.com/dotnet/app-trimming-in-net-5/
I'm sure there are many more - for example Asp.Net is definitely thinking about how it can use Source Generators to wire things up.
However at the moment source generators can't use other source generators. What this means is that it will be impossible for a source generator to generate pinvoke code, asp.net code, or code using serialization, since the relevant source generators which are meant to process these wont see the generated files (although they can always use the runtime/reflection option as a fallback). This seems like a pretty critical limitation.
In an ideal world it would be possible to create a graph of exactly which source generators rely on which other ones. However in practice this means creating potentially as many compilations as there are source generators which may lead to serious performance problems: https://discord.com/channels/732297728826277939/735233259763400715/762740254921719848. There's also no obvious, reliable way to specify this graph.
More pragmatically I think it would be sufficient to run source generators in 2 passes. By default all source generators run in the second pass, and cannot use other source generators. However a SourceGenerator can opt in to running in the first pass. This will mean files it generates will be seen by the second pass. So either your generator can use other generators, or it can be used by other generators, but not both.
That way low level source generators which expect to be used by other source generators will make sure not to rely on any other source generator (even if that leads to a lot of extra work). Other source generators can then freely use these if they want.
Beta Was this translation helpful? Give feedback.
All reactions