diff --git a/TUnit.Core.SourceGenerator.Tests/DuplicateTypeNameAcrossAssembliesTests.InfrastructureGenerator_WithDuplicateTypeNames_CompilesSuccessfully.DotNet10_0.verified.txt b/TUnit.Core.SourceGenerator.Tests/DuplicateTypeNameAcrossAssembliesTests.InfrastructureGenerator_WithDuplicateTypeNames_CompilesSuccessfully.DotNet10_0.verified.txt
new file mode 100644
index 0000000000..d1438ad71e
--- /dev/null
+++ b/TUnit.Core.SourceGenerator.Tests/DuplicateTypeNameAcrossAssembliesTests.InfrastructureGenerator_WithDuplicateTypeNames_CompilesSuccessfully.DotNet10_0.verified.txt
@@ -0,0 +1,108 @@
+//
+#pragma warning disable
+
+using TUnit.Core.Logging;
+[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute]
+[global::System.CodeDom.Compiler.GeneratedCode("TUnit", "1.0.0.0")]
+file static class TUnitInfrastructure
+{
+ [global::System.Runtime.CompilerServices.ModuleInitializer]
+ public static void Initialize()
+ {
+ try
+ {
+ global::TUnit.Core.SourceRegistrar.IsEnabled = true;
+ }
+ catch { /* TUnit.Core not available - skip source registrar */ }
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] TUnit infrastructure initializing...");
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Loading 3 assembly reference(s)...");
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ try
+ {
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Loading assembly containing: global::TUnit.TestProject.Library.AsyncBaseTests");
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ var type_0 = typeof(global::TUnit.TestProject.Library.AsyncBaseTests);
+ // Force module initializer to complete before proceeding
+ // RunClassConstructor triggers static constructor, which can only run AFTER module initializer completes
+ global::System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(type_0.TypeHandle);
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Assembly initialized: global::TUnit.TestProject.Library.AsyncBaseTests");
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ }
+ catch (global::System.Exception ex)
+ {
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Failed to load global::TUnit.TestProject.Library.AsyncBaseTests: " + ex.Message);
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ }
+ try
+ {
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Loading assembly containing: global::VerifyTUnit.DerivePathInfo");
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ var type_1 = typeof(global::VerifyTUnit.DerivePathInfo);
+ // Force module initializer to complete before proceeding
+ // RunClassConstructor triggers static constructor, which can only run AFTER module initializer completes
+ global::System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(type_1.TypeHandle);
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Assembly initialized: global::VerifyTUnit.DerivePathInfo");
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ }
+ catch (global::System.Exception ex)
+ {
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Failed to load global::VerifyTUnit.DerivePathInfo: " + ex.Message);
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ }
+ try
+ {
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Loading assembly containing: global::TUnit.Core.SourceGenerator.Tests.AotConverterGeneratorTests");
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ var type_2 = typeof(global::TUnit.Core.SourceGenerator.Tests.AotConverterGeneratorTests);
+ // Force module initializer to complete before proceeding
+ // RunClassConstructor triggers static constructor, which can only run AFTER module initializer completes
+ global::System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(type_2.TypeHandle);
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Assembly initialized: global::TUnit.Core.SourceGenerator.Tests.AotConverterGeneratorTests");
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ }
+ catch (global::System.Exception ex)
+ {
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Failed to load global::TUnit.Core.SourceGenerator.Tests.AotConverterGeneratorTests: " + ex.Message);
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ }
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] TUnit infrastructure initialized");
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ }
+}
diff --git a/TUnit.Core.SourceGenerator.Tests/DuplicateTypeNameAcrossAssembliesTests.InfrastructureGenerator_WithDuplicateTypeNames_CompilesSuccessfully.DotNet8_0.verified.txt b/TUnit.Core.SourceGenerator.Tests/DuplicateTypeNameAcrossAssembliesTests.InfrastructureGenerator_WithDuplicateTypeNames_CompilesSuccessfully.DotNet8_0.verified.txt
new file mode 100644
index 0000000000..d1438ad71e
--- /dev/null
+++ b/TUnit.Core.SourceGenerator.Tests/DuplicateTypeNameAcrossAssembliesTests.InfrastructureGenerator_WithDuplicateTypeNames_CompilesSuccessfully.DotNet8_0.verified.txt
@@ -0,0 +1,108 @@
+//
+#pragma warning disable
+
+using TUnit.Core.Logging;
+[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute]
+[global::System.CodeDom.Compiler.GeneratedCode("TUnit", "1.0.0.0")]
+file static class TUnitInfrastructure
+{
+ [global::System.Runtime.CompilerServices.ModuleInitializer]
+ public static void Initialize()
+ {
+ try
+ {
+ global::TUnit.Core.SourceRegistrar.IsEnabled = true;
+ }
+ catch { /* TUnit.Core not available - skip source registrar */ }
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] TUnit infrastructure initializing...");
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Loading 3 assembly reference(s)...");
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ try
+ {
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Loading assembly containing: global::TUnit.TestProject.Library.AsyncBaseTests");
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ var type_0 = typeof(global::TUnit.TestProject.Library.AsyncBaseTests);
+ // Force module initializer to complete before proceeding
+ // RunClassConstructor triggers static constructor, which can only run AFTER module initializer completes
+ global::System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(type_0.TypeHandle);
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Assembly initialized: global::TUnit.TestProject.Library.AsyncBaseTests");
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ }
+ catch (global::System.Exception ex)
+ {
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Failed to load global::TUnit.TestProject.Library.AsyncBaseTests: " + ex.Message);
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ }
+ try
+ {
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Loading assembly containing: global::VerifyTUnit.DerivePathInfo");
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ var type_1 = typeof(global::VerifyTUnit.DerivePathInfo);
+ // Force module initializer to complete before proceeding
+ // RunClassConstructor triggers static constructor, which can only run AFTER module initializer completes
+ global::System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(type_1.TypeHandle);
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Assembly initialized: global::VerifyTUnit.DerivePathInfo");
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ }
+ catch (global::System.Exception ex)
+ {
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Failed to load global::VerifyTUnit.DerivePathInfo: " + ex.Message);
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ }
+ try
+ {
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Loading assembly containing: global::TUnit.Core.SourceGenerator.Tests.AotConverterGeneratorTests");
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ var type_2 = typeof(global::TUnit.Core.SourceGenerator.Tests.AotConverterGeneratorTests);
+ // Force module initializer to complete before proceeding
+ // RunClassConstructor triggers static constructor, which can only run AFTER module initializer completes
+ global::System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(type_2.TypeHandle);
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Assembly initialized: global::TUnit.Core.SourceGenerator.Tests.AotConverterGeneratorTests");
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ }
+ catch (global::System.Exception ex)
+ {
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Failed to load global::TUnit.Core.SourceGenerator.Tests.AotConverterGeneratorTests: " + ex.Message);
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ }
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] TUnit infrastructure initialized");
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ }
+}
diff --git a/TUnit.Core.SourceGenerator.Tests/DuplicateTypeNameAcrossAssembliesTests.InfrastructureGenerator_WithDuplicateTypeNames_CompilesSuccessfully.DotNet9_0.verified.txt b/TUnit.Core.SourceGenerator.Tests/DuplicateTypeNameAcrossAssembliesTests.InfrastructureGenerator_WithDuplicateTypeNames_CompilesSuccessfully.DotNet9_0.verified.txt
new file mode 100644
index 0000000000..d1438ad71e
--- /dev/null
+++ b/TUnit.Core.SourceGenerator.Tests/DuplicateTypeNameAcrossAssembliesTests.InfrastructureGenerator_WithDuplicateTypeNames_CompilesSuccessfully.DotNet9_0.verified.txt
@@ -0,0 +1,108 @@
+//
+#pragma warning disable
+
+using TUnit.Core.Logging;
+[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute]
+[global::System.CodeDom.Compiler.GeneratedCode("TUnit", "1.0.0.0")]
+file static class TUnitInfrastructure
+{
+ [global::System.Runtime.CompilerServices.ModuleInitializer]
+ public static void Initialize()
+ {
+ try
+ {
+ global::TUnit.Core.SourceRegistrar.IsEnabled = true;
+ }
+ catch { /* TUnit.Core not available - skip source registrar */ }
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] TUnit infrastructure initializing...");
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Loading 3 assembly reference(s)...");
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ try
+ {
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Loading assembly containing: global::TUnit.TestProject.Library.AsyncBaseTests");
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ var type_0 = typeof(global::TUnit.TestProject.Library.AsyncBaseTests);
+ // Force module initializer to complete before proceeding
+ // RunClassConstructor triggers static constructor, which can only run AFTER module initializer completes
+ global::System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(type_0.TypeHandle);
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Assembly initialized: global::TUnit.TestProject.Library.AsyncBaseTests");
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ }
+ catch (global::System.Exception ex)
+ {
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Failed to load global::TUnit.TestProject.Library.AsyncBaseTests: " + ex.Message);
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ }
+ try
+ {
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Loading assembly containing: global::VerifyTUnit.DerivePathInfo");
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ var type_1 = typeof(global::VerifyTUnit.DerivePathInfo);
+ // Force module initializer to complete before proceeding
+ // RunClassConstructor triggers static constructor, which can only run AFTER module initializer completes
+ global::System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(type_1.TypeHandle);
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Assembly initialized: global::VerifyTUnit.DerivePathInfo");
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ }
+ catch (global::System.Exception ex)
+ {
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Failed to load global::VerifyTUnit.DerivePathInfo: " + ex.Message);
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ }
+ try
+ {
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Loading assembly containing: global::TUnit.Core.SourceGenerator.Tests.AotConverterGeneratorTests");
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ var type_2 = typeof(global::TUnit.Core.SourceGenerator.Tests.AotConverterGeneratorTests);
+ // Force module initializer to complete before proceeding
+ // RunClassConstructor triggers static constructor, which can only run AFTER module initializer completes
+ global::System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(type_2.TypeHandle);
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Assembly initialized: global::TUnit.Core.SourceGenerator.Tests.AotConverterGeneratorTests");
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ }
+ catch (global::System.Exception ex)
+ {
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Failed to load global::TUnit.Core.SourceGenerator.Tests.AotConverterGeneratorTests: " + ex.Message);
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ }
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] TUnit infrastructure initialized");
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ }
+}
diff --git a/TUnit.Core.SourceGenerator.Tests/DuplicateTypeNameAcrossAssembliesTests.InfrastructureGenerator_WithDuplicateTypeNames_CompilesSuccessfully.Net4_7.verified.txt b/TUnit.Core.SourceGenerator.Tests/DuplicateTypeNameAcrossAssembliesTests.InfrastructureGenerator_WithDuplicateTypeNames_CompilesSuccessfully.Net4_7.verified.txt
new file mode 100644
index 0000000000..41b4956293
--- /dev/null
+++ b/TUnit.Core.SourceGenerator.Tests/DuplicateTypeNameAcrossAssembliesTests.InfrastructureGenerator_WithDuplicateTypeNames_CompilesSuccessfully.Net4_7.verified.txt
@@ -0,0 +1,108 @@
+//
+#pragma warning disable
+
+using TUnit.Core.Logging;
+[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute]
+[global::System.CodeDom.Compiler.GeneratedCode("TUnit", "1.0.0.0")]
+file static class TUnitInfrastructure
+{
+ [global::System.Runtime.CompilerServices.ModuleInitializer]
+ public static void Initialize()
+ {
+ try
+ {
+ global::TUnit.Core.SourceRegistrar.IsEnabled = true;
+ }
+ catch { /* TUnit.Core not available - skip source registrar */ }
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] TUnit infrastructure initializing...");
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Loading 3 assembly reference(s)...");
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ try
+ {
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Loading assembly containing: global::TUnit.TestProject.Library.AsyncBaseTests");
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ var type_0 = typeof(global::TUnit.TestProject.Library.AsyncBaseTests);
+ // Force module initializer to complete before proceeding
+ // RunClassConstructor triggers static constructor, which can only run AFTER module initializer completes
+ global::System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(type_0.TypeHandle);
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Assembly initialized: global::TUnit.TestProject.Library.AsyncBaseTests");
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ }
+ catch (global::System.Exception ex)
+ {
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Failed to load global::TUnit.TestProject.Library.AsyncBaseTests: " + ex.Message);
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ }
+ try
+ {
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Loading assembly containing: global::VerifyTUnit.DerivePathInfo");
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ var type_1 = typeof(global::VerifyTUnit.DerivePathInfo);
+ // Force module initializer to complete before proceeding
+ // RunClassConstructor triggers static constructor, which can only run AFTER module initializer completes
+ global::System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(type_1.TypeHandle);
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Assembly initialized: global::VerifyTUnit.DerivePathInfo");
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ }
+ catch (global::System.Exception ex)
+ {
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Failed to load global::VerifyTUnit.DerivePathInfo: " + ex.Message);
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ }
+ try
+ {
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Loading assembly containing: global::TUnit.Core.SourceGenerator.Tests.AotConverterGeneratorTests");
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ var type_2 = typeof(global::TUnit.Core.SourceGenerator.Tests.AotConverterGeneratorTests);
+ // Force module initializer to complete before proceeding
+ // RunClassConstructor triggers static constructor, which can only run AFTER module initializer completes
+ global::System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(type_2.TypeHandle);
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Assembly initialized: global::TUnit.Core.SourceGenerator.Tests.AotConverterGeneratorTests");
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ }
+ catch (global::System.Exception ex)
+ {
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] Failed to load global::TUnit.Core.SourceGenerator.Tests.AotConverterGeneratorTests: " + ex.Message);
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ }
+ try
+ {
+ global::TUnit.Core.GlobalContext.Current.GlobalLogger.LogDebug("[ModuleInitializer:TestsBase`1] TUnit infrastructure initialized");
+ }
+ catch { /* TUnit.Core not available - skip logging */ }
+ }
+}
diff --git a/TUnit.Core.SourceGenerator.Tests/DuplicateTypeNameAcrossAssembliesTests.cs b/TUnit.Core.SourceGenerator.Tests/DuplicateTypeNameAcrossAssembliesTests.cs
new file mode 100644
index 0000000000..ba153ed294
--- /dev/null
+++ b/TUnit.Core.SourceGenerator.Tests/DuplicateTypeNameAcrossAssembliesTests.cs
@@ -0,0 +1,55 @@
+using TUnit.Core.SourceGenerator.Tests.Options;
+
+namespace TUnit.Core.SourceGenerator.Tests;
+
+///
+/// Tests to verify that generated code compiles correctly when multiple assemblies
+/// define types with the same fully-qualified name.
+/// See: https://github.com/thomhurst/TUnit/issues/4663
+///
+internal class DuplicateTypeNameAcrossAssembliesTests : TestsBase
+{
+ ///
+ /// This test verifies that the InfrastructureGenerator correctly handles the case
+ /// where a type name is ambiguous (exists in multiple places).
+ ///
+ /// We simulate this by adding a synthetic type with the same fully-qualified name as
+ /// a type from the VerifyTUnit package. The generator uses GetTypeByMetadataName() to
+ /// detect ambiguous types and skip them, finding a unique type instead.
+ ///
+ /// Without the fix: generator picks DanglingSnapshots, which is ambiguous
+ /// With the fix: generator detects ambiguity and picks DerivePathInfo instead
+ ///
+ [Test]
+ public Task InfrastructureGenerator_WithDuplicateTypeNames_CompilesSuccessfully() => InfrastructureGenerator.RunTest(
+ Path.Combine(Git.RootDirectory.FullName, "TUnit.TestProject", "BasicTests.cs"),
+ new RunTestOptions
+ {
+ AdditionalSyntaxes =
+ [
+ // Create a type that conflicts with VerifyTUnit.DanglingSnapshots
+ // This simulates the scenario where two assemblies define the same type
+ """
+ namespace VerifyTUnit
+ {
+ public class DanglingSnapshots { }
+ }
+ """
+ ],
+ VerifyConfigurator = verify => verify.UniqueForTargetFrameworkAndVersion()
+ },
+ async generatedFiles =>
+ {
+ // If we get here without compilation errors, the test passes
+ // The fix ensures the generator picks unique types that don't conflict
+ await Assert.That(generatedFiles).IsNotEmpty();
+
+ // Verify that the generated code doesn't reference the conflicting type
+ var infrastructureFile = generatedFiles.FirstOrDefault(f => f.Contains("TUnitInfrastructure"));
+ await Assert.That(infrastructureFile).IsNotNull();
+
+ // The generator should have found a different type from VerifyTUnit assembly
+ // since DanglingSnapshots is now ambiguous
+ await Assert.That(infrastructureFile!).DoesNotContain("typeof(global::VerifyTUnit.DanglingSnapshots)");
+ });
+}
diff --git a/TUnit.Core.SourceGenerator/CodeGenerators/InfrastructureGenerator.cs b/TUnit.Core.SourceGenerator/CodeGenerators/InfrastructureGenerator.cs
index 608dbbce69..8c86ff486b 100644
--- a/TUnit.Core.SourceGenerator/CodeGenerators/InfrastructureGenerator.cs
+++ b/TUnit.Core.SourceGenerator/CodeGenerators/InfrastructureGenerator.cs
@@ -106,7 +106,7 @@ private static AssemblyInfoModel ExtractAssemblyInfo(Compilation compilation)
{
if (ShouldLoadAssembly(assembly, compilation))
{
- var publicType = GetFirstPublicType(assembly);
+ var publicType = GetFirstUniquePublicType(assembly, compilation);
if (publicType != null)
{
assembliesToLoad.Add(publicType);
@@ -256,39 +256,85 @@ private static bool IsLoadableAtRuntime(IAssemblySymbol assembly, Compilation co
return correspondingReference != null;
}
- private static string? GetFirstPublicType(IAssemblySymbol assembly)
+ ///
+ /// Gets the first public type from an assembly that can be uniquely resolved by the compilation.
+ /// This avoids CS0433 errors when multiple assemblies define types with the same fully-qualified name.
+ ///
+ private static string? GetFirstUniquePublicType(IAssemblySymbol assembly, Compilation compilation)
{
- var publicTypes = GetPublicTypesRecursive(assembly.GlobalNamespace);
+ foreach (var type in GetPublicTypesRecursive(assembly.GlobalNamespace))
+ {
+ // Skip generic types to avoid typeof() formatting complexity
+ if (type.IsGenericType)
+ {
+ continue;
+ }
- // Prefer non-generic types to avoid typeof() formatting complexity
- var publicType = publicTypes.FirstOrDefault(t => !t.IsGenericType)
- ?? publicTypes.FirstOrDefault();
+ var metadataName = GetFullMetadataName(type);
+ var resolvedType = compilation.GetTypeByMetadataName(metadataName);
- if (publicType == null)
- {
- return null;
- }
+ // If Roslyn resolves to the same type, it's unambiguous - use it
+ // GetTypeByMetadataName returns null when the type name is ambiguous
+ if (SymbolEqualityComparer.Default.Equals(resolvedType, type))
+ {
+ return type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
+ }
- var typeName = publicType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
+ // null or different type = ambiguous, try next type
+ }
- // For generic types (fallback case), use open generic syntax for typeof()
- // Example: global::Foo -> global::Foo<>
- // Example: global::Foo -> global::Foo<,>
- if (publicType.IsGenericType)
+ // Fallback: try generic types if no non-generic unique type was found
+ foreach (var type in GetPublicTypesRecursive(assembly.GlobalNamespace))
{
- var openGenericSuffix = publicType.Arity == 1
- ? "<>"
- : $"<{new string(',', publicType.Arity - 1)}>";
+ if (!type.IsGenericType)
+ {
+ continue;
+ }
- // Remove everything from < to the end and append the open generic suffix
- var genericStart = typeName.LastIndexOf('<');
- if (genericStart > 0)
+ var metadataName = GetFullMetadataName(type);
+ var resolvedType = compilation.GetTypeByMetadataName(metadataName);
+
+ if (SymbolEqualityComparer.Default.Equals(resolvedType, type))
{
- typeName = typeName.Substring(0, genericStart) + openGenericSuffix;
+ var typeName = type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
+
+ // Use open generic syntax for typeof()
+ // Example: global::Foo -> global::Foo<>
+ // Example: global::Foo -> global::Foo<,>
+ var openGenericSuffix = type.Arity == 1
+ ? "<>"
+ : $"<{new string(',', type.Arity - 1)}>";
+
+ var genericStart = typeName.LastIndexOf('<');
+ if (genericStart > 0)
+ {
+ typeName = typeName.Substring(0, genericStart) + openGenericSuffix;
+ }
+
+ return typeName;
}
}
- return typeName;
+ return null; // No unique type found, skip this assembly
+ }
+
+ ///
+ /// Gets the full metadata name for a type (e.g., "Namespace.OuterClass+NestedClass").
+ /// This is the format expected by Compilation.GetTypeByMetadataName().
+ ///
+ private static string GetFullMetadataName(INamedTypeSymbol type)
+ {
+ if (type.ContainingType != null)
+ {
+ return $"{GetFullMetadataName(type.ContainingType)}+{type.MetadataName}";
+ }
+
+ if (type.ContainingNamespace.IsGlobalNamespace)
+ {
+ return type.MetadataName;
+ }
+
+ return $"{type.ContainingNamespace.ToDisplayString()}.{type.MetadataName}";
}
private static IEnumerable GetPublicTypesRecursive(INamespaceSymbol namespaceSymbol)