Search code examples
c#roslynsourcegenerators

roslyn - how to unit test syntax analyzer in combination with source generator


All examples I was able to find testing analyzers and source generators separately. But my analyzer sticks to attributes, generated by source generator. How I can combine source generator and syntax analyzer in single test run?


Solution

  • Just run generator on the compilation and then attach the analyzer with WithAnalyzers - see my take on this task here (pre-incremental generators, so maybe some complications can arise from there) which can be somewhat summarized in the following base class for tests (removed some code compared to the repo):

    public abstract class GeneratorWithAnalyzerTestBase
    {
        protected Task<ImmutableArray<Diagnostic>> RunAnalyzer<T>(T analyzer, Compilation compilation)
            where T : DiagnosticAnalyzer
        {
            var compilationWithAnalyzers =
                // run generators on the compilation
                RunGenerators(compilation, out _, new SomeGenerator()) 
                // attach analyzers
                    .WithAnalyzers(ImmutableArray.Create<DiagnosticAnalyzer>(analyzer));
    
            // collect diagnostics
            return compilationWithAnalyzers.GetAllDiagnosticsAsync();
        }
    
        protected Compilation RunGenerators(Compilation compilation,
            out ImmutableArray<Diagnostic> diagnostics,
            params ISourceGenerator[] generators)
        {
            CreateDriver(compilation, generators)
                .RunGeneratorsAndUpdateCompilation(compilation, out var updatedCompilation, out diagnostics);
            return updatedCompilation;
        }
    
        protected GeneratorDriver CreateDriver(Compilation compilation, params ISourceGenerator[] generators) =>
            CSharpGeneratorDriver.Create(
                ImmutableArray.Create(generators),
                ImmutableArray<AdditionalText>.Empty,
                (CSharpParseOptions)compilation.SyntaxTrees.First().Options
            );
    }