C# source generators: How to debug compiler errors in the generated code?
Asked Answered
H

2

8

I am experimenting with C# source generators. I have spent about a day on it, and I find it a very frustrating and painful experience. IntelliSense is extremely unreliable. It occasionally works, but most often it does not, and I have not been able to figure out any system to it. (Restarting Visual Studio does not help.)

But more fundamentally, I have great trouble debugging errors in the generated code. When I make a mistake in the template in the source generator and try to compile, I might get errors like "Method must have a return type" in the generated file. But when I double-click on the error, it doesn't take me to the generated code. That makes it extremely hard to see what is wrong with it.

Is there a trick to it? Is there any way to inspect the generated code when it fails to compile? And more generally, what governs when the generated code is available for IntelliSense and when it is not?

I am using Visual Studio Professional 2022 version 17.1.6 and ReSharper 2022.1.

Thanks in advance!

Havener answered 24/5, 2022 at 13:8 Comment(7)
Are you using T4 templates?Rollins
@RossBush See the link OP included. I believe Source Generators was (were) added in .Net 5Sorrows
+1. I managed to get a source generator working after fiddling with it for several hours. However, when inspecting the obj folder, I don't see a way I can inspect the code that is being included in the assembly. So, that is also something I would like to know.Emmy
what governs when the generated code is available for IntelliSense and when it is not? - I know the answer to that one - Intellisense is controlled by source code analyzers. You really should limit your posts to a single question so they can be answered more easily.Emmy
I found an answer to how to output source code from a source generator, and it even goes into details about how to control the output path.Emmy
If you expand the Dependencies node in Solution Explorer, under that is Analyzers. Find your analyzer and expand it, and then expand the node representing your source generator. All your generated files should appear there.Eun
Apparently that "expand Dependencies node" trick only works when the source generator compiles. If it fails to compile, it is simply not listed.Havener
H
1

I have found a partial solution to my problem.

First, do not use the ReSharper builder in Visual Studio when working with source generators. It does not give proper error messages. Instead, run dotnet build from a command line. You'll get much better error messages that way.

In fact, part of my problem may be due to bugs or limitations in ReSharper (though I have not investigated this, so that is pure speculation).

Second, you can test the innards of your source generator without running the source generation at compile time.

  1. Refactor your source generator and extract a helper class (we can call it SourceGeneratorHelper.cs) that takes your input (e.g. XML) and produces output (e.g. a StringBuilder).
  2. Make a separate C# test project SourceGeneratorHelperTest.csproj for testing the class SourceGeneratorHelper.cs. In this project, reference your source generator project as if it were a regular project - i.e., DO NOT USE OutputItemType="Analyzer" in your project reference.
  3. Now you can unit test the innards of your source generator. You can also dump the generated C# code to a file and inspect it.

Moreover, as NightOwl888 pointed out, I can add this to the referencing project in order to get it to spit out the generated files to disk ( as explained in this article):

<PropertyGroup>
    <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
</PropertyGroup>

I have not solved the IntelliSense problem, but now I can at least endure working with this generator.

Havener answered 25/5, 2022 at 11:53 Comment(0)
G
4

Add the following to your code generator constructor code:

#if DEBUG 
    if (!Debugger.IsAttached) 
    { 
        Debugger.Launch(); 
    } 
#endif

Now you can use breakpoints in Visual Studio.

Intellisense is indeed garbage in VS with code generators. You need to close VS, delete /bin and /obj folders, reopen VS, then rebuild. This has to be done everytime you make changes. VS will show the old version after you changed something, intellisense will mark new things as error, yet it will still compile and run...

For a better experience I recommend using Rider, which has a much better integration experience for code generators.

Gambeson answered 30/3, 2023 at 6:31 Comment(1)
Thank you very much! I've finally gotten the debugger working. For others trying to do the same in rider, I had to set rider as the default jit debugger before getting this to work. Check the documentation to see how you do this.Atalante
H
1

I have found a partial solution to my problem.

First, do not use the ReSharper builder in Visual Studio when working with source generators. It does not give proper error messages. Instead, run dotnet build from a command line. You'll get much better error messages that way.

In fact, part of my problem may be due to bugs or limitations in ReSharper (though I have not investigated this, so that is pure speculation).

Second, you can test the innards of your source generator without running the source generation at compile time.

  1. Refactor your source generator and extract a helper class (we can call it SourceGeneratorHelper.cs) that takes your input (e.g. XML) and produces output (e.g. a StringBuilder).
  2. Make a separate C# test project SourceGeneratorHelperTest.csproj for testing the class SourceGeneratorHelper.cs. In this project, reference your source generator project as if it were a regular project - i.e., DO NOT USE OutputItemType="Analyzer" in your project reference.
  3. Now you can unit test the innards of your source generator. You can also dump the generated C# code to a file and inspect it.

Moreover, as NightOwl888 pointed out, I can add this to the referencing project in order to get it to spit out the generated files to disk ( as explained in this article):

<PropertyGroup>
    <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
</PropertyGroup>

I have not solved the IntelliSense problem, but now I can at least endure working with this generator.

Havener answered 25/5, 2022 at 11:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.