-
This is an extension of the issue #59388 Within VS IDE, source generators are currently running on every key stroke, even if you optimize them using an incremental source generator and cancellation tokens. The problem is that many use cases don't need the generated code to be actually generated at each key stroke. After 2+ years of seeing usage of source generators, I have seen a couple of interactivity mode that would be better suited depending on user scenarios (from most frequent to less frequent):
But you can have also a mixed solution where on every key stroke you generate diagnostic messages, but you don't want to generate any code (e.g validating a regex without generating the state machine, or usually any code that you generate behind a partial method). One year ago, I created this gist to workaround the lack of configuration for a source generator to only be triggered at build time. And I have been referring to it multiple times to several teams in my company whenever they were facing a struggle with source generator taking too much time at IDE time (while most generated code is actually not accessible for end users). Based on this experience, I would like to request that we provide a way to detect the current interactivity context for a source generator, so that it can select different code path depending on this context in a more fine grained way.
|
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 18 replies
-
The answer for #59388 applies here. Incremental generators have shown that generators can be efficient and non-impactful on the IDE experience. This is the supported and workable solution that SG authors should be taking. |
Beta Was this translation helpful? Give feedback.
-
Note: the suggested gist is not something that will work in the future, esp. if we start utilizing our external processes (like vbcscompiler) to run the generators the IDE needs. This is not something that should be done and breaks important things like idempotency. |
Beta Was this translation helpful? Give feedback.
-
It actually got broken with Rider. 🙂 So we gonna have to find another solution...
We have a source generator that is only relevant for build time but not for IDE time: This source generators needs to collect all struct/class/interface declarations in order to collect their source location, and then we generate an internal type that is going to store all these locations (large byte buffers that have strings of paths encoded in UTF8). For some assemblies, with thousands of types, it can be quite significant. @CyrusNajmabadi how an incremental source generator can help in that case? class TypeFileNameScraper : ISyntaxReceiver
{
public Dictionary<string, List<MonoScriptInfo>> Types { get; } = new();
public Dictionary<MonoScriptInfoKey, List<MonoScriptInfo>> MonoScriptInfoCollisions { get; } = new();
public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
{
if ((syntaxNode is StructDeclarationSyntax ||
syntaxNode is ClassDeclarationSyntax ||
syntaxNode is InterfaceDeclarationSyntax)
&& syntaxNode is TypeDeclarationSyntax typeDeclaration)
{ |
Beta Was this translation helpful? Give feedback.
I indeed use the
$(DesignTimeBuild)
property for exactly this purpose and it works great. It's set as a global property by VS when it runs the design-time build (you can see this by using the Project System Tools extension in VS and the msbuildlog.com tool). You just make it aCompilerVisibleProperty
and check it from the generator. I'm not sure Rider does the same though.