dotnet/roslyn-sdk

Add support in AnalyzerTest to include source generators as part of the test run

kzu opened this issue · 4 comments

kzu commented

Currently, analyzers that require a source generator to run so that the actual source
compiles successfully, cannot be run because only solution transforms are available.

By adding an AnalyzerTest.CompilationTransforms list (similar to SolutionTransforms)
property, test authors could easily apply additional source generators to the compilation
before the rest of the test evaluation continues, for example:

        var test = new AnalyzerTest
        {
            TestCode = "...",
            CompilationTransforms =
            {
                (compilation, project) =>
                {
                    CSharpGeneratorDriver
                        .Create(new StaticGenerator())
                        .RunGeneratorsAndUpdateCompilation(compilation, out var staticPass, out var _);

                    CSharpGeneratorDriver
                        .Create(new IncrementalGenerator())
                        .RunGeneratorsAndUpdateCompilation(staticPass, out var incrementalPass, out var _);

                    return incrementalPass;
                }
            }
        };

With this in place, the analyzer can verify code that uses generated code in order to properly
compile.

This is already mentioned in some other places but I'll include it here for visibility: to run your source generators as part of the overall test setup (i.e. not on a per-test basis), you can hook into the compilation by overriding GetProjectCompilationAsync inside your CSCodeFix+Test class.

For example to add a generator named PagedListGenerator, I just added a csproj reference and the following code:

protected override async Task<Compilation> GetProjectCompilationAsync(Project project, IVerifier verifier, CancellationToken cancellationToken)
{
    var compilation = await base.GetProjectCompilationAsync(project, verifier, cancellationToken);
    CSharpGeneratorDriver.Create(new PagedListGenerator()).RunGeneratorsAndUpdateCompilation(compilation, out var newCompilation, out _, cancellationToken);
    return newCompilation;
}
kzu commented

Compilation transforms are much more idiomatic IMO (with the SolutionTransforms approach). And they don't require you to inherit types just to override one thing (which might only apply to a single test).

I implemented support for adding source generators to analyzer and code fix tests in #1063