diff --git a/test/MapTo.Tests/Extensions/RoslynExtensions.cs b/test/MapTo.Tests/Extensions/RoslynExtensions.cs new file mode 100644 index 0000000..1c4cc91 --- /dev/null +++ b/test/MapTo.Tests/Extensions/RoslynExtensions.cs @@ -0,0 +1,39 @@ +using System; +using System.Linq; +using System.Text; +using Microsoft.CodeAnalysis; + +namespace MapTo.Tests.Extensions +{ + internal static class RoslynExtensions + { + internal static string PrintSyntaxTree(this Compilation compilation) + { + var builder = new StringBuilder(); + + return string.Join( + Environment.NewLine, + compilation.SyntaxTrees + .Reverse() + .Select((s, i) => + { + builder + .Clear() + .AppendLine("----------------------------------------") + .AppendFormat("File Path: \"{0}\"", s.FilePath).AppendLine() + .AppendFormat("Index: \"{0}\"", i).AppendLine() + .AppendLine(); + + var lines = s.ToString().Split(Environment.NewLine); + var lineNumber = 1; + foreach (var line in lines) + { + builder.AppendFormat("{0:00}: {1}", lineNumber, line).AppendLine(); + lineNumber++; + } + + return builder.ToString(); + })); + } + } +} \ No newline at end of file diff --git a/test/MapTo.Tests/Extensions/ShouldlyExtensions.cs b/test/MapTo.Tests/Extensions/ShouldlyExtensions.cs index 03df91d..bf8114e 100644 --- a/test/MapTo.Tests/Extensions/ShouldlyExtensions.cs +++ b/test/MapTo.Tests/Extensions/ShouldlyExtensions.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Shouldly; using Xunit; @@ -20,10 +21,32 @@ namespace MapTo.Tests.Extensions syntax.ShouldBe(expectedSource, customMessage); } - internal static void ShouldBeSuccessful(this IEnumerable diagnostics, DiagnosticSeverity severity = DiagnosticSeverity.Warning) + internal static void ShouldBeSuccessful(this IEnumerable diagnostics, Compilation compilation = null) { - var actual = diagnostics.Where(d => d.Severity >= severity).Select(c => $"{c.Severity}: {c.Location.GetLineSpan().StartLinePosition} - {c.GetMessage()}").ToArray(); - Assert.False(actual.Any(), $"Failed: {Environment.NewLine}{string.Join(Environment.NewLine, actual.Select(c => $"- {c}"))}"); + var actual = diagnostics + .Where(d => !d.Id.StartsWith("MT") && (d.Severity == DiagnosticSeverity.Warning || d.Severity == DiagnosticSeverity.Error)) + .Select(c => $"{c.Severity}: {c.Location.GetLineSpan()} - {c.GetMessage()}").ToArray(); + + if (!actual.Any()) + { + return; + } + + var builder = new StringBuilder(); + builder.AppendLine("Failed"); + + foreach (var d in actual) + { + builder.AppendFormat("- {0}", d).AppendLine(); + } + + if (compilation is not null) + { + builder.AppendLine("Generated Sources:"); + builder.AppendLine(compilation.PrintSyntaxTree()); + } + + Assert.False(true, builder.ToString()); } internal static void ShouldBeUnsuccessful(this ImmutableArray diagnostics, Diagnostic expectedError) diff --git a/test/MapTo.Tests/Infrastructure/CSharpGenerator.cs b/test/MapTo.Tests/Infrastructure/CSharpGenerator.cs index cd6c22c..1786c95 100644 --- a/test/MapTo.Tests/Infrastructure/CSharpGenerator.cs +++ b/test/MapTo.Tests/Infrastructure/CSharpGenerator.cs @@ -11,17 +11,19 @@ namespace MapTo.Tests.Infrastructure { internal static class CSharpGenerator { - internal static (Compilation compilation, ImmutableArray diagnostics) GetOutputCompilation(string source, bool assertCompilation = false, IDictionary analyzerConfigOptions = null, NullableContextOptions nullableContextOptions = NullableContextOptions.Disable) + internal static (Compilation compilation, ImmutableArray diagnostics) GetOutputCompilation(string source, bool assertCompilation = false, IDictionary analyzerConfigOptions = null, NullableContextOptions nullableContextOptions = NullableContextOptions.Disable) => + GetOutputCompilation(new[] { source }, assertCompilation, analyzerConfigOptions, nullableContextOptions); + + internal static (Compilation compilation, ImmutableArray diagnostics) GetOutputCompilation(IEnumerable sources, bool assertCompilation = false, IDictionary analyzerConfigOptions = null, NullableContextOptions nullableContextOptions = NullableContextOptions.Disable) { - var syntaxTree = CSharpSyntaxTree.ParseText(source); var references = AppDomain.CurrentDomain.GetAssemblies() .Where(a => !a.IsDynamic && !string.IsNullOrWhiteSpace(a.Location)) .Select(a => MetadataReference.CreateFromFile(a.Location)) .ToList(); - + var compilation = CSharpCompilation.Create( $"{typeof(CSharpGenerator).Assembly.GetName().Name}.Dynamic", - new[] { syntaxTree }, + sources.Select((source, index) => CSharpSyntaxTree.ParseText(source, path: $"Test{index:00}.g.cs")), references, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, nullableContextOptions: nullableContextOptions)); @@ -37,20 +39,9 @@ namespace MapTo.Tests.Infrastructure ); driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out var generateDiagnostics); - - var diagnostics = outputCompilation.GetDiagnostics() - .Where(d => d.Severity >= DiagnosticSeverity.Warning) - .Select(c => $"{c.Severity}: {c.Location.GetLineSpan().StartLinePosition} - {c.GetMessage()} [in \"{c.Location.SourceTree?.FilePath}\"]").ToArray(); - - if (diagnostics.Any()) - { - Assert.False(diagnostics.Any(), $@"Failed: -{string.Join(Environment.NewLine, diagnostics.Select(c => $"- {c}"))} - -Generated Sources: -{string.Join(Environment.NewLine, outputCompilation.SyntaxTrees.Reverse().Select(s => $"----------------------------------------{Environment.NewLine}File Path: \"{s.FilePath}\"{Environment.NewLine}{s}"))} -"); - } + + generateDiagnostics.ShouldBeSuccessful(); + outputCompilation.GetDiagnostics().ShouldBeSuccessful(outputCompilation); return (outputCompilation, generateDiagnostics); }