This project contains very simple incremental source code generator TestGenerator
, which takes ClassDeclarationSyntax
s having [Generate]
attribute and generates a partial class for it. This selection is done via ForAttributeWithMetadataName
.
Generator has no error
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)'.
-
Open and build the solution
-
Re-Open the visual studio to load the generator
- Don't open any file from "Generator.Test" project yet
-
Open file
Generator.Test/DClass.cs
- Remove
[Generate]
attribute on the classDClass
- Remove
-
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
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
Here is how the NodeStateTable
s looks like inside TransformNode
during the reproduction steps.
As you can see, the final result will end with duplicate SyntaxNode
s 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) | - |