What's wrong
GeneratorHarness.ReusesCachedOutputOnRerun (SourceGeneratorToolkit.Testing/GeneratorHarness.cs:~102-127) runs the driver twice against the same CSharpCompilation instance, with the same AdditionalText instances. Roslyn compares incremental inputs by reference, so on the second run every node, CompilationProvider included, is reported as Cached/Unchanged whatever the generator does.
The doc comment says the check exists to catch "a generator that recomputes everything on every keystroke". A keystroke produces a new Compilation, and this check never creates one, so it cannot detect that. TheGeneratorReusesItsOutputWhenNothingChanged (GeneratorBaseTests.cs:203) therefore asserts nothing meaningful.
Reproduction (ran)
The generator below is non-incremental by construction:
context.RegisterSourceOutput(
context.CompilationProvider.Select((c, _) => new object()),
(spc, _) => spc.AddSource("x.g.cs", "// x"));
ReusesCachedOutputOnRerun(generator) returns true. Expected false.
- For comparison, running it on
c1 and then on c1.AddSyntaxTrees(CSharpSyntaxTree.ParseText("")) reports the output step as Modified.
Why it matters
This is a test helper that consumers rely on to prove their generators are incremental. A check that always passes gives false confidence and lets IDE-performance regressions ship.
Suggested fix / acceptance criteria
- Run the second pass on a new but semantically equivalent compilation, for example
compilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(string.Empty)) or compilation.WithAssemblyName(compilation.AssemblyName). Ideally also rebuild the AdditionalText instances with identical content, as an IDE does.
- Treat "no tracked output steps" as not proven (
false, or throw) rather than true.
- Add a negative test: the
CompilationProvider.Select(_ => new object()) generator above must fail the check.
What's wrong
GeneratorHarness.ReusesCachedOutputOnRerun(SourceGeneratorToolkit.Testing/GeneratorHarness.cs:~102-127) runs the driver twice against the sameCSharpCompilationinstance, with the sameAdditionalTextinstances. Roslyn compares incremental inputs by reference, so on the second run every node,CompilationProviderincluded, is reported asCached/Unchangedwhatever the generator does.The doc comment says the check exists to catch "a generator that recomputes everything on every keystroke". A keystroke produces a new
Compilation, and this check never creates one, so it cannot detect that.TheGeneratorReusesItsOutputWhenNothingChanged(GeneratorBaseTests.cs:203) therefore asserts nothing meaningful.Reproduction (ran)
The generator below is non-incremental by construction:
ReusesCachedOutputOnRerun(generator)returns true. Expected false.c1and then onc1.AddSyntaxTrees(CSharpSyntaxTree.ParseText(""))reports the output step asModified.Why it matters
This is a test helper that consumers rely on to prove their generators are incremental. A check that always passes gives false confidence and lets IDE-performance regressions ship.
Suggested fix / acceptance criteria
compilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(string.Empty))orcompilation.WithAssemblyName(compilation.AssemblyName). Ideally also rebuild theAdditionalTextinstances with identical content, as an IDE does.false, or throw) rather thantrue.CompilationProvider.Select(_ => new object())generator above must fail the check.