From ad3f6afb64300692ec943a8c38a93a48fa116dac Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Thu, 13 Jun 2024 16:26:02 +0100 Subject: [PATCH] DUI3-300 - add ProxyMap to source gen (#6) --- .../FileGenerators/ExtraFilesGenerator.cs | 66 ++++- .../FileGenerators/IFileGenerator.cs | 2 +- .../FileGenerators/ProxyClassesGenerator.cs | 20 +- .../ProxyInterfaceCodeGenerator.cs | 11 +- .../AkkaTests.cs | 2 +- .../InheritedInterfaceTests.cs | 9 +- .../PnPTests.cs | 2 +- ...y_Should_GenerateCorrectFiles.verified.txt | 183 +++++++++----- ...rateFiles_ForClassWithIgnores.verified.txt | 227 ++++++++++------- ...es_ForClassWith_BaseInterface.verified.txt | 227 ++++++++++------- ...teFiles_ForClassWith_Extended.verified.txt | 228 +++++++++++------- .../ProxyInterfaceSourceGeneratorTest.cs | 38 +-- 12 files changed, 678 insertions(+), 337 deletions(-) diff --git a/src/Speckle.ProxyGenerator/FileGenerators/ExtraFilesGenerator.cs b/src/Speckle.ProxyGenerator/FileGenerators/ExtraFilesGenerator.cs index 829d02d..98ac119 100644 --- a/src/Speckle.ProxyGenerator/FileGenerators/ExtraFilesGenerator.cs +++ b/src/Speckle.ProxyGenerator/FileGenerators/ExtraFilesGenerator.cs @@ -1,14 +1,22 @@ +using System.Text; using Speckle.ProxyGenerator.Extensions; using Speckle.ProxyGenerator.Models; namespace Speckle.ProxyGenerator.FileGenerators; +internal record ProxyMapItem(string BaseType, string InterfaceType, string ProxyType); internal class ExtraFilesGenerator : IFileGenerator { private const string Name = "Speckle.ProxyGenerator.Extra.g.cs"; - public FileData GenerateFile(bool supportsNullable) + public FileData GenerateFile(List proxyMapItems, bool supportsNullable) { + var sb = new StringBuilder(); + foreach (var item in proxyMapItems) + { + sb.AppendLine( + $"Add<{item.BaseType}, {item.InterfaceType}, {item.ProxyType}>(x => new {item.ProxyType}(x));"); + } return new FileData( $"{Name}", $@"//---------------------------------------------------------------------------------------- @@ -86,6 +94,62 @@ namespace Speckle.ProxyGenerator ProxyForBaseInterface = 8 }} + + public static class ProxyMap + {{ + private static readonly global::System.Collections.Concurrent.ConcurrentDictionary s_revitToInterfaceMap = new(); + private static readonly global::System.Collections.Concurrent.ConcurrentDictionary s_proxyToInterfaceMap = new(); + private static readonly global::System.Collections.Concurrent.ConcurrentDictionary s_interfaceToRevit = new(); + private static readonly global::System.Collections.Concurrent.ConcurrentDictionary> s_proxyFactory = new(); + + static ProxyMap() + {{ + {sb} + }} + + private static void Add(Func f) + where T : class + where TInterface : notnull + where TProxy : TInterface + {{ + s_revitToInterfaceMap.TryAdd(typeof(T), typeof(TInterface)); + s_proxyToInterfaceMap.TryAdd(typeof(TProxy), typeof(TInterface)); + s_proxyFactory.TryAdd(typeof(TInterface), w => f((T)w)); + s_interfaceToRevit.TryAdd(typeof(TInterface), typeof(T)); + }} + + public static Type? GetMappedTypeFromHostType(Type type) + {{ + if (s_revitToInterfaceMap.TryGetValue(type, out var t)) + {{ + return t; + }} + return null; + }} + + public static Type? GetMappedTypeFromProxyType(Type type) + {{ + if (s_proxyToInterfaceMap.TryGetValue(type, out var t)) + {{ + return t; + }} + + return null; + }} + + public static Type? GetHostTypeFromMappedType(Type type) + {{ + if (s_interfaceToRevit.TryGetValue(type, out var t)) + {{ + return t; + }} + + return null; + }} + + public static object CreateProxy(Type type, object toWrap) => s_proxyFactory[type](toWrap); + public static T CreateProxy(object toWrap) => (T)CreateProxy(typeof(T), toWrap); + }} {supportsNullable.IIf("#nullable restore")} }}" ); diff --git a/src/Speckle.ProxyGenerator/FileGenerators/IFileGenerator.cs b/src/Speckle.ProxyGenerator/FileGenerators/IFileGenerator.cs index 72e6eca..51ceac4 100644 --- a/src/Speckle.ProxyGenerator/FileGenerators/IFileGenerator.cs +++ b/src/Speckle.ProxyGenerator/FileGenerators/IFileGenerator.cs @@ -4,5 +4,5 @@ namespace Speckle.ProxyGenerator.FileGenerators; internal interface IFileGenerator { - FileData GenerateFile(bool supportsNullable); + FileData GenerateFile(List proxyMapItems, bool supportsNullable); } diff --git a/src/Speckle.ProxyGenerator/FileGenerators/ProxyClassesGenerator.cs b/src/Speckle.ProxyGenerator/FileGenerators/ProxyClassesGenerator.cs index f631082..e2e572e 100644 --- a/src/Speckle.ProxyGenerator/FileGenerators/ProxyClassesGenerator.cs +++ b/src/Speckle.ProxyGenerator/FileGenerators/ProxyClassesGenerator.cs @@ -12,8 +12,16 @@ namespace Speckle.ProxyGenerator.FileGenerators; internal partial class ProxyClassesGenerator : BaseGenerator, IFilesGenerator { - public ProxyClassesGenerator(Context context, bool supportsNullable) - : base(context, supportsNullable) { } + private readonly + List _proxyMapItems; + + public ProxyClassesGenerator( + List proxyMapItems, Context context, bool supportsNullable) + : base(context, supportsNullable) + { + _proxyMapItems = proxyMapItems; + + } public IEnumerable GenerateFiles() { @@ -55,9 +63,13 @@ internal partial class ProxyClassesGenerator : BaseGenerator, IFilesGenerator var constructorName = $"{targetClassSymbol.Symbol.Name}Proxy"; var extendsProxyClasses = GetExtendsProxyData(targetClassSymbol, false); - + var targetClass = targetClassSymbol.Symbol.GetFullMetadataName(); + if (!targetClassSymbol.Symbol.IsGenericType) + { + _proxyMapItems.Add(new(targetClass, interfaceName, $"{pd.NamespaceDot}{className}")); + } fileData = new FileData( - $"{targetClassSymbol.Symbol.GetFullMetadataName()}Proxy.g.cs", + $"{targetClass}Proxy.g.cs", CreateProxyClassCode( pd, targetClassSymbol, diff --git a/src/Speckle.ProxyGenerator/ProxyInterfaceCodeGenerator.cs b/src/Speckle.ProxyGenerator/ProxyInterfaceCodeGenerator.cs index 724d9eb..c323dfc 100644 --- a/src/Speckle.ProxyGenerator/ProxyInterfaceCodeGenerator.cs +++ b/src/Speckle.ProxyGenerator/ProxyInterfaceCodeGenerator.cs @@ -48,9 +48,10 @@ class ProxyInterfaceCodeGenerator : ISourceGenerator // https://github.com/reactiveui/refit/blob/main/InterfaceStubGenerator.Core/InterfaceStubGenerator.cs var supportsNullable = csharpParseOptions.LanguageVersion >= LanguageVersion.CSharp8; - GenerateProxyAttribute(context, receiver, supportsNullable); + var proxyItems = new List(); GeneratePartialInterfaces(context, receiver, supportsNullable); - GenerateProxyClasses(context, receiver, supportsNullable); + GenerateProxyClasses(proxyItems, context, receiver, supportsNullable); + GenerateProxyAttribute(proxyItems, context, receiver, supportsNullable); } catch (Exception exception) { @@ -66,6 +67,7 @@ class ProxyInterfaceCodeGenerator : ISourceGenerator } private void GenerateProxyAttribute( + List proxyMapItems, GeneratorExecutionContext ctx, ProxySyntaxReceiver receiver, bool supportsNullable @@ -77,7 +79,7 @@ class ProxyInterfaceCodeGenerator : ISourceGenerator Candidates = receiver.CandidateInterfaces }; - var attributeData = _proxyAttributeGenerator.GenerateFile(supportsNullable); + var attributeData = _proxyAttributeGenerator.GenerateFile(proxyMapItems, supportsNullable); context.GeneratorExecutionContext.AddSource( attributeData.FileName, SourceText.From(attributeData.Text, Encoding.UTF8) @@ -107,6 +109,7 @@ class ProxyInterfaceCodeGenerator : ISourceGenerator } private static void GenerateProxyClasses( + List proxyMapItems, GeneratorExecutionContext ctx, ProxySyntaxReceiver receiver, bool supportsNullable @@ -118,7 +121,7 @@ class ProxyInterfaceCodeGenerator : ISourceGenerator Candidates = receiver.CandidateInterfaces }; - var proxyClassesGenerator = new ProxyClassesGenerator(context, supportsNullable); + var proxyClassesGenerator = new ProxyClassesGenerator(proxyMapItems, context, supportsNullable); foreach (var (fileName, text) in proxyClassesGenerator.GenerateFiles()) { context.GeneratorExecutionContext.AddSource( diff --git a/tests/ProxyInterfaceSourceGeneratorTests/AkkaTests.cs b/tests/ProxyInterfaceSourceGeneratorTests/AkkaTests.cs index 87e543a..39bd79f 100644 --- a/tests/ProxyInterfaceSourceGeneratorTests/AkkaTests.cs +++ b/tests/ProxyInterfaceSourceGeneratorTests/AkkaTests.cs @@ -48,7 +48,7 @@ public class AkkaTests foreach (var fileName in fileNames.Select((fileName, index) => new { fileName, index })) { - var builder = result.Files[fileName.index + 1]; // +1 means skip the attribute + var builder = result.Files[fileName.index]; // attribute is last builder.Path.Should().EndWith(fileName.fileName); if (Write) diff --git a/tests/ProxyInterfaceSourceGeneratorTests/InheritedInterfaceTests.cs b/tests/ProxyInterfaceSourceGeneratorTests/InheritedInterfaceTests.cs index b373659..6f47cf3 100644 --- a/tests/ProxyInterfaceSourceGeneratorTests/InheritedInterfaceTests.cs +++ b/tests/ProxyInterfaceSourceGeneratorTests/InheritedInterfaceTests.cs @@ -58,7 +58,7 @@ public class InheritedInterfaceTests result.Files.Should().HaveCount(fileNames.Length + 1); WriteFiles(fileNames, result); - var interfaceIndex = 1; + var interfaceIndex = 0; var tree = result.Files[interfaceIndex].SyntaxTree; var root = tree.GetRoot(); var interfaceDeclarations = root.DescendantNodes().OfType(); @@ -91,7 +91,7 @@ public class InheritedInterfaceTests result.Files.Should().HaveCount(fileNames.Length + 1); WriteFiles(fileNames, result); - var interfaceIndex = 1; + var interfaceIndex = 0; var tree = result.Files[interfaceIndex].SyntaxTree; var root = tree.GetRoot(); var interfaceDeclarations = root.DescendantNodes().OfType(); @@ -148,7 +148,6 @@ public class InheritedInterfaceTests // Arrange string[] fileNames = [$"{Namespace}.{interfaceName}.g.cs", $"{Namespace}.{proxyName}.g.cs"]; - var interfaceIndex = 1; var path = $"./Source/Disposable/{interfaceName}.cs"; SourceFile sourceFile = CreateSourceFile(path, name, ImplementationOptions.UseExtendedInterfaces); @@ -159,6 +158,7 @@ public class InheritedInterfaceTests result.Files.Should().HaveCount(fileNames.Length + 1); WriteFiles(fileNames, result); + var interfaceIndex = 0; var tree = result.Files[interfaceIndex].SyntaxTree; var root = tree.GetRoot(); var interfaceDeclarations = root.DescendantNodes().OfType(); @@ -209,10 +209,11 @@ public class InheritedInterfaceTests { foreach (var fileName in fileNames.Select((fileName, index) => new { fileName, index })) { - var builder = result.Files[fileName.index + 1]; // +1 means skip the attribute + var builder = result.Files[fileName.index]; // attribute is always last builder.Path.Should().EndWith(fileName.fileName); File.WriteAllText($"{OutputPath}{fileName.fileName}", builder.Text); builder.Text.Should().Be(File.ReadAllText($"{OutputPath}{fileName.fileName}")); } } } + diff --git a/tests/ProxyInterfaceSourceGeneratorTests/PnPTests.cs b/tests/ProxyInterfaceSourceGeneratorTests/PnPTests.cs index 4b3b555..117be46 100644 --- a/tests/ProxyInterfaceSourceGeneratorTests/PnPTests.cs +++ b/tests/ProxyInterfaceSourceGeneratorTests/PnPTests.cs @@ -115,7 +115,7 @@ public class PnPTests foreach (var fileName in fileNames.Select((fileName, index) => new { fileName, index })) { - var builder = result.Files[fileName.index + 1]; // +1 means skip the attribute + var builder = result.Files[fileName.index]; // attribute is last builder.Path.Should().EndWith(fileName.fileName); if (Write) diff --git a/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForClassWithArray_Should_GenerateCorrectFiles.verified.txt b/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForClassWithArray_Should_GenerateCorrectFiles.verified.txt index c02c2f4..fb5222d 100644 --- a/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForClassWithArray_Should_GenerateCorrectFiles.verified.txt +++ b/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForClassWithArray_Should_GenerateCorrectFiles.verified.txt @@ -1,4 +1,76 @@ [ + { + HintName: ProxyInterfaceSourceGeneratorTests.Source.IFoo.g.cs, + Source: +//---------------------------------------------------------------------------------------- +// +// This code was generated by https://github.com/specklesystems/ProxyGenerator. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//---------------------------------------------------------------------------------------- + +#nullable enable +using System; + +namespace ProxyInterfaceSourceGeneratorTests.Source +{ + public partial interface IFoo + { + global::ProxyInterfaceSourceGeneratorTests.Source.Foo _Instance { get; } + + global::ProxyInterfaceSourceGeneratorTests.Source.IFoo[] Foos { get; set; } + + global::ProxyInterfaceSourceGeneratorTests.Source.IFoo[] DoSomethingAndGetAnArrayOfFoos(); + } +} +#nullable restore + }, + { + HintName: ProxyInterfaceSourceGeneratorTests.Source.FooProxy.g.cs, + Source: +//---------------------------------------------------------------------------------------- +// +// This code was generated by https://github.com/specklesystems/ProxyGenerator. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//---------------------------------------------------------------------------------------- + +#nullable enable +using System; + +namespace ProxyInterfaceSourceGeneratorTests.Source +{ + public partial class FooProxy : global::ProxyInterfaceSourceGeneratorTests.Source.IFoo + { + public global::ProxyInterfaceSourceGeneratorTests.Source.Foo _Instance { get; } + + public global::ProxyInterfaceSourceGeneratorTests.Source.IFoo[] Foos { get => Mapster.TypeAdapter.Adapt(_Instance.Foos); set => _Instance.Foos = Mapster.TypeAdapter.Adapt(value); } + + public global::ProxyInterfaceSourceGeneratorTests.Source.IFoo[] DoSomethingAndGetAnArrayOfFoos() + { + var result_1603865878 = _Instance.DoSomethingAndGetAnArrayOfFoos(); + return Mapster.TypeAdapter.Adapt(result_1603865878); + } + + + public FooProxy(global::ProxyInterfaceSourceGeneratorTests.Source.Foo instance) + { + _Instance = instance; + + + Mapster.TypeAdapterConfig.NewConfig().ConstructUsing(instance2058774601 => new global::ProxyInterfaceSourceGeneratorTests.Source.FooProxy(instance2058774601)); + Mapster.TypeAdapterConfig.NewConfig().MapWith(proxy1662609081 => ((global::ProxyInterfaceSourceGeneratorTests.Source.FooProxy) proxy1662609081)._Instance); + + + } + } +} +#nullable restore + }, { HintName: Speckle.ProxyGenerator.Extra.g.cs, Source: @@ -77,79 +149,72 @@ namespace Speckle.ProxyGenerator ProxyForBaseInterface = 8 } -#nullable restore -} - }, - { - HintName: ProxyInterfaceSourceGeneratorTests.Source.IFoo.g.cs, - Source: -//---------------------------------------------------------------------------------------- -// -// This code was generated by https://github.com/specklesystems/ProxyGenerator. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//---------------------------------------------------------------------------------------- -#nullable enable -using System; - -namespace ProxyInterfaceSourceGeneratorTests.Source -{ - public partial interface IFoo + public interface IProxyMap { - global::ProxyInterfaceSourceGeneratorTests.Source.Foo _Instance { get; } + Type? GetMappedTypeFromHostType(Type type); + Type? GetMappedTypeFromProxyType(Type type); + Type? GetHostTypeFromMappedType(Type type); - global::ProxyInterfaceSourceGeneratorTests.Source.IFoo[] Foos { get; set; } - - global::ProxyInterfaceSourceGeneratorTests.Source.IFoo[] DoSomethingAndGetAnArrayOfFoos(); + object CreateProxy(Type type, object toWrap); } -} -#nullable restore - }, - { - HintName: ProxyInterfaceSourceGeneratorTests.Source.FooProxy.g.cs, - Source: -//---------------------------------------------------------------------------------------- -// -// This code was generated by https://github.com/specklesystems/ProxyGenerator. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//---------------------------------------------------------------------------------------- -#nullable enable -using System; - -namespace ProxyInterfaceSourceGeneratorTests.Source -{ - public partial class FooProxy : global::ProxyInterfaceSourceGeneratorTests.Source.IFoo + public class ProxyMap : IProxyMap { - public global::ProxyInterfaceSourceGeneratorTests.Source.Foo _Instance { get; } - - public global::ProxyInterfaceSourceGeneratorTests.Source.IFoo[] Foos { get => Mapster.TypeAdapter.Adapt(_Instance.Foos); set => _Instance.Foos = Mapster.TypeAdapter.Adapt(value); } + private static readonly global::System.Collections.Concurrent.ConcurrentDictionary s_revitToInterfaceMap = new(); + private static readonly global::System.Collections.Concurrent.ConcurrentDictionary s_proxyToInterfaceMap = new(); + private static readonly global::System.Collections.Concurrent.ConcurrentDictionary s_interfaceToRevit = new(); + private static readonly global::System.Collections.Concurrent.ConcurrentDictionary> s_proxyFactory = new(); - public global::ProxyInterfaceSourceGeneratorTests.Source.IFoo[] DoSomethingAndGetAnArrayOfFoos() + static ProxyMap() + { + Add(x => new ProxyInterfaceSourceGeneratorTests.Source.FooProxy(x)); + + } + + private static void Add(Func f) + where T : class + where TInterface : notnull + where TProxy : TInterface + { + s_revitToInterfaceMap.TryAdd(typeof(T), typeof(TInterface)); + s_proxyToInterfaceMap.TryAdd(typeof(TProxy), typeof(TInterface)); + s_proxyFactory.TryAdd(typeof(TInterface), w => f((T)w)); + s_interfaceToRevit.TryAdd(typeof(TInterface), typeof(T)); + } + + public Type? GetMappedTypeFromHostType(Type type) + { + if (s_revitToInterfaceMap.TryGetValue(type, out var t)) { - var result_1603865878 = _Instance.DoSomethingAndGetAnArrayOfFoos(); - return Mapster.TypeAdapter.Adapt(result_1603865878); + return t; + } + return null; + } + + public Type? GetMappedTypeFromProxyType(Type type) + { + if (s_proxyToInterfaceMap.TryGetValue(type, out var t)) + { + return t; } + return null; + } - public FooProxy(global::ProxyInterfaceSourceGeneratorTests.Source.Foo instance) + public Type? GetHostTypeFromMappedType(Type type) + { + if (s_interfaceToRevit.TryGetValue(type, out var t)) { - _Instance = instance; - - - Mapster.TypeAdapterConfig.NewConfig().ConstructUsing(instance2058774601 => new global::ProxyInterfaceSourceGeneratorTests.Source.FooProxy(instance2058774601)); - Mapster.TypeAdapterConfig.NewConfig().MapWith(proxy1662609081 => ((global::ProxyInterfaceSourceGeneratorTests.Source.FooProxy) proxy1662609081)._Instance); - - + return t; } + + return null; + } + + public object CreateProxy(Type type, object toWrap) => s_proxyFactory[type](toWrap); } -} #nullable restore +} } ] \ No newline at end of file diff --git a/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForClassWithIgnores.verified.txt b/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForClassWithIgnores.verified.txt index cc514aa..83274e2 100644 --- a/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForClassWithIgnores.verified.txt +++ b/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForClassWithIgnores.verified.txt @@ -1,85 +1,4 @@ [ - { - HintName: Speckle.ProxyGenerator.Extra.g.cs, - Source: -//---------------------------------------------------------------------------------------- -// -// This code was generated by https://github.com/specklesystems/ProxyGenerator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//---------------------------------------------------------------------------------------- - -#nullable enable -using System; - -namespace Speckle.ProxyGenerator -{ - [AttributeUsage(AttributeTargets.Interface)] - internal sealed class ProxyAttribute : Attribute - { - public Type Type { get; } - public ImplementationOptions Options { get; } - public ProxyClassAccessibility Accessibility { get; } - public string[]? MembersToIgnore { get; } - - public ProxyAttribute(Type type) : this(type, ImplementationOptions.None, ProxyClassAccessibility.Public) - { - } - - public ProxyAttribute(Type type, ImplementationOptions options) : this(type, options, ProxyClassAccessibility.Public) - { - } - - public ProxyAttribute(Type type, ProxyClassAccessibility accessibility) : this(type, ImplementationOptions.None, accessibility) - { - } - - public ProxyAttribute(Type type, ImplementationOptions options, ProxyClassAccessibility accessibility) : this(type, options, accessibility, null) - { - } - - public ProxyAttribute(Type type, string[]? membersToIgnore) : this(type, ImplementationOptions.None, ProxyClassAccessibility.Public, null) - { - } - - public ProxyAttribute(Type type, ImplementationOptions options, string[]? membersToIgnore) : this(type, options, ProxyClassAccessibility.Public, null) - { - } - - public ProxyAttribute(Type type, ImplementationOptions options, ProxyClassAccessibility accessibility, string[]? membersToIgnore) - { - Type = type; - Options = options; - Accessibility = accessibility; - MembersToIgnore = membersToIgnore; - } - } - - [Flags] - internal enum ProxyClassAccessibility - { - Public = 0, - - Internal = 1 - } - [Flags] - internal enum ImplementationOptions - { - None = 0, - - ProxyBaseClasses = 1, - - ProxyInterfaces = 2, - - UseExtendedInterfaces = 4, - - ProxyForBaseInterface = 8 - } -#nullable restore -} - }, { HintName: ProxyInterfaceSourceGeneratorTests.Source.IFoo2.g.cs, Source: @@ -159,5 +78,151 @@ namespace ProxyInterfaceSourceGeneratorTests.Source } } #nullable restore + }, + { + HintName: Speckle.ProxyGenerator.Extra.g.cs, + Source: +//---------------------------------------------------------------------------------------- +// +// This code was generated by https://github.com/specklesystems/ProxyGenerator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//---------------------------------------------------------------------------------------- + +#nullable enable +using System; + +namespace Speckle.ProxyGenerator +{ + [AttributeUsage(AttributeTargets.Interface)] + internal sealed class ProxyAttribute : Attribute + { + public Type Type { get; } + public ImplementationOptions Options { get; } + public ProxyClassAccessibility Accessibility { get; } + public string[]? MembersToIgnore { get; } + + public ProxyAttribute(Type type) : this(type, ImplementationOptions.None, ProxyClassAccessibility.Public) + { + } + + public ProxyAttribute(Type type, ImplementationOptions options) : this(type, options, ProxyClassAccessibility.Public) + { + } + + public ProxyAttribute(Type type, ProxyClassAccessibility accessibility) : this(type, ImplementationOptions.None, accessibility) + { + } + + public ProxyAttribute(Type type, ImplementationOptions options, ProxyClassAccessibility accessibility) : this(type, options, accessibility, null) + { + } + + public ProxyAttribute(Type type, string[]? membersToIgnore) : this(type, ImplementationOptions.None, ProxyClassAccessibility.Public, null) + { + } + + public ProxyAttribute(Type type, ImplementationOptions options, string[]? membersToIgnore) : this(type, options, ProxyClassAccessibility.Public, null) + { + } + + public ProxyAttribute(Type type, ImplementationOptions options, ProxyClassAccessibility accessibility, string[]? membersToIgnore) + { + Type = type; + Options = options; + Accessibility = accessibility; + MembersToIgnore = membersToIgnore; + } + } + + [Flags] + internal enum ProxyClassAccessibility + { + Public = 0, + + Internal = 1 + } + [Flags] + internal enum ImplementationOptions + { + None = 0, + + ProxyBaseClasses = 1, + + ProxyInterfaces = 2, + + UseExtendedInterfaces = 4, + + ProxyForBaseInterface = 8 + } + + public interface IProxyMap + { + Type? GetMappedTypeFromHostType(Type type); + Type? GetMappedTypeFromProxyType(Type type); + Type? GetHostTypeFromMappedType(Type type); + + object CreateProxy(Type type, object toWrap); + } + + public class ProxyMap : IProxyMap + { + private static readonly global::System.Collections.Concurrent.ConcurrentDictionary s_revitToInterfaceMap = new(); + private static readonly global::System.Collections.Concurrent.ConcurrentDictionary s_proxyToInterfaceMap = new(); + private static readonly global::System.Collections.Concurrent.ConcurrentDictionary s_interfaceToRevit = new(); + private static readonly global::System.Collections.Concurrent.ConcurrentDictionary> s_proxyFactory = new(); + + static ProxyMap() + { + Add(x => new ProxyInterfaceSourceGeneratorTests.Source.Foo2Proxy(x)); + + } + + private static void Add(Func f) + where T : class + where TInterface : notnull + where TProxy : TInterface + { + s_revitToInterfaceMap.TryAdd(typeof(T), typeof(TInterface)); + s_proxyToInterfaceMap.TryAdd(typeof(TProxy), typeof(TInterface)); + s_proxyFactory.TryAdd(typeof(TInterface), w => f((T)w)); + s_interfaceToRevit.TryAdd(typeof(TInterface), typeof(T)); + } + + public Type? GetMappedTypeFromHostType(Type type) + { + if (s_revitToInterfaceMap.TryGetValue(type, out var t)) + { + return t; + } + return null; + } + + public Type? GetMappedTypeFromProxyType(Type type) + { + if (s_proxyToInterfaceMap.TryGetValue(type, out var t)) + { + return t; + } + + return null; + } + + public Type? GetHostTypeFromMappedType(Type type) + { + if (s_interfaceToRevit.TryGetValue(type, out var t)) + { + return t; + } + + return null; + } + + public object CreateProxy(Type type, object toWrap) => s_proxyFactory[type](toWrap); + } +#nullable restore +} } ] \ No newline at end of file diff --git a/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForClassWith_BaseInterface.verified.txt b/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForClassWith_BaseInterface.verified.txt index 8c30f36..2c705a1 100644 --- a/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForClassWith_BaseInterface.verified.txt +++ b/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForClassWith_BaseInterface.verified.txt @@ -1,85 +1,4 @@ [ - { - HintName: Speckle.ProxyGenerator.Extra.g.cs, - Source: -//---------------------------------------------------------------------------------------- -// -// This code was generated by https://github.com/specklesystems/ProxyGenerator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//---------------------------------------------------------------------------------------- - -#nullable enable -using System; - -namespace Speckle.ProxyGenerator -{ - [AttributeUsage(AttributeTargets.Interface)] - internal sealed class ProxyAttribute : Attribute - { - public Type Type { get; } - public ImplementationOptions Options { get; } - public ProxyClassAccessibility Accessibility { get; } - public string[]? MembersToIgnore { get; } - - public ProxyAttribute(Type type) : this(type, ImplementationOptions.None, ProxyClassAccessibility.Public) - { - } - - public ProxyAttribute(Type type, ImplementationOptions options) : this(type, options, ProxyClassAccessibility.Public) - { - } - - public ProxyAttribute(Type type, ProxyClassAccessibility accessibility) : this(type, ImplementationOptions.None, accessibility) - { - } - - public ProxyAttribute(Type type, ImplementationOptions options, ProxyClassAccessibility accessibility) : this(type, options, accessibility, null) - { - } - - public ProxyAttribute(Type type, string[]? membersToIgnore) : this(type, ImplementationOptions.None, ProxyClassAccessibility.Public, null) - { - } - - public ProxyAttribute(Type type, ImplementationOptions options, string[]? membersToIgnore) : this(type, options, ProxyClassAccessibility.Public, null) - { - } - - public ProxyAttribute(Type type, ImplementationOptions options, ProxyClassAccessibility accessibility, string[]? membersToIgnore) - { - Type = type; - Options = options; - Accessibility = accessibility; - MembersToIgnore = membersToIgnore; - } - } - - [Flags] - internal enum ProxyClassAccessibility - { - Public = 0, - - Internal = 1 - } - [Flags] - internal enum ImplementationOptions - { - None = 0, - - ProxyBaseClasses = 1, - - ProxyInterfaces = 2, - - UseExtendedInterfaces = 4, - - ProxyForBaseInterface = 8 - } -#nullable restore -} - }, { HintName: ProxyInterfaceSourceGeneratorTests.Source.IFoo2.g.cs, Source: @@ -161,5 +80,151 @@ namespace ProxyInterfaceSourceGeneratorTests.Source } } #nullable restore + }, + { + HintName: Speckle.ProxyGenerator.Extra.g.cs, + Source: +//---------------------------------------------------------------------------------------- +// +// This code was generated by https://github.com/specklesystems/ProxyGenerator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//---------------------------------------------------------------------------------------- + +#nullable enable +using System; + +namespace Speckle.ProxyGenerator +{ + [AttributeUsage(AttributeTargets.Interface)] + internal sealed class ProxyAttribute : Attribute + { + public Type Type { get; } + public ImplementationOptions Options { get; } + public ProxyClassAccessibility Accessibility { get; } + public string[]? MembersToIgnore { get; } + + public ProxyAttribute(Type type) : this(type, ImplementationOptions.None, ProxyClassAccessibility.Public) + { + } + + public ProxyAttribute(Type type, ImplementationOptions options) : this(type, options, ProxyClassAccessibility.Public) + { + } + + public ProxyAttribute(Type type, ProxyClassAccessibility accessibility) : this(type, ImplementationOptions.None, accessibility) + { + } + + public ProxyAttribute(Type type, ImplementationOptions options, ProxyClassAccessibility accessibility) : this(type, options, accessibility, null) + { + } + + public ProxyAttribute(Type type, string[]? membersToIgnore) : this(type, ImplementationOptions.None, ProxyClassAccessibility.Public, null) + { + } + + public ProxyAttribute(Type type, ImplementationOptions options, string[]? membersToIgnore) : this(type, options, ProxyClassAccessibility.Public, null) + { + } + + public ProxyAttribute(Type type, ImplementationOptions options, ProxyClassAccessibility accessibility, string[]? membersToIgnore) + { + Type = type; + Options = options; + Accessibility = accessibility; + MembersToIgnore = membersToIgnore; + } + } + + [Flags] + internal enum ProxyClassAccessibility + { + Public = 0, + + Internal = 1 + } + [Flags] + internal enum ImplementationOptions + { + None = 0, + + ProxyBaseClasses = 1, + + ProxyInterfaces = 2, + + UseExtendedInterfaces = 4, + + ProxyForBaseInterface = 8 + } + + public interface IProxyMap + { + Type? GetMappedTypeFromHostType(Type type); + Type? GetMappedTypeFromProxyType(Type type); + Type? GetHostTypeFromMappedType(Type type); + + object CreateProxy(Type type, object toWrap); + } + + public class ProxyMap : IProxyMap + { + private static readonly global::System.Collections.Concurrent.ConcurrentDictionary s_revitToInterfaceMap = new(); + private static readonly global::System.Collections.Concurrent.ConcurrentDictionary s_proxyToInterfaceMap = new(); + private static readonly global::System.Collections.Concurrent.ConcurrentDictionary s_interfaceToRevit = new(); + private static readonly global::System.Collections.Concurrent.ConcurrentDictionary> s_proxyFactory = new(); + + static ProxyMap() + { + Add(x => new ProxyInterfaceSourceGeneratorTests.Source.Foo2Proxy(x)); + + } + + private static void Add(Func f) + where T : class + where TInterface : notnull + where TProxy : TInterface + { + s_revitToInterfaceMap.TryAdd(typeof(T), typeof(TInterface)); + s_proxyToInterfaceMap.TryAdd(typeof(TProxy), typeof(TInterface)); + s_proxyFactory.TryAdd(typeof(TInterface), w => f((T)w)); + s_interfaceToRevit.TryAdd(typeof(TInterface), typeof(T)); + } + + public Type? GetMappedTypeFromHostType(Type type) + { + if (s_revitToInterfaceMap.TryGetValue(type, out var t)) + { + return t; + } + return null; + } + + public Type? GetMappedTypeFromProxyType(Type type) + { + if (s_proxyToInterfaceMap.TryGetValue(type, out var t)) + { + return t; + } + + return null; + } + + public Type? GetHostTypeFromMappedType(Type type) + { + if (s_interfaceToRevit.TryGetValue(type, out var t)) + { + return t; + } + + return null; + } + + public object CreateProxy(Type type, object toWrap) => s_proxyFactory[type](toWrap); + } +#nullable restore +} } ] \ No newline at end of file diff --git a/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForClassWith_Extended.verified.txt b/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForClassWith_Extended.verified.txt index a9e0fce..be6f694 100644 --- a/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForClassWith_Extended.verified.txt +++ b/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForClassWith_Extended.verified.txt @@ -1,85 +1,4 @@ [ - { - HintName: Speckle.ProxyGenerator.Extra.g.cs, - Source: -//---------------------------------------------------------------------------------------- -// -// This code was generated by https://github.com/specklesystems/ProxyGenerator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//---------------------------------------------------------------------------------------- - -#nullable enable -using System; - -namespace Speckle.ProxyGenerator -{ - [AttributeUsage(AttributeTargets.Interface)] - internal sealed class ProxyAttribute : Attribute - { - public Type Type { get; } - public ImplementationOptions Options { get; } - public ProxyClassAccessibility Accessibility { get; } - public string[]? MembersToIgnore { get; } - - public ProxyAttribute(Type type) : this(type, ImplementationOptions.None, ProxyClassAccessibility.Public) - { - } - - public ProxyAttribute(Type type, ImplementationOptions options) : this(type, options, ProxyClassAccessibility.Public) - { - } - - public ProxyAttribute(Type type, ProxyClassAccessibility accessibility) : this(type, ImplementationOptions.None, accessibility) - { - } - - public ProxyAttribute(Type type, ImplementationOptions options, ProxyClassAccessibility accessibility) : this(type, options, accessibility, null) - { - } - - public ProxyAttribute(Type type, string[]? membersToIgnore) : this(type, ImplementationOptions.None, ProxyClassAccessibility.Public, null) - { - } - - public ProxyAttribute(Type type, ImplementationOptions options, string[]? membersToIgnore) : this(type, options, ProxyClassAccessibility.Public, null) - { - } - - public ProxyAttribute(Type type, ImplementationOptions options, ProxyClassAccessibility accessibility, string[]? membersToIgnore) - { - Type = type; - Options = options; - Accessibility = accessibility; - MembersToIgnore = membersToIgnore; - } - } - - [Flags] - internal enum ProxyClassAccessibility - { - Public = 0, - - Internal = 1 - } - [Flags] - internal enum ImplementationOptions - { - None = 0, - - ProxyBaseClasses = 1, - - ProxyInterfaces = 2, - - UseExtendedInterfaces = 4, - - ProxyForBaseInterface = 8 - } -#nullable restore -} - }, { HintName: ProxyInterfaceSourceGeneratorTests.Source.IFoo3Proxy.g.cs, Source: @@ -209,5 +128,152 @@ namespace ProxyInterfaceSourceGeneratorTests.Source } } #nullable restore + }, + { + HintName: Speckle.ProxyGenerator.Extra.g.cs, + Source: +//---------------------------------------------------------------------------------------- +// +// This code was generated by https://github.com/specklesystems/ProxyGenerator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//---------------------------------------------------------------------------------------- + +#nullable enable +using System; + +namespace Speckle.ProxyGenerator +{ + [AttributeUsage(AttributeTargets.Interface)] + internal sealed class ProxyAttribute : Attribute + { + public Type Type { get; } + public ImplementationOptions Options { get; } + public ProxyClassAccessibility Accessibility { get; } + public string[]? MembersToIgnore { get; } + + public ProxyAttribute(Type type) : this(type, ImplementationOptions.None, ProxyClassAccessibility.Public) + { + } + + public ProxyAttribute(Type type, ImplementationOptions options) : this(type, options, ProxyClassAccessibility.Public) + { + } + + public ProxyAttribute(Type type, ProxyClassAccessibility accessibility) : this(type, ImplementationOptions.None, accessibility) + { + } + + public ProxyAttribute(Type type, ImplementationOptions options, ProxyClassAccessibility accessibility) : this(type, options, accessibility, null) + { + } + + public ProxyAttribute(Type type, string[]? membersToIgnore) : this(type, ImplementationOptions.None, ProxyClassAccessibility.Public, null) + { + } + + public ProxyAttribute(Type type, ImplementationOptions options, string[]? membersToIgnore) : this(type, options, ProxyClassAccessibility.Public, null) + { + } + + public ProxyAttribute(Type type, ImplementationOptions options, ProxyClassAccessibility accessibility, string[]? membersToIgnore) + { + Type = type; + Options = options; + Accessibility = accessibility; + MembersToIgnore = membersToIgnore; + } + } + + [Flags] + internal enum ProxyClassAccessibility + { + Public = 0, + + Internal = 1 + } + [Flags] + internal enum ImplementationOptions + { + None = 0, + + ProxyBaseClasses = 1, + + ProxyInterfaces = 2, + + UseExtendedInterfaces = 4, + + ProxyForBaseInterface = 8 + } + + public interface IProxyMap + { + Type? GetMappedTypeFromHostType(Type type); + Type? GetMappedTypeFromProxyType(Type type); + Type? GetHostTypeFromMappedType(Type type); + + object CreateProxy(Type type, object toWrap); + } + + public class ProxyMap : IProxyMap + { + private static readonly global::System.Collections.Concurrent.ConcurrentDictionary s_revitToInterfaceMap = new(); + private static readonly global::System.Collections.Concurrent.ConcurrentDictionary s_proxyToInterfaceMap = new(); + private static readonly global::System.Collections.Concurrent.ConcurrentDictionary s_interfaceToRevit = new(); + private static readonly global::System.Collections.Concurrent.ConcurrentDictionary> s_proxyFactory = new(); + + static ProxyMap() + { + Add(x => new ProxyInterfaceSourceGeneratorTests.Source.Foo3Proxy(x)); +Add(x => new ProxyInterfaceSourceGeneratorTests.Source.Bar3Proxy(x)); + + } + + private static void Add(Func f) + where T : class + where TInterface : notnull + where TProxy : TInterface + { + s_revitToInterfaceMap.TryAdd(typeof(T), typeof(TInterface)); + s_proxyToInterfaceMap.TryAdd(typeof(TProxy), typeof(TInterface)); + s_proxyFactory.TryAdd(typeof(TInterface), w => f((T)w)); + s_interfaceToRevit.TryAdd(typeof(TInterface), typeof(T)); + } + + public Type? GetMappedTypeFromHostType(Type type) + { + if (s_revitToInterfaceMap.TryGetValue(type, out var t)) + { + return t; + } + return null; + } + + public Type? GetMappedTypeFromProxyType(Type type) + { + if (s_proxyToInterfaceMap.TryGetValue(type, out var t)) + { + return t; + } + + return null; + } + + public Type? GetHostTypeFromMappedType(Type type) + { + if (s_interfaceToRevit.TryGetValue(type, out var t)) + { + return t; + } + + return null; + } + + public object CreateProxy(Type type, object toWrap) => s_proxyFactory[type](toWrap); + } +#nullable restore +} } ] \ No newline at end of file diff --git a/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.cs b/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.cs index ca18c74..fb107ff 100644 --- a/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.cs +++ b/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.cs @@ -248,7 +248,7 @@ public class ProxyInterfaceSourceGeneratorTest foreach (var fileName in fileNames.Select((fileName, index) => new { fileName, index })) { - var builder = result.Files[fileName.index + 1]; // +1 means skip the attribute + var builder = result.Files[fileName.index]; // attribute is last builder.Path.Should().EndWith(fileName.fileName); if (Write) @@ -288,7 +288,7 @@ public class ProxyInterfaceSourceGeneratorTest foreach (var fileName in fileNames.Select((fileName, index) => new { fileName, index })) { - var builder = result.Files[fileName.index + 1]; // +1 means skip the attribute + var builder = result.Files[fileName.index]; // attribute is last builder.Path.Should().EndWith(fileName.fileName); if (Write) @@ -328,7 +328,7 @@ public class ProxyInterfaceSourceGeneratorTest foreach (var fileName in fileNames.Select((fileName, index) => new { fileName, index })) { - var builder = result.Files[fileName.index + 1]; // +1 means skip the attribute + var builder = result.Files[fileName.index ]; // attribute is last builder.Path.Should().EndWith(fileName.fileName); if (Write) @@ -376,7 +376,7 @@ public class ProxyInterfaceSourceGeneratorTest foreach (var fileName in fileNames.Select((fileName, index) => new { fileName, index })) { - var builder = result.Files[fileName.index + 1]; // +1 means skip the attribute + var builder = result.Files[fileName.index]; // attribute is last builder.Path.Should().EndWith(fileName.fileName); if (Write) @@ -416,7 +416,7 @@ public class ProxyInterfaceSourceGeneratorTest foreach (var fileName in fileNames.Select((fileName, index) => new { fileName, index })) { - var builder = result.Files[fileName.index + 1]; // +1 means skip the attribute + var builder = result.Files[fileName.index]; // attribute is last builder.Path.Should().EndWith(fileName.fileName); if (Write) @@ -458,11 +458,11 @@ public class ProxyInterfaceSourceGeneratorTest result.Files.Should().HaveCount(3); // Assert attribute - var attribute = result.Files[0].SyntaxTree; + var attribute = result.Files.Last().SyntaxTree; attribute.FilePath.Should().EndWith(attributeFilename); // Assert interface - var @interface = result.Files[1].SyntaxTree; + var @interface = result.Files[0].SyntaxTree; @interface.FilePath.Should().EndWith(interfaceFilename); var interfaceCode = @interface.ToString(); @@ -474,7 +474,7 @@ public class ProxyInterfaceSourceGeneratorTest .And.Be(File.ReadAllText($"../../../Destination/{interfaceFilename}")); // Assert Proxy - var proxyClass = result.Files[2].SyntaxTree; + var proxyClass = result.Files[1].SyntaxTree; proxyClass.FilePath.Should().EndWith(proxyClassFilename); var proxyCode = proxyClass.ToString(); @@ -518,7 +518,7 @@ public class ProxyInterfaceSourceGeneratorTest result.Files.Should().HaveCount(3); // Assert interface - var @interface = result.Files[1].SyntaxTree; + var @interface = result.Files[0].SyntaxTree; @interface.FilePath.Should().EndWith(interfaceFilename); var interfaceCode = @interface.ToString(); @@ -530,7 +530,7 @@ public class ProxyInterfaceSourceGeneratorTest .And.Be(File.ReadAllText($"../../../Destination/{interfaceFilename}")); // Assert Proxy - var proxyClass = result.Files[2].SyntaxTree; + var proxyClass = result.Files[1].SyntaxTree; proxyClass.FilePath.Should().EndWith(proxyClassFilename); var proxyCode = proxyClass.ToString(); @@ -584,11 +584,11 @@ public class ProxyInterfaceSourceGeneratorTest result.Files.Should().HaveCount(5); // Assert attribute - var attribute = result.Files[0].SyntaxTree; + var attribute = result.Files.Last().SyntaxTree; attribute.FilePath.Should().EndWith(attributeFilename); // Assert interface Human - var interfaceHuman = result.Files[1].SyntaxTree; + var interfaceHuman = result.Files[0].SyntaxTree; interfaceHuman.FilePath.Should().EndWith(interfaceHumanFilename); var interfaceCodeHuman = interfaceHuman.ToString(); @@ -600,7 +600,7 @@ public class ProxyInterfaceSourceGeneratorTest .And.Be(File.ReadAllText($"../../../Destination/{interfaceHumanFilename}")); // Assert interface Person - var interfacePerson = result.Files[2].SyntaxTree; + var interfacePerson = result.Files[1].SyntaxTree; interfacePerson.FilePath.Should().EndWith(interfacePersonFilename); var interfaceCodePerson = interfacePerson.ToString(); @@ -690,11 +690,11 @@ public class ProxyInterfaceSourceGeneratorTest result.Files.Should().HaveCount(5); // Assert attribute - var attribute = result.Files[0].SyntaxTree; + var attribute = result.Files.Last().SyntaxTree; attribute.FilePath.Should().EndWith(attributeFilename); // Assert interface IHttpClient - var interfaceIHttpClient = result.Files[1].SyntaxTree; + var interfaceIHttpClient = result.Files[0].SyntaxTree; interfaceIHttpClient.FilePath.Should().EndWith(interfaceIHttpClientFilename); var interfaceCodeIHttpClient = interfaceIHttpClient.ToString(); @@ -709,7 +709,7 @@ public class ProxyInterfaceSourceGeneratorTest .And.Be(File.ReadAllText($"../../../Destination/{interfaceIHttpClientFilename}")); // Assert interface IHttpMessageInvoker - var interfaceIMessageInvoker = result.Files[2].SyntaxTree; + var interfaceIMessageInvoker = result.Files[1].SyntaxTree; interfaceIMessageInvoker.FilePath.Should().EndWith(interfaceIHttpMessageInvokerFilename); var interfaceCodeIMessageInvoker = interfaceIMessageInvoker.ToString(); @@ -795,11 +795,11 @@ public class ProxyInterfaceSourceGeneratorTest result.Files.Should().HaveCount(3); // Assert attribute - var attribute = result.Files[0].SyntaxTree; + var attribute = result.Files.Last().SyntaxTree; attribute.FilePath.Should().EndWith(attributeFilename); // Assert interface - var @interface = result.Files[1].SyntaxTree; + var @interface = result.Files[0].SyntaxTree; @interface.FilePath.Should().EndWith(interfaceFilename); var interfaceCode = @interface.ToString(); @@ -811,7 +811,7 @@ public class ProxyInterfaceSourceGeneratorTest .And.Be(File.ReadAllText($"../../../Destination/{interfaceFilename}")); // Assert Proxy - var proxyClass = result.Files[2].SyntaxTree; + var proxyClass = result.Files[1].SyntaxTree; proxyClass.FilePath.Should().EndWith(proxyClassFilename); var proxyCode = proxyClass.ToString();