diff --git a/src/TUnit.Core.SourceGenerator/CodeGenerators/DynamicTestsGenerator.cs b/src/TUnit.Core.SourceGenerator/CodeGenerators/DynamicTestsGenerator.cs
index d2c2cd989b6..70defd07d4b 100644
--- a/src/TUnit.Core.SourceGenerator/CodeGenerators/DynamicTestsGenerator.cs
+++ b/src/TUnit.Core.SourceGenerator/CodeGenerators/DynamicTestsGenerator.cs
@@ -73,11 +73,8 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
{
FullyQualifiedTypeName = containingType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat),
MinimalTypeName = containingType.Name,
- Namespace = containingType.ContainingNamespace?.ToDisplayString() ?? string.Empty,
MethodName = methodSymbol.Name,
IsStatic = methodSymbol.IsStatic,
- IsAsync = methodSymbol.IsAsync,
- ReturnType = methodSymbol.ReturnType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat),
FilePath = filePath,
LineNumber = lineNumber
};
diff --git a/src/TUnit.Core.SourceGenerator/CodeGenerators/Equality/PreventCompilationTriggerOnEveryKeystrokeComparer.cs b/src/TUnit.Core.SourceGenerator/CodeGenerators/Equality/PreventCompilationTriggerOnEveryKeystrokeComparer.cs
index 356bec30ae8..bf9148cd6b3 100644
--- a/src/TUnit.Core.SourceGenerator/CodeGenerators/Equality/PreventCompilationTriggerOnEveryKeystrokeComparer.cs
+++ b/src/TUnit.Core.SourceGenerator/CodeGenerators/Equality/PreventCompilationTriggerOnEveryKeystrokeComparer.cs
@@ -1,7 +1,14 @@
-using Microsoft.CodeAnalysis;
+using System.Collections.Immutable;
+using Microsoft.CodeAnalysis;
namespace TUnit.Core.SourceGenerator.CodeGenerators.Equality;
+///
+/// Treats two compilations as equal when they would produce the same reference-derived output:
+/// same language, assembly name and metadata references. Syntax-only edits (ordinary keystrokes)
+/// keep the same instances, so they compare equal and the
+/// downstream reference walk is skipped. Adding, removing, rebuilding or editing a reference does not.
+///
public class PreventCompilationTriggerOnEveryKeystrokeComparer : IEqualityComparer
{
public bool Equals(Compilation? x, Compilation? y)
@@ -26,7 +33,10 @@ public bool Equals(Compilation? x, Compilation? y)
return false;
}
- return x.Language == y.Language && x.AssemblyName == y.AssemblyName;
+ return x.Language == y.Language
+ && x.AssemblyName == y.AssemblyName
+ && ReferencesEqual(x.ExternalReferences, y.ExternalReferences)
+ && ReferencesEqual(x.DirectiveReferences, y.DirectiveReferences);
}
public int GetHashCode(Compilation obj)
@@ -36,4 +46,33 @@ public int GetHashCode(Compilation obj)
return (obj.Language.GetHashCode() * 397) ^ (obj.AssemblyName != null ? obj.AssemblyName.GetHashCode() : 0);
}
}
+
+ private static bool ReferencesEqual(ImmutableArray x, ImmutableArray y)
+ {
+ // Syntax-only edits usually keep the same backing array, so this avoids the element walk.
+ if (x == y)
+ {
+ return true;
+ }
+
+ if (x.Length != y.Length)
+ {
+ return false;
+ }
+
+ for (var i = 0; i < x.Length; i++)
+ {
+ // Hosts reuse reference instances while the referenced file or project is unchanged.
+ // A new instance means the reference was added, rebuilt or (for an IDE project
+ // reference) its source was edited, which can change the types and dependencies the
+ // reference walk selects. Rerun extraction then; AssemblyInfoModel equality keeps the
+ // generated source cached when the extracted model is unchanged.
+ if (!ReferenceEquals(x[i], y[i]))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
}
diff --git a/src/TUnit.Core.SourceGenerator/CodeGenerators/InfrastructureGenerator.cs b/src/TUnit.Core.SourceGenerator/CodeGenerators/InfrastructureGenerator.cs
index b494c7cff01..a9746741288 100644
--- a/src/TUnit.Core.SourceGenerator/CodeGenerators/InfrastructureGenerator.cs
+++ b/src/TUnit.Core.SourceGenerator/CodeGenerators/InfrastructureGenerator.cs
@@ -46,6 +46,8 @@ public class InfrastructureGenerator : IIncrementalGenerator
"TUnit_DynamicTestRegistration",
];
+ public const string ExtractAssemblyInfoStep = "ExtractAssemblyInfo";
+
public void Initialize(IncrementalGeneratorInitializationContext context)
{
var enabledProvider = context.AnalyzerConfigOptionsProvider
@@ -60,6 +62,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
var assemblyInfoProvider = context.CompilationProvider
.WithComparer(new PreventCompilationTriggerOnEveryKeystrokeComparer())
.Select((compilation, _) => ExtractAssemblyInfo(compilation))
+ .WithTrackingName(ExtractAssemblyInfoStep)
.Combine(enabledProvider);
context.RegisterSourceOutput(assemblyInfoProvider, (sourceContext, data) =>
diff --git a/src/TUnit.Core.SourceGenerator/Generators/HookMetadataGenerator.cs b/src/TUnit.Core.SourceGenerator/Generators/HookMetadataGenerator.cs
index 524d4d73b1b..917e20a3d5d 100644
--- a/src/TUnit.Core.SourceGenerator/Generators/HookMetadataGenerator.cs
+++ b/src/TUnit.Core.SourceGenerator/Generators/HookMetadataGenerator.cs
@@ -16,6 +16,11 @@ namespace TUnit.Core.SourceGenerator.Generators;
[Generator]
public class HookMetadataGenerator : IIncrementalGenerator
{
+ public const string ExtractBeforeHooks = "ExtractBeforeHooks";
+ public const string ExtractAfterHooks = "ExtractAfterHooks";
+ public const string ExtractBeforeEveryHooks = "ExtractBeforeEveryHooks";
+ public const string ExtractAfterEveryHooks = "ExtractAfterEveryHooks";
+
public void Initialize(IncrementalGeneratorInitializationContext context)
{
var enabledProvider = context.AnalyzerConfigOptionsProvider
@@ -31,6 +36,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
predicate: static (node, _) => node is MethodDeclarationSyntax,
transform: static (ctx, _) => ExtractHookModel(ctx, "Before"))
.Where(static m => m is not null)
+ .WithTrackingName(ExtractBeforeHooks)
.Combine(enabledProvider);
var afterHooks = context.SyntaxProvider
@@ -39,6 +45,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
predicate: static (node, _) => node is MethodDeclarationSyntax,
transform: static (ctx, _) => ExtractHookModel(ctx, "After"))
.Where(static m => m is not null)
+ .WithTrackingName(ExtractAfterHooks)
.Combine(enabledProvider);
var beforeEveryHooks = context.SyntaxProvider
@@ -47,6 +54,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
predicate: static (node, _) => node is MethodDeclarationSyntax,
transform: static (ctx, _) => ExtractHookModel(ctx, "BeforeEvery"))
.Where(static m => m is not null)
+ .WithTrackingName(ExtractBeforeEveryHooks)
.Combine(enabledProvider);
var afterEveryHooks = context.SyntaxProvider
@@ -55,6 +63,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
predicate: static (node, _) => node is MethodDeclarationSyntax,
transform: static (ctx, _) => ExtractHookModel(ctx, "AfterEvery"))
.Where(static m => m is not null)
+ .WithTrackingName(ExtractAfterEveryHooks)
.Combine(enabledProvider);
context.RegisterSourceOutput(beforeHooks, GenerateHookFile);
diff --git a/src/TUnit.Core.SourceGenerator/Models/Extracted/DynamicTestModel.cs b/src/TUnit.Core.SourceGenerator/Models/Extracted/DynamicTestModel.cs
index 0b87357f08f..03eafecfed4 100644
--- a/src/TUnit.Core.SourceGenerator/Models/Extracted/DynamicTestModel.cs
+++ b/src/TUnit.Core.SourceGenerator/Models/Extracted/DynamicTestModel.cs
@@ -8,11 +8,8 @@ public sealed class DynamicTestModel : IEquatable
{
public required string FullyQualifiedTypeName { get; init; }
public required string MinimalTypeName { get; init; }
- public required string Namespace { get; init; }
public required string MethodName { get; init; }
public required bool IsStatic { get; init; }
- public required bool IsAsync { get; init; }
- public required string ReturnType { get; init; }
public required string FilePath { get; init; }
public required int LineNumber { get; init; }
@@ -28,9 +25,14 @@ public bool Equals(DynamicTestModel? other)
return true;
}
+ // Every field feeds the generated source (FilePath and LineNumber also feed the hint name),
+ // so all of them must be compared.
return FullyQualifiedTypeName == other.FullyQualifiedTypeName
+ && MinimalTypeName == other.MinimalTypeName
&& MethodName == other.MethodName
- && IsStatic == other.IsStatic;
+ && IsStatic == other.IsStatic
+ && FilePath == other.FilePath
+ && LineNumber == other.LineNumber;
}
public override bool Equals(object? obj)
@@ -45,6 +47,8 @@ public override int GetHashCode()
var hash = FullyQualifiedTypeName.GetHashCode();
hash = (hash * 397) ^ MethodName.GetHashCode();
hash = (hash * 397) ^ IsStatic.GetHashCode();
+ hash = (hash * 397) ^ FilePath.GetHashCode();
+ hash = (hash * 397) ^ LineNumber;
return hash;
}
}
diff --git a/src/TUnit.Core.SourceGenerator/Models/Extracted/HookModel.cs b/src/TUnit.Core.SourceGenerator/Models/Extracted/HookModel.cs
index 8d19b7cf52e..f0aeb69e5a4 100644
--- a/src/TUnit.Core.SourceGenerator/Models/Extracted/HookModel.cs
+++ b/src/TUnit.Core.SourceGenerator/Models/Extracted/HookModel.cs
@@ -58,13 +58,37 @@ public bool Equals(HookModel? other)
return true;
}
+ // Every field feeds the generated hook file (hint name, delegate body, or the hook
+ // object's metadata such as FilePath/LineNumber), so every field must be compared.
+ // Otherwise the incremental pipeline treats a changed hook as unchanged and the IDE
+ // keeps showing stale generated output.
return FullyQualifiedTypeName == other.FullyQualifiedTypeName
+ && MinimalTypeName == other.MinimalTypeName
+ && Namespace == other.Namespace
+ && AssemblyName == other.AssemblyName
&& MethodName == other.MethodName
+ && FilePath == other.FilePath
+ && LineNumber == other.LineNumber
&& HookKind == other.HookKind
&& HookType == other.HookType
&& Order == other.Order
+ && HookExecutorTypeName == other.HookExecutorTypeName
+ && IsStatic == other.IsStatic
+ && IsAsync == other.IsAsync
+ && ReturnsVoid == other.ReturnsVoid
+ && ReturnType == other.ReturnType
&& ParameterCount == other.ParameterCount
- && IsStatic == other.IsStatic;
+ && HasCancellationTokenOnly == other.HasCancellationTokenOnly
+ && HasContextOnly == other.HasContextOnly
+ && HasContextAndCancellationToken == other.HasContextAndCancellationToken
+ && FirstParameterTypeName == other.FirstParameterTypeName
+ && Parameters.Equals(other.Parameters)
+ && ClassIsGenericType == other.ClassIsGenericType
+ && ClassIsOpenGeneric == other.ClassIsOpenGeneric
+ && ClassTypeParameters.Equals(other.ClassTypeParameters)
+ && MethodInfoExpression == other.MethodInfoExpression
+ && HookAttribute.Equals(other.HookAttribute)
+ && MethodAttributes.Equals(other.MethodAttributes);
}
public override bool Equals(object? obj)
@@ -78,11 +102,17 @@ public override int GetHashCode()
{
var hash = FullyQualifiedTypeName.GetHashCode();
hash = (hash * 397) ^ MethodName.GetHashCode();
+ hash = (hash * 397) ^ FilePath.GetHashCode();
+ hash = (hash * 397) ^ LineNumber;
hash = (hash * 397) ^ HookKind.GetHashCode();
hash = (hash * 397) ^ HookType.GetHashCode();
hash = (hash * 397) ^ Order;
hash = (hash * 397) ^ ParameterCount;
hash = (hash * 397) ^ IsStatic.GetHashCode();
+ hash = (hash * 397) ^ IsAsync.GetHashCode();
+ hash = (hash * 397) ^ ReturnType.GetHashCode();
+ hash = (hash * 397) ^ Parameters.GetHashCode();
+ hash = (hash * 397) ^ MethodAttributes.GetHashCode();
return hash;
}
}
diff --git a/tests/TUnit.SourceGenerator.IncrementalTests/DynamicTestsGeneratorIncrementalTests.cs b/tests/TUnit.SourceGenerator.IncrementalTests/DynamicTestsGeneratorIncrementalTests.cs
index bd807bb810c..dc27055539b 100644
--- a/tests/TUnit.SourceGenerator.IncrementalTests/DynamicTestsGeneratorIncrementalTests.cs
+++ b/tests/TUnit.SourceGenerator.IncrementalTests/DynamicTestsGeneratorIncrementalTests.cs
@@ -84,6 +84,25 @@ public void SecondBuildDynamicTests(DynamicTestBuilderContext context)
AssertRunReasons(driver2, IncrementalGeneratorRunReasons.New, 1);
}
+ [Fact]
+ public void MoveDynamicMethodToDifferentLine_ShouldRegenerate()
+ {
+ var syntaxTree = CSharpSyntaxTree.ParseText(DefaultConverter, CSharpParseOptions.Default);
+ var compilation1 = Fixture.CreateLibrary(syntaxTree);
+
+ var driver1 = TestHelper.GenerateTracked(compilation1);
+ AssertRunReasons(driver1, IncrementalGeneratorRunReasons.New);
+
+ // The [CallerLineNumber] captured by DynamicTestBuilder feeds the hint name and the
+ // generated DynamicTestBuilderContext, so shifting the method must regenerate.
+ var compilation2 = compilation1.ReplaceSyntaxTree(
+ syntaxTree,
+ CSharpSyntaxTree.ParseText(DefaultConverter.Replace("public class DynamicTestArgumentsTests", "\n\npublic class DynamicTestArgumentsTests"), CSharpParseOptions.Default));
+
+ var driver2 = driver1.RunGenerators(compilation2);
+ AssertRunReasons(driver2, IncrementalGeneratorRunReasons.Modified);
+ }
+
private static void AssertRunReasons(
GeneratorDriver driver,
IncrementalGeneratorRunReasons reasons,
diff --git a/tests/TUnit.SourceGenerator.IncrementalTests/HookMetadataGeneratorIncrementalTests.cs b/tests/TUnit.SourceGenerator.IncrementalTests/HookMetadataGeneratorIncrementalTests.cs
new file mode 100644
index 00000000000..20fb7c53fd1
--- /dev/null
+++ b/tests/TUnit.SourceGenerator.IncrementalTests/HookMetadataGeneratorIncrementalTests.cs
@@ -0,0 +1,80 @@
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using TUnit.Core.SourceGenerator.Generators;
+
+namespace TUnit.Assertions.SourceGenerator.IncrementalTests;
+
+public class HookMetadataGeneratorIncrementalTests
+{
+ private const string DefaultSource =
+ """
+ using System.Threading.Tasks;
+ using TUnit.Core;
+
+ public class HookTests
+ {
+ [Before(HookType.Test)]
+ public void Setup()
+ {
+ }
+ }
+ """;
+
+ [Fact]
+ public void AddUnrelatedType_ShouldNotRegenerate()
+ {
+ var compilation1 = Fixture.CreateLibrary(CSharpSyntaxTree.ParseText(DefaultSource, CSharpParseOptions.Default));
+
+ var driver1 = TestHelper.GenerateTracked(compilation1);
+ AssertRunReason(driver1, IncrementalStepRunReason.New);
+
+ var compilation2 = compilation1.AddSyntaxTrees(CSharpSyntaxTree.ParseText("struct MyValue {}"));
+ var driver2 = driver1.RunGenerators(compilation2);
+ AssertRunReason(driver2, IncrementalStepRunReason.Cached);
+ }
+
+ [Fact]
+ public void MoveHookToDifferentLine_ShouldRegenerate()
+ {
+ var compilation1 = Fixture.CreateLibrary(CSharpSyntaxTree.ParseText(DefaultSource, CSharpParseOptions.Default));
+
+ var driver1 = TestHelper.GenerateTracked(compilation1);
+ AssertRunReason(driver1, IncrementalStepRunReason.New);
+
+ // Same hook shifted down two lines: the emitted LineNumber must follow it.
+ var compilation2 = compilation1.ReplaceSyntaxTree(
+ compilation1.SyntaxTrees.Single(),
+ CSharpSyntaxTree.ParseText(DefaultSource.Replace("public class HookTests", "\n\npublic class HookTests"), CSharpParseOptions.Default));
+
+ var driver2 = driver1.RunGenerators(compilation2);
+ AssertRunReason(driver2, IncrementalStepRunReason.Modified);
+ }
+
+ [Fact]
+ public void MakeHookAsync_ShouldRegenerate()
+ {
+ var compilation1 = Fixture.CreateLibrary(CSharpSyntaxTree.ParseText(DefaultSource, CSharpParseOptions.Default));
+
+ var driver1 = TestHelper.GenerateTracked(compilation1);
+ AssertRunReason(driver1, IncrementalStepRunReason.New);
+
+ var compilation2 = TestHelper.ReplaceMethodDeclaration(compilation1, "Setup",
+ """
+ [Before(HookType.Test)]
+ public async Task Setup()
+ {
+ await Task.Yield();
+ }
+ """);
+
+ var driver2 = driver1.RunGenerators(compilation2);
+ AssertRunReason(driver2, IncrementalStepRunReason.Modified);
+ }
+
+ private static void AssertRunReason(GeneratorDriver driver, IncrementalStepRunReason reason)
+ {
+ var runResult = driver.GetRunResult().Results[0];
+
+ TestHelper.AssertRunReason(runResult, HookMetadataGenerator.ExtractBeforeHooks, reason, 0);
+ }
+}
diff --git a/tests/TUnit.SourceGenerator.IncrementalTests/InfrastructureGeneratorIncrementalTests.cs b/tests/TUnit.SourceGenerator.IncrementalTests/InfrastructureGeneratorIncrementalTests.cs
new file mode 100644
index 00000000000..2bd2c4f274a
--- /dev/null
+++ b/tests/TUnit.SourceGenerator.IncrementalTests/InfrastructureGeneratorIncrementalTests.cs
@@ -0,0 +1,112 @@
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using TUnit.Core.SourceGenerator.CodeGenerators;
+
+namespace TUnit.Assertions.SourceGenerator.IncrementalTests;
+
+public class InfrastructureGeneratorIncrementalTests
+{
+ private const string DefaultSource =
+ """
+ using TUnit.Core;
+
+ public class Tests
+ {
+ [Test]
+ public void Test1()
+ {
+ }
+ }
+ """;
+
+ [Fact]
+ public void EditSource_ShouldNotRegenerate()
+ {
+ var compilation1 = Fixture.CreateLibrary(CSharpSyntaxTree.ParseText(DefaultSource, CSharpParseOptions.Default));
+
+ var driver1 = TestHelper.GenerateTracked(compilation1);
+ AssertRunReason(driver1, IncrementalStepRunReason.New);
+
+ var compilation2 = compilation1.AddSyntaxTrees(CSharpSyntaxTree.ParseText("struct MyValue {}"));
+ var driver2 = driver1.RunGenerators(compilation2);
+ AssertRunReason(driver2, IncrementalStepRunReason.Cached);
+
+ var compilation3 = TestHelper.ReplaceMethodDeclaration(compilation1, "Test1",
+ """
+ [Test]
+ public void Test1()
+ {
+ var x = 1;
+ }
+ """);
+ var driver3 = driver2.RunGenerators(compilation3);
+ AssertRunReason(driver3, IncrementalStepRunReason.Cached);
+ }
+
+ [Fact]
+ public void AddReference_ShouldRegenerate()
+ {
+ var compilation1 = Fixture.CreateLibrary(CSharpSyntaxTree.ParseText(DefaultSource, CSharpParseOptions.Default));
+
+ var driver1 = TestHelper.GenerateTracked(compilation1);
+ AssertRunReason(driver1, IncrementalStepRunReason.New);
+
+ // A library that references TUnit.Core must be pre-loaded by TUnitInfrastructure.g.cs.
+ var library = CSharpCompilation.Create(
+ "OtherTestLibrary",
+ [CSharpSyntaxTree.ParseText("namespace OtherTestLibrary { public class SharedHooks { [TUnit.Core.Before(TUnit.Core.HookType.Assembly)] public static void Setup() { } } }")],
+ compilation1.References,
+ new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
+
+ var compilation2 = compilation1.AddReferences(library.ToMetadataReference());
+ var driver2 = driver1.RunGenerators(compilation2);
+ AssertRunReason(driver2, IncrementalStepRunReason.Modified);
+
+ var generated = driver2.GetRunResult().GeneratedTrees.Single(t => t.FilePath.EndsWith("TUnitInfrastructure.g.cs"));
+ Xunit.Assert.Contains("global::OtherTestLibrary.SharedHooks", generated.ToString());
+ }
+
+ [Fact]
+ public void EditProjectReference_ShouldRegenerate()
+ {
+ var compilation1 = Fixture.CreateLibrary(CSharpSyntaxTree.ParseText(DefaultSource, CSharpParseOptions.Default));
+
+ var library1 = CreateHookLibrary(compilation1, "SharedHooks");
+ compilation1 = compilation1.AddReferences(library1.ToMetadataReference());
+
+ var driver1 = TestHelper.GenerateTracked(compilation1);
+ AssertRunReason(driver1, IncrementalStepRunReason.New);
+
+ // In the IDE, editing a referenced project replaces its CompilationReference while the
+ // assembly name stays the same. Renaming the only public type must reach the output,
+ // otherwise TUnitInfrastructure.g.cs keeps a typeof() to a type that no longer exists.
+ var library2 = CreateHookLibrary(compilation1, "RenamedHooks");
+ var compilation2 = compilation1.ReplaceReference(compilation1.References.Last(), library2.ToMetadataReference());
+ var driver2 = driver1.RunGenerators(compilation2);
+ AssertRunReason(driver2, IncrementalStepRunReason.Modified);
+
+ var generated = driver2.GetRunResult().GeneratedTrees.Single(t => t.FilePath.EndsWith("TUnitInfrastructure.g.cs")).ToString();
+ Xunit.Assert.Contains("global::OtherTestLibrary.RenamedHooks", generated);
+ Xunit.Assert.DoesNotContain("global::OtherTestLibrary.SharedHooks", generated);
+
+ // An edit that does not change the extracted model reruns extraction but keeps the output cached.
+ var library3 = CreateHookLibrary(compilation1, "RenamedHooks");
+ var compilation3 = compilation2.ReplaceReference(compilation2.References.Last(), library3.ToMetadataReference());
+ var driver3 = driver2.RunGenerators(compilation3);
+ AssertRunReason(driver3, IncrementalStepRunReason.Unchanged);
+ }
+
+ private static CSharpCompilation CreateHookLibrary(Compilation consumer, string typeName) =>
+ CSharpCompilation.Create(
+ "OtherTestLibrary",
+ [CSharpSyntaxTree.ParseText($"namespace OtherTestLibrary {{ public class {typeName} {{ [TUnit.Core.Before(TUnit.Core.HookType.Assembly)] public static void Setup() {{ }} }} }}")],
+ consumer.References.Where(r => r is not CompilationReference),
+ new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
+
+ private static void AssertRunReason(GeneratorDriver driver, IncrementalStepRunReason reason)
+ {
+ var runResult = driver.GetRunResult().Results[0];
+
+ TestHelper.AssertRunReason(runResult, InfrastructureGenerator.ExtractAssemblyInfoStep, reason, 0);
+ }
+}