Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,21 @@ file static class AssemblyLoader_Guid
[global::System.Runtime.CompilerServices.ModuleInitializer]
public static void Initialize()
{
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("TUnit.Core.SourceGenerator.Tests, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("TUnit.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b8d4030011dbd70c"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("Verify.TUnit, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c7a34512ecd69090"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("Verify, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c7a34512ecd69090"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("Argon, Version=1.0.0.0, Culture=neutral, PublicKeyToken=00a55352ff068a54"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("DiffEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c7a34512ecd69090"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("EmptyFiles, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c7a34512ecd69090"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("SimpleInfoName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c7a34512ecd69090"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("TUnit.Assertions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b8d4030011dbd70c"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("TUnit.Core.SourceGenerator, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("TUnit.Engine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b8d4030011dbd70c"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("EnumerableAsyncProcessor, Version=2.1.0.0, Culture=neutral, PublicKeyToken=7a7adb9c614908c9"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("Sourcy.Core, Version=0.7.6.0, Culture=neutral, PublicKeyToken=null"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("TUnit.TestProject.Library, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,21 @@ file static class AssemblyLoader_Guid
[global::System.Runtime.CompilerServices.ModuleInitializer]
public static void Initialize()
{
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("TUnit.Core.SourceGenerator.Tests, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("TUnit.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b8d4030011dbd70c"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("Verify.TUnit, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c7a34512ecd69090"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("Verify, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c7a34512ecd69090"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("Argon, Version=1.0.0.0, Culture=neutral, PublicKeyToken=00a55352ff068a54"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("DiffEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c7a34512ecd69090"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("EmptyFiles, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c7a34512ecd69090"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("SimpleInfoName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c7a34512ecd69090"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("TUnit.Assertions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b8d4030011dbd70c"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("TUnit.Core.SourceGenerator, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("TUnit.Engine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b8d4030011dbd70c"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("EnumerableAsyncProcessor, Version=2.1.0.0, Culture=neutral, PublicKeyToken=7a7adb9c614908c9"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("Sourcy.Core, Version=0.7.6.0, Culture=neutral, PublicKeyToken=null"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("TUnit.TestProject.Library, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,21 @@ file static class AssemblyLoader_Guid
[global::System.Runtime.CompilerServices.ModuleInitializer]
public static void Initialize()
{
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("TUnit.Core.SourceGenerator.Tests, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("TUnit.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b8d4030011dbd70c"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("Verify.TUnit, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c7a34512ecd69090"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("Verify, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c7a34512ecd69090"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("Argon, Version=1.0.0.0, Culture=neutral, PublicKeyToken=00a55352ff068a54"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("DiffEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c7a34512ecd69090"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("EmptyFiles, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c7a34512ecd69090"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("SimpleInfoName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c7a34512ecd69090"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("TUnit.Assertions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b8d4030011dbd70c"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("TUnit.Core.SourceGenerator, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("TUnit.Engine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b8d4030011dbd70c"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("EnumerableAsyncProcessor, Version=2.1.0.0, Culture=neutral, PublicKeyToken=7a7adb9c614908c9"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("Sourcy.Core, Version=0.7.6.0, Culture=neutral, PublicKeyToken=null"));
global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load("TUnit.TestProject.Library, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"));
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,33 +1,41 @@
using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
using TUnit.Core.SourceGenerator.CodeGenerators.Equality;

namespace TUnit.Core.SourceGenerator.CodeGenerators;

[Generator]
public class AssemblyLoaderGenerator : IIncrementalGenerator
{
private static readonly string[] _excludedAssemblies =
[
"b77a5c561934e089",
"b03f5f7f11d50a3a",
"31bf3856ad364e35",
"cc7b13ffcd2ddd51",
"7cec85d7bea7798e",

];
public void Initialize(IncrementalGeneratorInitializationContext context)
{
var provider = context.CompilationProvider
.Select((x, _) => x.GetUsedAssemblyReferences())
.WithComparer(new AssemblyComparer())
.Combine(context.CompilationProvider);
.WithComparer(new PreventCompilationTriggerOnEveryKeystrokeComparer());

context.RegisterSourceOutput(provider, (sourceProductionContext, source) => GenerateCode(sourceProductionContext, source.Right, source.Left));
context.RegisterSourceOutput(provider, (sourceProductionContext, source) => GenerateCode(sourceProductionContext, source));
}

private void GenerateCode(SourceProductionContext context, Compilation compilation, ImmutableArray<MetadataReference> metadataReferences)
private void GenerateCode(SourceProductionContext context, Compilation compilation)
{
var assemblyReferences = metadataReferences
var assemblyReferences = compilation.References
.Where(x => x.Properties.Kind == MetadataImageKind.Assembly)
.Where(x => !string.IsNullOrEmpty(x.Display));

var assemblySymbols = assemblyReferences
.Select(compilation.GetAssemblyOrModuleSymbol)
.OfType<IAssemblySymbol>()
.Where(x => !IsSystemAssembly(x))
.Select(GetAssemblyFullName)
.Distinct();
.Distinct(SymbolEqualityComparer.Default)
.OfType<IAssemblySymbol>()
.ToArray();

var sourceBuilder = new SourceCodeWriter();

Expand All @@ -40,9 +48,10 @@ private void GenerateCode(SourceProductionContext context, Compilation compilati
sourceBuilder.WriteLine("public static void Initialize()");
sourceBuilder.WriteLine("{");

var visitedAssemblies = new HashSet<IAssemblySymbol>(SymbolEqualityComparer.Default);
foreach (var assembly in assemblySymbols)
{
sourceBuilder.WriteLine($"global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load(\"{assembly}\"));");
WriteAssemblyLoad(sourceBuilder, assembly, visitedAssemblies);
}

sourceBuilder.WriteLine("}");
Expand All @@ -51,43 +60,38 @@ private void GenerateCode(SourceProductionContext context, Compilation compilati
context.AddSource("AssemblyLoader.g.cs", sourceBuilder.ToString());
}

private static bool IsSystemAssembly(IAssemblySymbol assemblySymbol)
private static void WriteAssemblyLoad(SourceCodeWriter sourceBuilder, IAssemblySymbol assembly, HashSet<IAssemblySymbol> visitedAssemblies)
{
// Check for well-known public key tokens of system assemblies
var publicKeyToken = assemblySymbol.Identity.PublicKeyToken;
if (!visitedAssemblies.Add(assembly) || IsSystemAssembly(assembly))
{
return;
}

if (publicKeyToken == null)
sourceBuilder.WriteLine($"global::TUnit.Core.SourceRegistrar.RegisterAssembly(() => global::System.Reflection.Assembly.Load(\"{GetAssemblyFullName(assembly)}\"));");

foreach (var innerAssembly in assembly.Modules.SelectMany(x => x.ReferencedAssemblySymbols))
{
WriteAssemblyLoad(sourceBuilder, innerAssembly, visitedAssemblies);
}
}

private static bool IsSystemAssembly(IAssemblySymbol assemblySymbol)
{
if (assemblySymbol.Identity.PublicKeyToken.IsDefaultOrEmpty)
{
return false;
}

return publicKeyToken.SequenceEqual(new byte[] { 0xb7, 0x7a, 0x5c, 0x56, 0x19, 0x34, 0xe0, 0x89 }) // .NET Framework
|| publicKeyToken.SequenceEqual(new byte[] { 0x7c, 0xec, 0x85, 0xd7, 0xbe, 0xa7, 0x79, 0x8e }) // .NET Core
|| publicKeyToken.SequenceEqual(new byte[] { 0xcc, 0x7b, 0x13, 0xff, 0xcd, 0x2d, 0xdd, 0x51 }) // System.Private
|| publicKeyToken.SequenceEqual(new byte[] { 0xb0, 0x3f, 0x5f, 0x7f, 0x11, 0xd5, 0x0a, 0x3a }); // mscorlib
var stringPublicTokenKey = BitConverter.ToString(assemblySymbol.Identity.PublicKeyToken.ToArray())
.Replace("-", "")
.ToLowerInvariant();

return _excludedAssemblies.Contains(stringPublicTokenKey);
}

private static string GetAssemblyFullName(IAssemblySymbol assemblySymbol)
{
var identity = assemblySymbol.Identity;
return $"{identity.Name}, Version={identity.Version}, Culture={(string.IsNullOrEmpty(identity.CultureName) ? "neutral" : identity.CultureName)}, PublicKeyToken={(identity.PublicKeyToken.Length > 0 ? BitConverter.ToString(identity.PublicKeyToken.ToArray()).Replace("-", "").ToLowerInvariant() : "null")}";
}

private class AssemblyComparer : IEqualityComparer<ImmutableArray<MetadataReference>>
{
public bool Equals(ImmutableArray<MetadataReference> x, ImmutableArray<MetadataReference> y)
{
return GetAssemblyNamesString(x).Equals(GetAssemblyNamesString(y));
}

public int GetHashCode(ImmutableArray<MetadataReference> obj)
{
return GetAssemblyNamesString(obj).GetHashCode();
}

private static string GetAssemblyNamesString(ImmutableArray<MetadataReference> metadataReferences)
{
return string.Join("|", metadataReferences.Select(x => x.Display));
}
}
}
Loading