5

Verifier has a method:

public static Task VerifyAnalyzerAsync(string source, params DiagnosticResult[] expected)

Is it possible to load assemblies with types which are required be source code?

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
Pavel Voronin
  • 13,503
  • 7
  • 71
  • 137

1 Answers1

2

The following code made it work for me:

@usings of test class:

using BindHandlerAnalyzerVerifier = ExtendedAnalyzerVerifier<AnalyzerNamespace>;

In test:

var diagnostic = BindHandlerAnalyzerVerifier.Diagnostic().WithSpan(4, 1, 12, 2).WithArguments("TestCommand");
await BindHandlerAnalyzerVerifier.VerifyAnalyzerAsync(input, Configure, diagnostic);

Assembly configuration:

private void Configure(CSharpAnalyzerTest<CommandCallsBindHandlerAnalyzer, XUnitVerifier> configuration)
{
    var root = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
    var enumerateFiles = Directory.EnumerateFiles(root, "*.dll", SearchOption.TopDirectoryOnly).ToArray();
    configuration.ReferenceAssemblies = ReferenceAssemblies.Net.Net50;
    configuration.TestState.AdditionalReferences.AddRange(
        new[]
        {
            MetadataReference.CreateFromFile(typeof(Command).GetTypeInfo().Assembly.Location)
        });
}

Tooling class:

public class ExtendedAnalyzerVerifier<TAnalyzer> : ExtendedAnalyzerVerifier<TAnalyzer, CSharpAnalyzerTest<TAnalyzer, XUnitVerifier>, XUnitVerifier>
    where TAnalyzer : DiagnosticAnalyzer, new(){}

public class ExtendedAnalyzerVerifier<TAnalyzer, TTest, TVerifier>
    where TAnalyzer : DiagnosticAnalyzer, new()
    where TTest : AnalyzerTest<TVerifier>, new()
    where TVerifier : IVerifier, new()
{
    public static DiagnosticResult Diagnostic()
    {
        var analyzer = new TAnalyzer();
        try
        {
            return Diagnostic(analyzer.SupportedDiagnostics.Single());
        }
        catch (InvalidOperationException ex)
        {
            throw new InvalidOperationException(
                $"'{nameof(Diagnostic)}()' can only be used when the analyzer has a single supported diagnostic. Use the '{nameof(Diagnostic)}(DiagnosticDescriptor)' overload to specify the descriptor from which to create the expected result.",
                ex);
        }
    }
    
    public static DiagnosticResult Diagnostic(string diagnosticId)
    {
        var analyzer = new TAnalyzer();
        try
        {
            return Diagnostic(analyzer.SupportedDiagnostics.Single(i => i.Id == diagnosticId));
        }
        catch (InvalidOperationException ex)
        {
            throw new InvalidOperationException(
                $"'{nameof(Diagnostic)}(string)' can only be used when the analyzer has a single supported diagnostic with the specified ID. Use the '{nameof(Diagnostic)}(DiagnosticDescriptor)' overload to specify the descriptor from which to create the expected result.",
                ex);
        }
    }
    
    public static DiagnosticResult Diagnostic(DiagnosticDescriptor descriptor) => new DiagnosticResult(descriptor);

    public static Task VerifyAnalyzerAsync(string source, Action<TTest>? configure = default, params DiagnosticResult[] expected)
    {
        var test = new TTest
        {
            TestCode = source,
        };

        test.ExpectedDiagnostics.AddRange(expected);
        configure?.Invoke(test);
        
        return test.RunAsync(CancellationToken.None);
    }
}
Dbl
  • 5,634
  • 3
  • 41
  • 66