roslyn-sdk icon indicating copy to clipboard operation
roslyn-sdk copied to clipboard

Source generators, how to debug?

Open b-straub opened this issue 4 years ago • 9 comments

How can a "Source generator" be debugged?

  • where to find the generated output file as mentioned in the section "Output files" from Source Generators? For now I store the generated results myself.

  • is there a way to set breakpoints inside the generator?

b-straub avatar May 06 '20 07:05 b-straub

Found the answers to one of my questions:

  • is there a way to set breakpoints inside the generator?

When invoked by CSharpGeneratorDriver e.g. during Unit testing, the generator code can be debugged.

b-straub avatar May 10 '20 17:05 b-straub

@b-straub How are you properly creating a testable SourceGeneratorContext?

danielcrenna avatar May 12 '20 20:05 danielcrenna

@danielcrenna

Please see my test repository for an example BlazorSourceGeneratorTests

b-straub avatar May 13 '20 09:05 b-straub

I'm porting my project from using Uno.SourceGeneration to the new source generators. Uno outputs the generated files exactly as proposed for source generators and I'm missing it.

aalmada avatar May 18 '20 20:05 aalmada

The response from Directory.GetCurrentDirectory() returns the consuming project folder, so it’s easy to emit a string builder to both Roslyn and a text file. I do this to spot check output.

On Mon, May 18, 2020 at 4:58 PM Antão Almada [email protected] wrote:

I'm porting my project from using Uno.SourceGeneration https://github.com/unoplatform/Uno.SourceGeneration to new source generators. Uno outputs the generated files exactly as proposed for source generators https://github.com/dotnet/roslyn/blob/master/docs/features/source-generators.md#output-files and I'm missing it.

danielcrenna avatar May 18 '20 22:05 danielcrenna

@danielcrenna I added the following to the beginning of my Execute():

        // create a folder to serialize the generated source for debugging
        string? generatedPath = null;
#if DEBUG
        // place it inside obj so that source is not added to the project
        generatedPath = Path.Combine("obj", "Debug", "Generated");
        // delete source generated by previous build
        if (Directory.Exists(generatedPath))
                Directory.Delete(generatedPath, true);
        Directory.CreateDirectory(generatedPath);
#endif

and, for each generated file:

        var hitName = $"{containerClass.OriginalDefinition.MetadataName}.{extendedType.OriginalDefinition.MetadataName}.cs";
        var source = builder.ToString();
#if DEBUG
        File.WriteAllText(Path.Combine(generatedPath, hitName), source);
#endif
        context.AddSource(hitName, SourceText.From(source, Encoding.UTF8));

Still, it would be nice to have an official solution.

aalmada avatar May 19 '20 11:05 aalmada

@aalmada Oh, that is a much nicer way than I'm doing it, thanks for sharing.

danielcrenna avatar May 22 '20 19:05 danielcrenna

Take a look at this target: https://github.com/pakrym/jab/blob/main/src/Jab.Tests/Jab.Tests.csproj#L33

It generates the https://github.com/pakrym/jab/blob/main/src/Jab/Properties/launchSettings.json file that mimicks the csc invocation and allows for F5 debugging.

pakrym avatar Dec 28 '20 16:12 pakrym

I debug my source generators by attaching vscode to the build process Add this code to the source generator:

using System;
using System.Diagnostics;
using System.Threading;

Console.Error.WriteLine($"PID: {Process.GetCurrentProcess().Id}");
while (!Debugger.IsAttached)
{
    Thread.Sleep(100);
}

opekope2 avatar Apr 03 '21 12:04 opekope2