From dd5a4dfb895ce574701710a06b3083b991d2e7b4 Mon Sep 17 00:00:00 2001 From: Jean-Sebastien Carle <29762210+jscarle@users.noreply.github.com> Date: Sat, 20 Jun 2026 15:27:19 -0400 Subject: [PATCH 1/2] Changed base target frameworks. --- .../SourceGeneratorTestHelpers.csproj | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/SourceGeneratorTestHelpers/SourceGeneratorTestHelpers.csproj b/src/SourceGeneratorTestHelpers/SourceGeneratorTestHelpers.csproj index dbed528..4251a5f 100644 --- a/src/SourceGeneratorTestHelpers/SourceGeneratorTestHelpers.csproj +++ b/src/SourceGeneratorTestHelpers/SourceGeneratorTestHelpers.csproj @@ -1,7 +1,7 @@ - netstandard2.0;net6.0;net7.0;net8.0;net9.0;net10.0 + net8.0;net9.0;net10.0 enable enable SourceGeneratorTestHelpers @@ -38,13 +38,13 @@ - + + - True \ @@ -56,8 +56,10 @@ False + true true + From 1060b3d0158c7a54d0aa394a42d6e5c3f80d51b9 Mon Sep 17 00:00:00 2001 From: Jean-Sebastien Carle <29762210+jscarle@users.noreply.github.com> Date: Sat, 20 Jun 2026 15:39:43 -0400 Subject: [PATCH 2/2] Added support for enumerable sources. --- README.md | 40 +++++++++++++++---- .../GeneratorDriverTestBase.cs | 2 +- .../Common/Helpers.cs | 32 +++++++++++---- .../IncrementalGenerator.cs | 40 +++++++++++-------- .../SourceGenerator.cs | 34 +++++++++------- .../SourceGeneratorTestHelpers.csproj | 8 ++-- 6 files changed, 104 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index 59742a5..024e101 100644 --- a/README.md +++ b/README.md @@ -9,13 +9,37 @@ Test helpers and extension methods to simplify testing of .NET source generators ## Testing a source generator ```csharp -var result = SourceGenerator.Run("your source"); +var (generator, result) = SourceGenerator.Run("your source"); +``` + +You can also run a generator against multiple source files by passing any `IEnumerable`. + +```csharp +var sources = new[] +{ + "namespace Tests; public partial class First;", + "namespace Tests; public partial class Second;" +}; + +var (generator, result) = SourceGenerator.Run(sources); ``` ## Testing an incremental source generator ```csharp -var result = IncrementalGenerator.Run("your source"); +var (generator, result) = IncrementalGenerator.Run("your source"); +``` + +The same multiple-source overload is available for incremental generators. + +```csharp +var sources = new[] +{ + "namespace Tests; public partial class First;", + "namespace Tests; public partial class Second;" +}; + +var (generator, result) = IncrementalGenerator.Run(sources); ``` ## Obtaining the generated source @@ -50,7 +74,7 @@ Using one of the testing framework packages below, you can also assert the diffe [![MSTest](https://img.shields.io/nuget/dt/SourceGeneratorTestHelpers.MSTest?label=MSTest)](https://www.nuget.org/packages/SourceGeneratorTestHelpers.MSTest) ```csharp -var result = IncrementalGenerator.Run("your source"); +var (_, result) = IncrementalGenerator.Run("your source"); result.ShouldProduce("TestId.g.cs", "expected source"); ``` @@ -58,7 +82,7 @@ result.ShouldProduce("TestId.g.cs", "expected source"); _Note: If you do not wish to assert on errors produced during diagnostics of the source generator run, you can simply disable them as such._ ```csharp -var result = IncrementalGenerator.Run("your source"); +var (_, result) = IncrementalGenerator.Run("your source"); result.ShouldProduce("TestId.g.cs", "expected source", false); ``` @@ -75,7 +99,7 @@ public class SourceGeneratorTests [Fact] public Task ShouldProductTestId() { - var result = IncrementalGenerator.Run("your source"); + var (_, result) = IncrementalGenerator.Run("your source"); return result.VerifyAsync("TestId.g.cs"); } } @@ -90,7 +114,7 @@ public class SourceGeneratorTests [Test] public Task ShouldProductTestId() { - var result = IncrementalGenerator.Run("your source"); + var (_, result) = IncrementalGenerator.Run("your source"); return result.VerifyAsync("TestId.g.cs"); } } @@ -106,8 +130,8 @@ public class SourceGeneratorTests : [TestMethod] public Task ShouldProductTestId() { - var result = IncrementalGenerator.Run("your source"); - return VerifyAsync("TestId.g.cs"); + var (_, result) = IncrementalGenerator.Run("your source"); + return VerifyAsync(result, "TestId.g.cs"); } } ``` diff --git a/src/SourceGeneratorTestHelpers.MSTest/GeneratorDriverTestBase.cs b/src/SourceGeneratorTestHelpers.MSTest/GeneratorDriverTestBase.cs index b8ba9a5..c657c2e 100644 --- a/src/SourceGeneratorTestHelpers.MSTest/GeneratorDriverTestBase.cs +++ b/src/SourceGeneratorTestHelpers.MSTest/GeneratorDriverTestBase.cs @@ -5,7 +5,7 @@ namespace SourceGeneratorTestHelpers.MSTest; -internal abstract class GeneratorDriverTestBase : VerifyBase +public abstract class GeneratorDriverTestBase : VerifyBase { /// Verifies that the generated source from a with a specific file path ending matches the expected source. /// The to get the source from. diff --git a/src/SourceGeneratorTestHelpers/Common/Helpers.cs b/src/SourceGeneratorTestHelpers/Common/Helpers.cs index 6c7fb55..489b7d5 100644 --- a/src/SourceGeneratorTestHelpers/Common/Helpers.cs +++ b/src/SourceGeneratorTestHelpers/Common/Helpers.cs @@ -22,9 +22,10 @@ internal static (ImmutableArray CompilationDiagnostics, GeneratorDri CSharpCompilationOptions? cSharpCompilationOptions ) { - var sources = new[] { source }; + cSharpParseOptions ??= DefaultCSharpParseOptions; + var syntaxTrees = new[] { CSharpSyntaxTree.ParseText(source, cSharpParseOptions, encoding: Encoding.UTF8) }; - return InternalRunGenerator(generator, sources, cSharpParseOptions, metadataReferences, cSharpCompilationOptions); + return InternalRunGenerator(generator, syntaxTrees, cSharpParseOptions, metadataReferences, cSharpCompilationOptions); } internal static (ImmutableArray CompilationDiagnostics, GeneratorDriverRunResult Result) InternalRunGenerator( @@ -35,8 +36,20 @@ internal static (ImmutableArray CompilationDiagnostics, GeneratorDri CSharpCompilationOptions? cSharpCompilationOptions ) { - var syntaxTrees = sources.Select(source => CSharpSyntaxTree.ParseText(source, cSharpParseOptions, encoding: Encoding.UTF8)).ToArray(); cSharpParseOptions ??= DefaultCSharpParseOptions; + var syntaxTrees = sources.Select(source => CSharpSyntaxTree.ParseText(source, cSharpParseOptions, encoding: Encoding.UTF8)).ToArray(); + + return InternalRunGenerator(generator, syntaxTrees, cSharpParseOptions, metadataReferences, cSharpCompilationOptions); + } + + private static (ImmutableArray CompilationDiagnostics, GeneratorDriverRunResult Result) InternalRunGenerator( + ISourceGenerator generator, + SyntaxTree[] syntaxTrees, + CSharpParseOptions cSharpParseOptions, + IEnumerable? metadataReferences, + CSharpCompilationOptions? cSharpCompilationOptions + ) + { metadataReferences ??= DefaultMetadataReferences; cSharpCompilationOptions ??= DefaultCSharpCompilationOptions; @@ -97,11 +110,14 @@ Action assertAction internal static GeneratedSource? InternalGetSource(this GeneratorDriverRunResult result, string filePathEndsWith) { - var sources = InternalGetSources(result); - - var matchingSources = sources.Where(x => x.FilePath.EndsWith(filePathEndsWith, StringComparison.InvariantCultureIgnoreCase)).ToList(); - - return matchingSources.Count == 0 ? null : matchingSources[0]; + foreach (var generatedTree in result.GeneratedTrees) + { + var source = GetGeneratedSource(generatedTree); + if (source.FilePath.EndsWith(filePathEndsWith, StringComparison.InvariantCultureIgnoreCase)) + return source; + } + + return null; } internal static ImmutableList InternalGetSources(this GeneratorDriverRunResult result) diff --git a/src/SourceGeneratorTestHelpers/IncrementalGenerator.cs b/src/SourceGeneratorTestHelpers/IncrementalGenerator.cs index 67bf779..c6fb083 100644 --- a/src/SourceGeneratorTestHelpers/IncrementalGenerator.cs +++ b/src/SourceGeneratorTestHelpers/IncrementalGenerator.cs @@ -17,8 +17,8 @@ public static class IncrementalGenerator /// The C# compilation options to compile with. By default, Output will be set to library, and Nullable will be set to /// enable. /// - /// The results of the execution. - public static GeneratorDriverRunResult Run( + /// The generator instance used for the run and the result of the execution. + public static (T Generator, GeneratorDriverRunResult Result) Run( string source, CSharpParseOptions? cSharpParseOptions = null, IEnumerable? metadataReferences = null, @@ -26,9 +26,11 @@ public static GeneratorDriverRunResult Run( ) where T : IIncrementalGenerator, new() { - var generator = new T().AsSourceGenerator(); + var generator = new T(); + var sourceGenerator = generator.AsSourceGenerator(); + var result = Helpers.InternalRunGenerator(sourceGenerator, source, cSharpParseOptions, metadataReferences, cSharpCompilationOptions).Result; - return Helpers.InternalRunGenerator(generator, source, cSharpParseOptions, metadataReferences, cSharpCompilationOptions).Result; + return (generator, result); } /// Gather compilation diagnostics and executes a specified against the provided sources within a testing environment. @@ -40,8 +42,8 @@ public static GeneratorDriverRunResult Run( /// The C# compilation options to compile with. By default, Output will be set to library, and Nullable will be set to /// enable. /// - /// The compilation diagnostics and the result of the execution. - public static (ImmutableArray Diagnostics, GeneratorDriverRunResult Result) RunWithDiagnostics( + /// The generator instance used for the run, the result of the execution, and the compilation diagnostics. + public static (T Generator, GeneratorDriverRunResult Result, ImmutableArray Diagnostics) RunWithDiagnostics( string source, CSharpParseOptions? cSharpParseOptions = null, IEnumerable? metadataReferences = null, @@ -49,9 +51,11 @@ public static (ImmutableArray Diagnostics, GeneratorDriverRunResult ) where T : IIncrementalGenerator, new() { - var generator = new T().AsSourceGenerator(); + var generator = new T(); + var sourceGenerator = generator.AsSourceGenerator(); + var result = Helpers.InternalRunGenerator(sourceGenerator, source, cSharpParseOptions, metadataReferences, cSharpCompilationOptions); - return Helpers.InternalRunGenerator(generator, source, cSharpParseOptions, metadataReferences, cSharpCompilationOptions); + return (generator, result.Result, result.CompilationDiagnostics); } /// Executes a specified against the provided sources within a testing environment. @@ -63,8 +67,8 @@ public static (ImmutableArray Diagnostics, GeneratorDriverRunResult /// The C# compilation options to compile with. By default, Output will be set to library, and Nullable will be set to /// enable. /// - /// The result of the execution. - public static GeneratorDriverRunResult Run( + /// The generator instance used for the run and the result of the execution. + public static (T Generator, GeneratorDriverRunResult Result) Run( IEnumerable sources, CSharpParseOptions? cSharpParseOptions = null, IEnumerable? metadataReferences = null, @@ -72,9 +76,11 @@ public static GeneratorDriverRunResult Run( ) where T : IIncrementalGenerator, new() { - var generator = new T().AsSourceGenerator(); + var generator = new T(); + var sourceGenerator = generator.AsSourceGenerator(); + var result = Helpers.InternalRunGenerator(sourceGenerator, sources, cSharpParseOptions, metadataReferences, cSharpCompilationOptions).Result; - return Helpers.InternalRunGenerator(generator, sources, cSharpParseOptions, metadataReferences, cSharpCompilationOptions).Result; + return (generator, result); } /// Gather compilation diagnostics and executes a specified against the provided sources within a testing environment. @@ -86,8 +92,8 @@ public static GeneratorDriverRunResult Run( /// The C# compilation options to compile with. By default, Output will be set to library, and Nullable will be set to /// enable. /// - /// The compilation diagnostics and the result of the execution. - public static (ImmutableArray Diagnostics, GeneratorDriverRunResult Result) RunWithDiagnostics( + /// The generator instance used for the run, the result of the execution, and the compilation diagnostics. + public static (T Generator, GeneratorDriverRunResult Result, ImmutableArray Diagnostics) RunWithDiagnostics( IEnumerable sources, CSharpParseOptions? cSharpParseOptions = null, IEnumerable? metadataReferences = null, @@ -95,8 +101,10 @@ public static (ImmutableArray Diagnostics, GeneratorDriverRunResult ) where T : IIncrementalGenerator, new() { - var generator = new T().AsSourceGenerator(); + var generator = new T(); + var sourceGenerator = generator.AsSourceGenerator(); + var result = Helpers.InternalRunGenerator(sourceGenerator, sources, cSharpParseOptions, metadataReferences, cSharpCompilationOptions); - return Helpers.InternalRunGenerator(generator, sources, cSharpParseOptions, metadataReferences, cSharpCompilationOptions); + return (generator, result.Result, result.CompilationDiagnostics); } } diff --git a/src/SourceGeneratorTestHelpers/SourceGenerator.cs b/src/SourceGeneratorTestHelpers/SourceGenerator.cs index 66f622d..199b3d5 100644 --- a/src/SourceGeneratorTestHelpers/SourceGenerator.cs +++ b/src/SourceGeneratorTestHelpers/SourceGenerator.cs @@ -1,4 +1,4 @@ -using System.Collections.Immutable; +using System.Collections.Immutable; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using SourceGeneratorTestHelpers.Common; @@ -17,8 +17,8 @@ public static class SourceGenerator /// The C# compilation options to compile with. By default, Output will be set to library, and Nullable will be set to /// enable. /// - /// The results of the execution. - public static GeneratorDriverRunResult Run( + /// The generator instance used for the run and the result of the execution. + public static (T Generator, GeneratorDriverRunResult Result) Run( string source, CSharpParseOptions? cSharpParseOptions = null, IEnumerable? metadataReferences = null, @@ -27,8 +27,9 @@ public static GeneratorDriverRunResult Run( where T : ISourceGenerator, new() { var generator = new T(); + var result = Helpers.InternalRunGenerator(generator, source, cSharpParseOptions, metadataReferences, cSharpCompilationOptions).Result; - return Helpers.InternalRunGenerator(generator, source, cSharpParseOptions, metadataReferences, cSharpCompilationOptions).Result; + return (generator, result); } /// Gather compilation diagnostics and executes a specified against the provided source within a testing environment. @@ -40,8 +41,8 @@ public static GeneratorDriverRunResult Run( /// The C# compilation options to compile with. By default, Output will be set to library, and Nullable will be set to /// enable. /// - /// The compilation diagnostics and the result of the execution. - public static (ImmutableArray Diagnostics, GeneratorDriverRunResult Result) RunWithDiagnostics( + /// The generator instance used for the run, the result of the execution, and the compilation diagnostics. + public static (T Generator, GeneratorDriverRunResult Result, ImmutableArray Diagnostics) RunWithDiagnostics( string source, CSharpParseOptions? cSharpParseOptions = null, IEnumerable? metadataReferences = null, @@ -50,11 +51,12 @@ public static (ImmutableArray Diagnostics, GeneratorDriverRunResult where T : ISourceGenerator, new() { var generator = new T(); + var result = Helpers.InternalRunGenerator(generator, source, cSharpParseOptions, metadataReferences, cSharpCompilationOptions); - return Helpers.InternalRunGenerator(generator, source, cSharpParseOptions, metadataReferences, cSharpCompilationOptions); + return (generator, result.Result, result.CompilationDiagnostics); } - /// Executes a specified against the provided source within a testing environment. + /// Executes a specified against the provided sources within a testing environment. /// The type of to execute. /// The sources to be analyzed and processed by the . /// The C# source parsing options to compile with. By default, LangVersion will be set to latest. @@ -63,8 +65,8 @@ public static (ImmutableArray Diagnostics, GeneratorDriverRunResult /// The C# compilation options to compile with. By default, Output will be set to library, and Nullable will be set to /// enable. /// - /// The result of the execution. - public static GeneratorDriverRunResult Run( + /// The generator instance used for the run and the result of the execution. + public static (T Generator, GeneratorDriverRunResult Result) Run( IEnumerable sources, CSharpParseOptions? cSharpParseOptions = null, IEnumerable? metadataReferences = null, @@ -73,11 +75,12 @@ public static GeneratorDriverRunResult Run( where T : ISourceGenerator, new() { var generator = new T(); + var result = Helpers.InternalRunGenerator(generator, sources, cSharpParseOptions, metadataReferences, cSharpCompilationOptions).Result; - return Helpers.InternalRunGenerator(generator, sources, cSharpParseOptions, metadataReferences, cSharpCompilationOptions).Result; + return (generator, result); } - /// Gather compilation diagnostics and executes a specified against the provided source within a testing environment. + /// Gather compilation diagnostics and executes a specified against the provided sources within a testing environment. /// The type of to execute. /// The sources to be analyzed and processed by the . /// The C# source parsing options to compile with. By default, LangVersion will be set to latest. @@ -86,8 +89,8 @@ public static GeneratorDriverRunResult Run( /// The C# compilation options to compile with. By default, Output will be set to library, and Nullable will be set to /// enable. /// - /// The compilation diagnostics and the result of the execution. - public static (ImmutableArray Diagnostics, GeneratorDriverRunResult Result) RunWithDiagnostics( + /// The generator instance used for the run, the result of the execution, and the compilation diagnostics. + public static (T Generator, GeneratorDriverRunResult Result, ImmutableArray Diagnostics) RunWithDiagnostics( IEnumerable sources, CSharpParseOptions? cSharpParseOptions = null, IEnumerable? metadataReferences = null, @@ -96,7 +99,8 @@ public static (ImmutableArray Diagnostics, GeneratorDriverRunResult where T : ISourceGenerator, new() { var generator = new T(); + var result = Helpers.InternalRunGenerator(generator, sources, cSharpParseOptions, metadataReferences, cSharpCompilationOptions); - return Helpers.InternalRunGenerator(generator, sources, cSharpParseOptions, metadataReferences, cSharpCompilationOptions); + return (generator, result.Result, result.CompilationDiagnostics); } } diff --git a/src/SourceGeneratorTestHelpers/SourceGeneratorTestHelpers.csproj b/src/SourceGeneratorTestHelpers/SourceGeneratorTestHelpers.csproj index 4251a5f..7d083e2 100644 --- a/src/SourceGeneratorTestHelpers/SourceGeneratorTestHelpers.csproj +++ b/src/SourceGeneratorTestHelpers/SourceGeneratorTestHelpers.csproj @@ -6,7 +6,7 @@ enable SourceGeneratorTestHelpers latest - 10.0.1 + 10.1.0 SourceGeneratorTestHelpers Jean-Sebastien Carle Test helpers and extension methods to simplify testing of .NET source generators. @@ -18,8 +18,8 @@ https://github.com/jscarle/SourceGeneratorTestHelpers git testing source-generators - 10.0.1.0 - 10.0.1.0 + 10.1.0.0 + 10.1.0.0 en-US true snupkg @@ -38,7 +38,7 @@ - +