I'm writing a source generator (IIncrementalGenerator to be specific) and I want to make sure that the caching is correctly responding to changes in the source code.
- Run the source generator
- Assert that certain internal stages are outputting the correct data
- Change the
Compilationto modify the code that the source generator is listening for - Assert that certain stages have a
ModifiedorNewstate for the run reason (and that the data itself is correct)
This would show that the generator is responsive to changes in the source code, otherwise I'm limited to just testing that the generator creates correct source code in the initial compile, not follow up changes.
Here is the core code that I've got for running the generator over multiple iterations:
public static IReadOnlyList<GeneratorDriverRunResult> RunGeneratorIterations<T>(T generator, params Compilation[] codeIterations)
where T : IIncrementalGenerator
{
GeneratorDriverOptions driverOptions = new(IncrementalGeneratorOutputKind.None, true);
ISourceGenerator[] generators = { generator.AsSourceGenerator() };
GeneratorDriver driver = CSharpGeneratorDriver.Create(generators, driverOptions: driverOptions);
List<GeneratorDriverRunResult> runResults = new();
// Run the generation pass
driver = driver.RunGeneratorsAndUpdateCompilation(codeIterations[0], out _, out _);
runResults.Add(driver.GetRunResult());
for (int i = 1; i < codeIterations.Length; i++)
{
driver = driver.RunGenerators(codeIterations[i], CancellationToken.None);
runResults.Add(driver.GetRunResult());
}
Assert.AreEqual(codeIterations.Length, runResults.Count);
return runResults;
}
The issue with this is that when I run tests using the above code itt throws an exception in the second driver.RunGenerators call:
Unexpected value '(Modified, Added)' of type 'System.ValueTuple'2[[Microsoft.CodeAnalysis.EntryState, Microsoft.CodeAnalysis.EntryState]]
This tells me that I'm not setting up the next compile pass correctly, How do I run a source generator with incrementally changing source code in unit tests?
Small update on this:
It seems that if I tell driverOptions not to track the generator stages it doesn't crash... but I then can't inspect the actual data in my unit test. I'm beginning to think I'm fighting a compiler bug.