diff --git a/README.md b/README.md
index 7673549..c702437 100644
--- a/README.md
+++ b/README.md
@@ -208,6 +208,35 @@ public class MyGenerator : IncrementalGenerator
}
```
+## Unit Tests
+You can write unit test to validate that your source generators are working as expected. To do this for this library requires a very tiny amount of extra work. You can also look at the [example project](src\Sandbox\ConsoleApp.SourceGenerator.Tests\TestCase.cs) to see how it works.
+
+The generated class will all be internal so your unit test assembly will need to have viability.
+
+```csharp
+using System.Runtime.CompilerServices;
+
+[assembly: InternalsVisibleTo("ConsoleApp.SourceGenerator.Tests")]
+```
+
+Then for your unit test functions the only difference will be that instead of creating an instance of your class you create an instance of the `Hoist` class.
+
+```c#
+// Create the instance of our generator and set whatever properties
+ConsoleAppSourceGenerator generator = new ConsoleAppSourceGenerator()
+{
+ Explode = true
+};
+// Build the instance of the wrapper `Host` which takes in your generator.
+ConsoleAppSourceGeneratorHoist host = new
+
+// From here it's just like testing any other generator
+ConsoleAppSourceGeneratorHoist(generator);
+GeneratorDriver driver = CSharpGeneratorDriver.Create(host);
+driver = driver.RunGenerators(compilation);
+```
+The only unique feature is the wrapper class `{YourGeneratorName}Host`. This class is an internal feature of `SGF` and is used to make sure all dependencies are resolved before calling into your source generator.
+
## Project Layout
This library is made up of quite a few different components leveraging various techniques to help
diff --git a/src/Sandbox/ConsoleApp.SourceGenerator.Tests/ConsoleApp.SourceGenerator.Tests.csproj b/src/Sandbox/ConsoleApp.SourceGenerator.Tests/ConsoleApp.SourceGenerator.Tests.csproj
new file mode 100644
index 0000000..10f6dd1
--- /dev/null
+++ b/src/Sandbox/ConsoleApp.SourceGenerator.Tests/ConsoleApp.SourceGenerator.Tests.csproj
@@ -0,0 +1,28 @@
+
+
+
+ net8.0
+ enable
+ enable
+ 12
+
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Sandbox/ConsoleApp.SourceGenerator.Tests/TestCase.cs b/src/Sandbox/ConsoleApp.SourceGenerator.Tests/TestCase.cs
new file mode 100644
index 0000000..5da446e
--- /dev/null
+++ b/src/Sandbox/ConsoleApp.SourceGenerator.Tests/TestCase.cs
@@ -0,0 +1,47 @@
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+
+namespace ConsoleApp.SourceGenerator.Tests
+{
+ public class TestCase
+ {
+ [Fact]
+ public void Compiles()
+ {
+ Compose("""
+ namespace MyNamespace
+ {
+ public class MyClass
+ {
+ }
+ }
+ """);
+ }
+
+
+ private void Compose(string source)
+ {
+ // Create the generator, you can pass any parameters you want
+ ConsoleAppSourceGenerator generator = new ConsoleAppSourceGenerator()
+ {
+ WarningMessage = "I am running from a unit test!" // Change any settings you want
+ };
+ // Create the 'host' which is the wrapper that is auto generated by SGF.
+ ConsoleAppSourceGeneratorHoist host = new ConsoleAppSourceGeneratorHoist(generator);
+ // Parse the source into syntax trees
+ SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(source);
+ // Setup the compilation settings
+ CSharpCompilation compilation = CSharpCompilation.Create(
+ assemblyName: "UniTests",
+ syntaxTrees: new[] { syntaxTree });
+ // Create the driver the executes the generator
+ GeneratorDriver driver = CSharpGeneratorDriver.Create(host);
+ // Run it
+ driver = driver.RunGenerators(compilation);
+ // Get the results
+ GeneratorDriverRunResult results = driver.GetRunResult();
+ // Test the results
+ Assert.NotEmpty(results.GeneratedTrees);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Sandbox/ConsoleApp.SourceGenerator/AssemblyInfo.cs b/src/Sandbox/ConsoleApp.SourceGenerator/AssemblyInfo.cs
new file mode 100644
index 0000000..b8821c7
--- /dev/null
+++ b/src/Sandbox/ConsoleApp.SourceGenerator/AssemblyInfo.cs
@@ -0,0 +1,3 @@
+using System.Runtime.CompilerServices;
+
+[assembly: InternalsVisibleTo("ConsoleApp.SourceGenerator.Tests")]
\ No newline at end of file
diff --git a/src/Sandbox/ConsoleApp.SourceGenerator/ConsoleAppSourceGenerator.cs b/src/Sandbox/ConsoleApp.SourceGenerator/ConsoleAppSourceGenerator.cs
index 89e56b2..62da2f9 100644
--- a/src/Sandbox/ConsoleApp.SourceGenerator/ConsoleAppSourceGenerator.cs
+++ b/src/Sandbox/ConsoleApp.SourceGenerator/ConsoleAppSourceGenerator.cs
@@ -16,9 +16,11 @@ public class Payload
public string? Version { get; set; }
}
+ public string WarningMessage { get; set; }
+
public ConsoleAppSourceGenerator() : base("ConsoleAppSourceGenerator")
{
-
+ WarningMessage = "Warnigs show up in the 'Build' pane along with the 'Source Generators' pane";
}
public override void OnInitialize(SgfInitializationContext context)
@@ -29,7 +31,7 @@ public override void OnInitialize(SgfInitializationContext context)
Version = "13.0.1"
};
- Logger.Warning("Warnigs show up in the 'Build' pane along with the 'Source Generators' pane");
+ Logger.Warning(WarningMessage);
Logger.Information("This is the output from the sournce generator assembly ConsoleApp.SourceGenerator");
Logger.Information("This generator references Newtonsoft.Json and it can just be referenced without any other boilerplate");
Logger.Information(JsonConvert.SerializeObject(payload));
diff --git a/src/SourceGenerator.Foundations.sln b/src/SourceGenerator.Foundations.sln
index 7c4d601..f2a2f21 100644
--- a/src/SourceGenerator.Foundations.sln
+++ b/src/SourceGenerator.Foundations.sln
@@ -31,6 +31,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Scripts", "Scripts", "{F012
EndProject
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "SourceGenerator.Foundations.Shared", "SourceGenerator.Foundations.Shared\SourceGenerator.Foundations.Shared.shproj", "{8AF3630C-2BF5-4854-A45D-0074C2787964}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleApp.SourceGenerator.Tests", "Sandbox\ConsoleApp.SourceGenerator.Tests\ConsoleApp.SourceGenerator.Tests.csproj", "{560C8028-2831-4697-9571-A9920FB972E7}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -87,6 +89,14 @@ Global
{E95587D6-78E8-48FE-9F98-371800A77B69}.Release|Any CPU.Build.0 = Release|Any CPU
{E95587D6-78E8-48FE-9F98-371800A77B69}.Release|x64.ActiveCfg = Release|Any CPU
{E95587D6-78E8-48FE-9F98-371800A77B69}.Release|x64.Build.0 = Release|Any CPU
+ {560C8028-2831-4697-9571-A9920FB972E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {560C8028-2831-4697-9571-A9920FB972E7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {560C8028-2831-4697-9571-A9920FB972E7}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {560C8028-2831-4697-9571-A9920FB972E7}.Debug|x64.Build.0 = Debug|Any CPU
+ {560C8028-2831-4697-9571-A9920FB972E7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {560C8028-2831-4697-9571-A9920FB972E7}.Release|Any CPU.Build.0 = Release|Any CPU
+ {560C8028-2831-4697-9571-A9920FB972E7}.Release|x64.ActiveCfg = Release|Any CPU
+ {560C8028-2831-4697-9571-A9920FB972E7}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -95,6 +105,7 @@ Global
{DC8C5A1A-6269-4BA7-852A-D21CB0B2B5A0} = {A651676B-FBDB-4710-B010-D05AF3A56084}
{F4BA95B9-0353-44CA-9502-C74B532321B7} = {6118BF32-23BA-4D33-946E-F7E8A6F5D758}
{594AACB5-B550-46CF-B6E2-16EF826D655A} = {6118BF32-23BA-4D33-946E-F7E8A6F5D758}
+ {560C8028-2831-4697-9571-A9920FB972E7} = {6118BF32-23BA-4D33-946E-F7E8A6F5D758}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {EDB10920-970A-43F9-A2B3-7F1270DD477B}
diff --git a/src/SourceGenerator.Foundations/Templates/SourceGeneratorHostImpl.cs b/src/SourceGenerator.Foundations/Templates/SourceGeneratorHostImpl.cs
index d889bdf..543d42d 100644
--- a/src/SourceGenerator.Foundations/Templates/SourceGeneratorHostImpl.cs
+++ b/src/SourceGenerator.Foundations/Templates/SourceGeneratorHostImpl.cs
@@ -24,11 +24,23 @@ namespace {{dataModel.Namespace}}
internal class {{dataModel.ClassName}}Hoist : SourceGeneratorHoist, IIncrementalGenerator
{
// Has to be untyped otherwise it will try to resolve at startup
- private object? m_generator;
+ private Lazy