Incremental generator ForAttributeWithMetadataName issues

System.ArgumentException: SyntaxTree is not part of the compilation

This project contains very simple incremental source code generator TestGenerator, which takes ClassDeclarationSyntaxs having [Generate] attribute and generates a partial class for it. This selection is done via ForAttributeWithMetadataName.

Expected outcome

Generator has no error

Actual outcome

Generator crashes with:

Warning	CS8785	Generator 'TestGenerator' failed to generate source. It will not contribute to the output and compilation errors may occur as a result. Exception was of type 'ArgumentException' with message 'SyntaxTree is not part of the compilation
Parameter name: syntaxTree'	Generator.Test	...\src\Generator.Test	1	Active	Generator threw the following exception:
'System.ArgumentException: SyntaxTree is not part of the compilation
Parameter name: syntaxTree
   at Microsoft.CodeAnalysis.CSharp.CSharpCompilation.GetSemanticModel(SyntaxTree syntaxTree, Boolean ignoreAccessibility)
   at Microsoft.CodeAnalysis.SyntaxValueProvider.<>c__DisplayClass11_0`1.<ForAttributeWithMetadataName>b__0(ValueTuple`2 tuple, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.UserFunctionExtensions.<>c__DisplayClass0_0`2.<WrapUserFunction>b__0(TInput input, CancellationToken token)'.

Steps to reproduce:

  1. Open and build the solution

  2. Re-Open the visual studio to load the generator

    • Don't open any file from "Generator.Test" project yet
  3. Open file Generator.Test/DClass.cs

    • Remove [Generate] attribute on the class DClass
  4. Open file Generator.Test/CClass.cs

    • This should now trigger the error. If not, do a whitespace chage in this file

These steps rely on the order of compilation.CommonSyntaxTrees. In my case, the order is following:

...\Generator.Test\DClass.cs
...\Generator.Test\CClass.cs
...\Generator.Test\AClass.cs
...\Generator.Test\obj\Debug\net6.0\.NETCoreApp,Version=v6.0.AssemblyAttributes.cs
...\Generator.Test\obj\Debug\net6.0\Generator.Test.AssemblyInfo.cs

Duplicate hintName

The same steps as above could also lead to duplicate hintName issue, because one SyntaxNode will end up in the NodeStateTable twice. Once from previous compilation and once from current compilation. In this case it'll be Generator.Test\CClass.cs

Diagnostic data

Here is how the NodeStateTables looks like inside TransformNode during the reproduction steps. As you can see, the final result will end with duplicate SyntaxNodes in the newTable, and one of them is from previous compilation.

Iteration 1 - Remove `[Generate]` attribute on the class `DClass` (Step 3.)
.Where((info, _) => info.Info.HasFlag(ContainsAttributeList)) .Where(tuple => tuple.Item2.Length > 0)
Index PreviousTable NewTable SourceTable PreviousTable NewTable
0 DClass.cs (Cached) DClass.cs (Modified) DClass.cs (Modified) DClass.cs (Cached) DClass.cs (Removed)
1 CClass.cs (Cached) CClass.cs (Cached) CClass.cs (Cached) CClass.cs (Cached) CClass.cs (Cached)
2 AClass.cs (Cached) AClass.cs (Cached) AClass.cs (Cached) AClass.cs (Cached) AClass.cs (Cached)
3 obj\Debug\net6.0\.NETCoreApp,Version=v6.0.AssemblyAttributes.cs (Cached) obj\Debug\net6.0\.NETCoreApp,Version=v6.0.AssemblyAttributes.cs (Cached) obj\Debug\net6.0\.NETCoreApp,Version=v6.0.AssemblyAttributes.cs (Cached)
4 obj\Debug\net6.0\Generator.Test.AssemblyInfo.cs (Cached) obj\Debug\net6.0\Generator.Test.AssemblyInfo.cs (Cached) obj\Debug\net6.0\Generator.Test.AssemblyInfo.cs (Cached)
Iteration 2 - Open file `Generator.Test/CClass.cs` (Step 4.)
.Where((info, _) => info.Info.HasFlag(ContainsAttributeList)) .Where(tuple => tuple.Item2.Length > 0)
Index PreviousTable NewTable SourceTable PreviousTable NewTable
0 DClass.cs (Cached) DClass.cs (Cached) DClass.cs (Cached) CClass.cs (Cached) CClass.cs (Cached)
1 CClass.cs (Cached) CClass.cs (Modified) CClass.cs (Modified) AClass.cs (Cached) CClass.cs (Modified)
2 AClass.cs (Cached) AClass.cs (Cached) AClass.cs (Cached)
3 obj\Debug\net6.0\.NETCoreApp,Version=v6.0.AssemblyAttributes.cs   (Cached) obj\Debug\net6.0\.NETCoreApp,Version=v6.0.AssemblyAttributes.cs   (Cached) obj\Debug\net6.0\.NETCoreApp,Version=v6.0.AssemblyAttributes.cs   (Cached)
4 obj\Debug\net6.0\Generator.Test.AssemblyInfo.cs   (Cached) obj\Debug\net6.0\Generator.Test.AssemblyInfo.cs   (Cached) obj\Debug\net6.0\Generator.Test.AssemblyInfo.cs   (Cached) -