I’ve been following the Unity documentation for setting up a Roslyn source generator in my project. So far, the essential part, generating code, works fine.
However, I’m having big issues developing my generator because I can’t get debugging to work. Here’s what I’ve tried:
Build the generator DLL with debug information (debug configuration in Rider and pdb symbol files)
Open the Unity project solution, navigate to the generator assembly, set a breakpoint
Attach the regular Unity debugger (which normally works in my project)
Open the generator project solution, set a breakpoint
Attach to the Unity editor process
In both cases, the breakpoints are never hit and show grayed out with the error message “Didn’t find the associated module”.
Next, I tried to get some form of logging working:
System.Console.WriteLine (as expected this doesn’t show in Unity, nor in Rider, not sure if there’s a way to make it show outside of Unity)
System.Diagnostic.Trace.WriteLine (not showing, as expected)
Roslyn GeneratorExecutionContext.ReportDiagnostic (nothing happened, but I think this only works for Analyzers anyway)
Finally, I tried to add a reference to the UnityEngine.dll and use Debug.Log in the generator, however this also failed. This option seems the most promising, so I tried a couple of things, but no matter what I did, as soon as I added a reference to the UnityEngine.dll in my csproj the generator would silently fail without errors. It simply stopped generating the code. In other regular DLL projects, it works fine to reference UnityEngine and also export it back to Unity.
So, does anyone have debugging or logging working for Roslyn source generators? Please share!
I also could not find a good way to debug Roslyn source generators, but here’s my janky solution: just append your debug output to a file and tail the log in Notepad++ or similar.
Right now I’m basically wrapping my entire Execute block in a try/catch and then doing something like this in the catch block:
If the generator runs in Rider or Visual Studio, the working directory of the executing code is unrelated to Unity and so, relative file paths for the log would point to some temporary directory.But if we use absolute file paths, we can implement regular C# logging, we just have to keep the concurrency issues in mind.
Btw, GeneratorExecutionContext.ReportDiagnostic does work to show messages in the Unity console. Mine weren’t running because the generator threw an unnoticed exception earlier. However, I still found file logging to be more practical to work with.
Can you post a link to the dev’s post or maybe share some more insight how I could attach the debugger while compiling with csc directly? I tried the command, and it prints a lot of compilation output in my IDE, but my debugger didn’t launch. Also, do you know which profiler would work for this?
To be for me, but I believe, Debugger.Launch is not implemented on macOS, at least it’s not working for me and I found a couple of mentions online that it’s only working on Windows.
As a replacement for Debugger.Launch I added some waiting code:
bool loop = true; while(loop) Thread.Sleep(10);
Tasks or something else will probably work the same.
While the compiler was stuck on the infinite loop I could attach the debugger. Pay attention to the file paths, as there are usually multiple processes running (Unity + IDE):
Then, when the debugger hits a breakpoint within the infinite loop, use the evaluate/expression window of your IDE to set the variable to false and continue the code
Can anyone give an optimal way for testing source generators? First time using C# outside of Unity. Right now I’m just printing output to text files… not pretty. I’m a little too out of my depth to pick up on what people have been talking about in this thread.
It also shows how to use ReportDiagnostic, this one works for me inside the Execute(context) method:
var desc = new DiagnosticDescriptor("id", "title", "message format", "category", DiagnosticSeverity.Error, true);
var diag = Diagnostic.Create(desc, Location.None, "more context");
context.ReportDiagnostic(diag);
You probably need to adjust the messageFormat to consume the additional parameters. However I’m not taking this any further because only Error severity diagnostics are logged to the Unity Console.
Tests seem to be the most viable option for debugging.
After spend few time on search way for getting generator exceptions in Unity, I found some interesting solution.
We can out exceptions in generated files, just like this:
public class IncrementalGenerator : IIncrementalGenerator
{
public void Initialize(IncrementalGeneratorInitializationContext context) {
var provider = context.SyntaxProvider.CreateSyntaxProvider(GetSyntaxNode, GetSemantic);
var values = provider.Collect();
context.RegisterSourceOutput(values, (ctx, values) => {
try {
// your code generation logic
}
catch(Exception e) {
ctx.AddSource("Exception.g.cs", "// <auto-generated/>\n\n" + e);
}
});
}
}
This generated file accessible from IDE, so you can read inside what went wrong)