diff --git a/src-examples/ProxyInterfaceConsumer/IAddress.cs b/src-examples/ProxyInterfaceConsumer/IAddress.cs index 4481daa..f92df07 100644 --- a/src-examples/ProxyInterfaceConsumer/IAddress.cs +++ b/src-examples/ProxyInterfaceConsumer/IAddress.cs @@ -2,7 +2,12 @@ using Speckle.ProxyGenerator; namespace ProxyInterfaceConsumer { - [Proxy(typeof(Address), ImplementationOptions.ProxyBaseClasses, ProxyClassAccessibility.Public, new[] { "Weird" })] + [Proxy( + typeof(Address), + ImplementationOptions.ProxyBaseClasses, + ProxyClassAccessibility.Public, + new[] { "Weird" } + )] public partial interface IAddress { public void Weird() diff --git a/src/Speckle.ProxyGenerator/Extensions/NamedTypeSymbolExtensions.cs b/src/Speckle.ProxyGenerator/Extensions/NamedTypeSymbolExtensions.cs index 859578c..9a7751b 100644 --- a/src/Speckle.ProxyGenerator/Extensions/NamedTypeSymbolExtensions.cs +++ b/src/Speckle.ProxyGenerator/Extensions/NamedTypeSymbolExtensions.cs @@ -110,7 +110,8 @@ internal static class NamedTypeSymbolExtensions } public static IEnumerable ResolveBaseInterfaces( - this INamedTypeSymbol symbol, List previousInterfaces + this INamedTypeSymbol symbol, + List previousInterfaces ) { // Direct interfaces, recursive interfaces or base class interfaces should go here. diff --git a/src/Speckle.ProxyGenerator/FileGenerators/BaseGenerator.cs b/src/Speckle.ProxyGenerator/FileGenerators/BaseGenerator.cs index d79f9f1..b7e8c3c 100644 --- a/src/Speckle.ProxyGenerator/FileGenerators/BaseGenerator.cs +++ b/src/Speckle.ProxyGenerator/FileGenerators/BaseGenerator.cs @@ -36,7 +36,9 @@ internal abstract class BaseGenerator [NotNullWhen(true)] out ProxyData? proxyData ) { - proxyData = Context.Candidates.Values.FirstOrDefault(x => x.FullQualifiedMappedTypeName == type); + proxyData = Context.Candidates.Values.FirstOrDefault(x => + x.FullQualifiedMappedTypeName == type + ); if (proxyData is not null) { return true; @@ -213,7 +215,7 @@ internal abstract class BaseGenerator } protected bool TryGetNamedTypeSymbolByFullName( - TypeKind kind, + TypeKind[] kind, string name, IEnumerable usings, [NotNullWhen(true)] out ClassSymbol? classSymbol @@ -228,7 +230,7 @@ internal abstract class BaseGenerator // The GetTypeByMetadataName method returns null if no type matches the full name or if 2 or more types (in different assemblies) match the full name. var symbol = Context.GeneratorExecutionContext.Compilation.GetTypeByMetadataName(name); - if (symbol is not null && symbol.TypeKind == kind) + if (symbol is not null && kind.Contains(symbol.TypeKind)) { classSymbol = new ClassSymbol( symbol, @@ -243,7 +245,7 @@ internal abstract class BaseGenerator symbol = Context.GeneratorExecutionContext.Compilation.GetTypeByMetadataName( $"{@using}.{name}" ); - if (symbol is not null && symbol.TypeKind == kind) + if (symbol is not null && kind.Contains(symbol.TypeKind)) { classSymbol = new ClassSymbol( symbol, @@ -288,7 +290,8 @@ internal abstract class BaseGenerator } protected IReadOnlyList GetExtendsProxyData( - ClassSymbol targetClassSymbol, bool useFullQualifiedMappedTypeName + ClassSymbol targetClassSymbol, + bool useFullQualifiedMappedTypeName ) { var extendsProxyClasses = new List(); diff --git a/src/Speckle.ProxyGenerator/FileGenerators/ExtraFilesGenerator.cs b/src/Speckle.ProxyGenerator/FileGenerators/ExtraFilesGenerator.cs index 98ac119..6d87a5d 100644 --- a/src/Speckle.ProxyGenerator/FileGenerators/ExtraFilesGenerator.cs +++ b/src/Speckle.ProxyGenerator/FileGenerators/ExtraFilesGenerator.cs @@ -5,6 +5,7 @@ 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"; @@ -15,7 +16,8 @@ internal class ExtraFilesGenerator : IFileGenerator foreach (var item in proxyMapItems) { sb.AppendLine( - $"Add<{item.BaseType}, {item.InterfaceType}, {item.ProxyType}>(x => new {item.ProxyType}(x));"); + $"Add<{item.BaseType}, {item.InterfaceType}, {item.ProxyType}>(x => new {item.ProxyType}(x));" + ); } return new FileData( $"{Name}", @@ -108,7 +110,6 @@ namespace Speckle.ProxyGenerator }} private static void Add(Func f) - where T : class where TInterface : notnull where TProxy : TInterface {{ diff --git a/src/Speckle.ProxyGenerator/FileGenerators/PartialInterfacesGenerator.cs b/src/Speckle.ProxyGenerator/FileGenerators/PartialInterfacesGenerator.cs index 901182c..1426082 100644 --- a/src/Speckle.ProxyGenerator/FileGenerators/PartialInterfacesGenerator.cs +++ b/src/Speckle.ProxyGenerator/FileGenerators/PartialInterfacesGenerator.cs @@ -38,7 +38,7 @@ internal class PartialInterfacesGenerator : BaseGenerator, IFilesGenerator if ( !TryGetNamedTypeSymbolByFullName( - TypeKind.Interface, + [TypeKind.Interface], ci.Identifier.ToString(), pd.Usings, out var sourceInterfaceSymbol @@ -50,7 +50,7 @@ internal class PartialInterfacesGenerator : BaseGenerator, IFilesGenerator if ( !TryGetNamedTypeSymbolByFullName( - TypeKind.Class, + [TypeKind.Class, TypeKind.Struct], pd.FullMetadataTypeName, pd.Usings, out var targetClassSymbol @@ -67,7 +67,13 @@ internal class PartialInterfacesGenerator : BaseGenerator, IFilesGenerator fileData = new FileData( $"{sourceInterfaceSymbol.Symbol.GetFullMetadataName()}.g.cs", - CreatePartialInterfaceCode(pd.Namespace, targetClassSymbol, sourceInterfaceSymbol,interfaceName, pd) + CreatePartialInterfaceCode( + pd.Namespace, + targetClassSymbol, + sourceInterfaceSymbol, + interfaceName, + pd + ) ); return true; @@ -82,16 +88,24 @@ internal class PartialInterfacesGenerator : BaseGenerator, IFilesGenerator ) { _implementedInterfaces.Clear(); - _implementedInterfaces.AddRange(classSymbol.Symbol.ResolveImplementedInterfaces( - proxyData.Options.HasFlag(ImplementationOptions.ProxyBaseClasses), - proxyData.Options.HasFlag(ImplementationOptions.ProxyInterfaces) - )); + _implementedInterfaces.AddRange( + classSymbol.Symbol.ResolveImplementedInterfaces( + proxyData.Options.HasFlag(ImplementationOptions.ProxyBaseClasses), + proxyData.Options.HasFlag(ImplementationOptions.ProxyInterfaces) + ) + ); if (proxyData.Options.HasFlag(ImplementationOptions.UseExtendedInterfaces)) { - var bases = interfaceSymbol.Symbol.ResolveBaseInterfaces(_implementedInterfaces).ToList(); - if (bases.Count == 1 && proxyData.Options.HasFlag(ImplementationOptions.ProxyForBaseInterface)) + var bases = interfaceSymbol + .Symbol.ResolveBaseInterfaces(_implementedInterfaces) + .ToList(); + if ( + bases.Count == 1 + && proxyData.Options.HasFlag(ImplementationOptions.ProxyForBaseInterface) + ) { - proxyData.FullQualifiedMappedTypeName = globalPrefix + bases.Single().GetFullMetadataName(); + proxyData.FullQualifiedMappedTypeName = + globalPrefix + bases.Single().GetFullMetadataName(); } _implementedInterfaces.AddRange(bases); //don't readd self @@ -102,7 +116,11 @@ internal class PartialInterfacesGenerator : BaseGenerator, IFilesGenerator } _implementedInterfaces = _implementedInterfaces.Distinct().ToList(); - var isNew = GetExtendsProxyData(classSymbol, proxyData.Options.HasFlag(ImplementationOptions.UseExtendedInterfaces)).Any(); + var isNew = GetExtendsProxyData( + classSymbol, + proxyData.Options.HasFlag(ImplementationOptions.UseExtendedInterfaces) + ) + .Any(); var implementedInterfacesNames = _implementedInterfaces .Select(i => i.ToFullyQualifiedDisplayString()) diff --git a/src/Speckle.ProxyGenerator/FileGenerators/ProxyClassesGenerator.cs b/src/Speckle.ProxyGenerator/FileGenerators/ProxyClassesGenerator.cs index ea583f6..be1dc00 100644 --- a/src/Speckle.ProxyGenerator/FileGenerators/ProxyClassesGenerator.cs +++ b/src/Speckle.ProxyGenerator/FileGenerators/ProxyClassesGenerator.cs @@ -12,15 +12,16 @@ namespace Speckle.ProxyGenerator.FileGenerators; internal partial class ProxyClassesGenerator : BaseGenerator, IFilesGenerator { - private readonly - List _proxyMapItems; + private readonly List _proxyMapItems; public ProxyClassesGenerator( - List proxyMapItems, Context context, bool supportsNullable) + List proxyMapItems, + Context context, + bool supportsNullable + ) : base(context, supportsNullable) { _proxyMapItems = proxyMapItems; - } public IEnumerable GenerateFiles() @@ -45,7 +46,7 @@ internal partial class ProxyClassesGenerator : BaseGenerator, IFilesGenerator if ( !TryGetNamedTypeSymbolByFullName( - TypeKind.Class, + [TypeKind.Class, TypeKind.Struct], pd.FullMetadataTypeName, pd.Usings, out var targetClassSymbol @@ -76,7 +77,8 @@ internal partial class ProxyClassesGenerator : BaseGenerator, IFilesGenerator extendsProxyClasses, interfaceName, className, - constructorName + constructorName, + targetClassSymbol.Symbol.TypeKind ) ); @@ -89,7 +91,8 @@ internal partial class ProxyClassesGenerator : BaseGenerator, IFilesGenerator IReadOnlyList extendsProxyClasses, string interfaceName, string className, - string constructorName + string constructorName, + TypeKind kind ) { var firstExtends = extendsProxyClasses.FirstOrDefault(); @@ -125,7 +128,8 @@ internal partial class ProxyClassesGenerator : BaseGenerator, IFilesGenerator var staticConstructor = string.Empty; if (!string.IsNullOrWhiteSpace(configurationForMapster)) { - staticConstructor = $@" + staticConstructor = + $@" static {constructorName}() {{ {configurationForMapster} @@ -138,6 +142,8 @@ internal partial class ProxyClassesGenerator : BaseGenerator, IFilesGenerator var accessibility = pd.Accessibility == ProxyClassAccessibility.Internal ? "internal" : "public"; + var kindString = kind == TypeKind.Class ? "class" : "struct"; + return $@"//---------------------------------------------------------------------------------------- // // This code was generated by https://github.com/specklesystems/ProxyGenerator. @@ -151,14 +157,14 @@ internal partial class ProxyClassesGenerator : BaseGenerator, IFilesGenerator using System; {namespaceStart} - {accessibility} {@abstract}partial class {className} : {extends}{interfaceName} + {accessibility} {@abstract}partial {kindString} {className} : {extends}{interfaceName} {{ public {@new}{targetClassSymbol} _Instance {{ get; }} {instanceBaseDefinition} {events + -properties + -methods + -operators} + properties + + methods + + operators} public {constructorName}({targetClassSymbol} instance){@base} {{ _Instance = instance; @@ -202,7 +208,9 @@ operators} } var getIsPublic = property.GetMethod.IsPublic(); - var setIsPublic = property.SetMethod.IsPublic(); + var setIsPublic = + property.SetMethod.IsPublic() + && targetClassSymbol.Symbol.TypeKind == TypeKind.Class; if (!getIsPublic && !setIsPublic) { @@ -267,7 +275,7 @@ operators} if (method.IsOverride && method.OverriddenMethod != null) { var baseType = method.OverriddenMethod.ContainingType.GetFullType(); - if (TryGetNamedTypeSymbolByFullName(TypeKind.Class, baseType, [], out _)) + if (TryGetNamedTypeSymbolByFullName([TypeKind.Class], baseType, [], out _)) { overrideOrVirtual = "override "; } @@ -342,14 +350,10 @@ operators} foreach (var ps in method.Parameters.Where(p => p.RefKind == RefKind.Out)) { string normalOrMap = $" = {ps.GetSanitizedName()}_"; - if (ps.GetTypeEnum() == TypeEnum.Complex) + var type = GetParameterType(ps, out var isReplaced); + if (isReplaced) { - var type = GetParameterType(ps, out var isReplaced); - if (isReplaced) - { - normalOrMap = - $" = Mapster.TypeAdapter.Adapt<{type}>({ps.GetSanitizedName()}_)"; - } + normalOrMap = $" = Mapster.TypeAdapter.Adapt<{type}>({ps.GetSanitizedName()}_)"; } str.AppendLine($" {ps.GetSanitizedName()}{normalOrMap};"); diff --git a/src/Speckle.ProxyGenerator/ProxyInterfaceCodeGenerator.cs b/src/Speckle.ProxyGenerator/ProxyInterfaceCodeGenerator.cs index c323dfc..f1264ca 100644 --- a/src/Speckle.ProxyGenerator/ProxyInterfaceCodeGenerator.cs +++ b/src/Speckle.ProxyGenerator/ProxyInterfaceCodeGenerator.cs @@ -121,7 +121,11 @@ class ProxyInterfaceCodeGenerator : ISourceGenerator Candidates = receiver.CandidateInterfaces }; - var proxyClassesGenerator = new ProxyClassesGenerator(proxyMapItems, context, supportsNullable); + var proxyClassesGenerator = new ProxyClassesGenerator( + proxyMapItems, + context, + supportsNullable + ); foreach (var (fileName, text) in proxyClassesGenerator.GenerateFiles()) { context.GeneratorExecutionContext.AddSource( diff --git a/src/Speckle.ProxyGenerator/SyntaxReceiver/AttributeArgumentListParser.cs b/src/Speckle.ProxyGenerator/SyntaxReceiver/AttributeArgumentListParser.cs index ab2b8f5..1eb049f 100644 --- a/src/Speckle.ProxyGenerator/SyntaxReceiver/AttributeArgumentListParser.cs +++ b/src/Speckle.ProxyGenerator/SyntaxReceiver/AttributeArgumentListParser.cs @@ -94,8 +94,10 @@ internal static class AttributeArgumentListParser { return false; } - var splitter = new[] {$"{typeof(TEnum).Name}."}; - var vals = enumAsString.Split(splitter, StringSplitOptions.RemoveEmptyEntries).Select(x => x.TrimEnd(' ', '|')); + var splitter = new[] { $"{typeof(TEnum).Name}." }; + var vals = enumAsString + .Split(splitter, StringSplitOptions.RemoveEmptyEntries) + .Select(x => x.TrimEnd(' ', '|')); long l = 0; foreach (var v in vals) @@ -105,7 +107,8 @@ internal static class AttributeArgumentListParser l |= Convert.ToInt64(e); } } - value = (TEnum)Enum.ToObject(typeof(TEnum), l);; + value = (TEnum)Enum.ToObject(typeof(TEnum), l); + ; return true; } diff --git a/src/Speckle.ProxyGenerator/Types/ProxyInterfaceGeneratorAccessibility.cs b/src/Speckle.ProxyGenerator/Types/ProxyInterfaceGeneratorAccessibility.cs index 2ebf158..2c5bf50 100644 --- a/src/Speckle.ProxyGenerator/Types/ProxyInterfaceGeneratorAccessibility.cs +++ b/src/Speckle.ProxyGenerator/Types/ProxyInterfaceGeneratorAccessibility.cs @@ -13,9 +13,9 @@ internal enum ImplementationOptions { None = 0, - ProxyBaseClasses = 1, + ProxyBaseClasses = 1, - ProxyInterfaces = 2, + ProxyInterfaces = 2, UseExtendedInterfaces = 4, diff --git a/tests/ProxyInterfaceSourceGeneratorTests/AkkaTests.cs b/tests/ProxyInterfaceSourceGeneratorTests/AkkaTests.cs index 39bd79f..19e0917 100644 --- a/tests/ProxyInterfaceSourceGeneratorTests/AkkaTests.cs +++ b/tests/ProxyInterfaceSourceGeneratorTests/AkkaTests.cs @@ -35,7 +35,11 @@ public class AkkaTests AttributeToAddToInterface = new ExtraAttribute { Name = "Speckle.ProxyGenerator.Proxy", - ArgumentList = new [] {"typeof(Akka.Actor.LocalActorRefProvider)","ImplementationOptions.ProxyInterfaces"} + ArgumentList = new[] + { + "typeof(Akka.Actor.LocalActorRefProvider)", + "ImplementationOptions.ProxyInterfaces" + } } }; diff --git a/tests/ProxyInterfaceSourceGeneratorTests/InheritedInterfaceTests.cs b/tests/ProxyInterfaceSourceGeneratorTests/InheritedInterfaceTests.cs index 6f47cf3..c7e7a8c 100644 --- a/tests/ProxyInterfaceSourceGeneratorTests/InheritedInterfaceTests.cs +++ b/tests/ProxyInterfaceSourceGeneratorTests/InheritedInterfaceTests.cs @@ -6,6 +6,7 @@ using ProxyInterfaceSourceGeneratorTests.Source.Disposable; using Speckle.ProxyGenerator; namespace ProxyInterfaceSourceGeneratorTests; + [Flags] public enum ImplementationOptions { @@ -19,6 +20,7 @@ public enum ImplementationOptions ProxyForBaseInterface = 8 } + public class InheritedInterfaceTests { private const string Namespace = "ProxyInterfaceSourceGeneratorTests.Source.Disposable"; @@ -36,7 +38,10 @@ public class InheritedInterfaceTests [Theory] [InlineData(ImplementationOptions.None, false)] - [InlineData(ImplementationOptions.ProxyBaseClasses | ImplementationOptions.ProxyInterfaces, true)] + [InlineData( + ImplementationOptions.ProxyBaseClasses | ImplementationOptions.ProxyInterfaces, + true + )] public void GenerateFiles_InheritedInterface_InheritFromBaseClass( ImplementationOptions options, bool inheritBaseInterface @@ -49,7 +54,7 @@ public class InheritedInterfaceTests // Arrange string[] fileNames = [$"{Namespace}.{interfaceName}.g.cs", $"{Namespace}.{proxyName}.g.cs"]; var path = $"./Source/Disposable/{interfaceName}.cs"; - SourceFile sourceFile = CreateSourceFile(path, name,options); + SourceFile sourceFile = CreateSourceFile(path, name, options); // Act var result = _sut.Execute([sourceFile]); @@ -82,7 +87,13 @@ public class InheritedInterfaceTests string[] fileNames = [$"{Namespace}.{interfaceName}.g.cs", $"{Namespace}.{proxyName}.g.cs"]; var path = $"./Source/Disposable/{interfaceName}.cs"; - SourceFile sourceFile = CreateSourceFile(path, name, ImplementationOptions.ProxyInterfaces | ImplementationOptions.ProxyBaseClasses | ImplementationOptions.UseExtendedInterfaces); + SourceFile sourceFile = CreateSourceFile( + path, + name, + ImplementationOptions.ProxyInterfaces + | ImplementationOptions.ProxyBaseClasses + | ImplementationOptions.UseExtendedInterfaces + ); // Act var result = _sut.Execute([sourceFile]); @@ -111,24 +122,39 @@ public class InheritedInterfaceTests { var className1 = "LocationPoint"; var interfaceName1 = "IRevitLocationPointProxy"; - var proxyName1 = $"{className1}Proxy"; + var proxyName1 = $"{className1}Proxy"; // Arrange var path1 = $"./Source/Disposable/{interfaceName1}.cs"; - var sourceFile1 = CreateSourceFile(path1, className1, ImplementationOptions.ProxyForBaseInterface | ImplementationOptions.UseExtendedInterfaces); + var sourceFile1 = CreateSourceFile( + path1, + className1, + ImplementationOptions.ProxyForBaseInterface + | ImplementationOptions.UseExtendedInterfaces + ); var className2 = "Location"; var interfaceName2 = "IRevitLocationProxy"; - var proxyName2 = $"{className2}Proxy"; + var proxyName2 = $"{className2}Proxy"; // Arrange var path2 = $"./Source/Disposable/{interfaceName2}.cs"; - var sourceFile2 = CreateSourceFile(path2, className2, ImplementationOptions.ProxyForBaseInterface | ImplementationOptions.UseExtendedInterfaces); + var sourceFile2 = CreateSourceFile( + path2, + className2, + ImplementationOptions.ProxyForBaseInterface + | ImplementationOptions.UseExtendedInterfaces + ); // Act var result = _sut.Execute([sourceFile1, sourceFile2]); - string[] fileNames = [$"{Namespace}.{interfaceName1}.g.cs", $"{Namespace}.{proxyName1}.g.cs", - $"{Namespace}.{interfaceName2}.g.cs", $"{Namespace}.{proxyName2}.g.cs"]; + string[] fileNames = + [ + $"{Namespace}.{interfaceName1}.g.cs", + $"{Namespace}.{proxyName1}.g.cs", + $"{Namespace}.{interfaceName2}.g.cs", + $"{Namespace}.{proxyName2}.g.cs" + ]; result.Valid.Should().BeTrue(); result.Files.Should().HaveCount(fileNames.Length + 1); @@ -139,6 +165,7 @@ public class InheritedInterfaceTests File.WriteAllText($"{OutputPath}{fileName.fileName}", builder.Text); } } + [Fact] public void GenerateFiles_InheritedInterface_Should_Not_InheritExplicitImplementedInterfaces() { @@ -149,7 +176,11 @@ public class InheritedInterfaceTests // Arrange string[] fileNames = [$"{Namespace}.{interfaceName}.g.cs", $"{Namespace}.{proxyName}.g.cs"]; var path = $"./Source/Disposable/{interfaceName}.cs"; - SourceFile sourceFile = CreateSourceFile(path, name, ImplementationOptions.UseExtendedInterfaces); + SourceFile sourceFile = CreateSourceFile( + path, + name, + ImplementationOptions.UseExtendedInterfaces + ); // Act var result = _sut.Execute([sourceFile]); @@ -173,7 +204,11 @@ public class InheritedInterfaceTests Assert.True(noInterfaceImplementationFound); } - private static SourceFile CreateSourceFile(string path, string name, ImplementationOptions options) + private static SourceFile CreateSourceFile( + string path, + string name, + ImplementationOptions options + ) { var o = string.Empty; foreach (var val in Enum.GetValues()) @@ -191,7 +226,7 @@ public class InheritedInterfaceTests } if (o.Length == 0) { - o = "ImplementationOptions.None"; + o = "ImplementationOptions.None"; } return new SourceFile { @@ -216,4 +251,3 @@ public class InheritedInterfaceTests } } } - diff --git a/tests/ProxyInterfaceSourceGeneratorTests/PnPTests.cs b/tests/ProxyInterfaceSourceGeneratorTests/PnPTests.cs index 117be46..b0fe00f 100644 --- a/tests/ProxyInterfaceSourceGeneratorTests/PnPTests.cs +++ b/tests/ProxyInterfaceSourceGeneratorTests/PnPTests.cs @@ -45,7 +45,11 @@ public class PnPTests AttributeToAddToInterface = new ExtraAttribute { Name = "Speckle.ProxyGenerator.Proxy", - ArgumentList = new [] { "typeof(Microsoft.SharePoint.Client.ClientObject)", "ImplementationOptions.UseExtendedInterfaces"} + ArgumentList = new[] + { + "typeof(Microsoft.SharePoint.Client.ClientObject)", + "ImplementationOptions.UseExtendedInterfaces" + } } }; @@ -57,7 +61,11 @@ public class PnPTests AttributeToAddToInterface = new ExtraAttribute { Name = "Speckle.ProxyGenerator.Proxy", - ArgumentList =new [] { "typeof(SecurableObject)" , "ImplementationOptions.UseExtendedInterfaces"}// Only name, no namespace + ArgumentList = new[] + { + "typeof(SecurableObject)", + "ImplementationOptions.UseExtendedInterfaces" + } // Only name, no namespace } }; @@ -69,7 +77,11 @@ public class PnPTests AttributeToAddToInterface = new ExtraAttribute { Name = "Speckle.ProxyGenerator.Proxy", - ArgumentList = new [] { "typeof(Web)", "ImplementationOptions.UseExtendedInterfaces"} // Only name, no namespace + ArgumentList = new[] + { + "typeof(Web)", + "ImplementationOptions.UseExtendedInterfaces" + } // Only name, no namespace } }; @@ -81,7 +93,11 @@ public class PnPTests AttributeToAddToInterface = new ExtraAttribute { Name = "Speckle.ProxyGenerator.Proxy", - ArgumentList = new [] { "typeof(Microsoft.SharePoint.Client.ClientRuntimeContext)", "ImplementationOptions.UseExtendedInterfaces"} + ArgumentList = new[] + { + "typeof(Microsoft.SharePoint.Client.ClientRuntimeContext)", + "ImplementationOptions.UseExtendedInterfaces" + } } }; @@ -93,7 +109,11 @@ public class PnPTests AttributeToAddToInterface = new ExtraAttribute { Name = "Speckle.ProxyGenerator.Proxy", - ArgumentList =new [] { "typeof(Microsoft.SharePoint.Client.ClientContext)", "ImplementationOptions.UseExtendedInterfaces"} // Only name, no namespace + ArgumentList = new[] + { + "typeof(Microsoft.SharePoint.Client.ClientContext)", + "ImplementationOptions.UseExtendedInterfaces" + } // Only name, no namespace } }; diff --git a/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForClassWithArray_Should_GenerateCorrectFiles.verified.txt b/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForClassWithArray_Should_GenerateCorrectFiles.verified.txt index 03ba694..27db633 100644 --- a/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForClassWithArray_Should_GenerateCorrectFiles.verified.txt +++ b/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForClassWithArray_Should_GenerateCorrectFiles.verified.txt @@ -166,7 +166,6 @@ namespace Speckle.ProxyGenerator } private static void Add(Func f) - where T : class where TInterface : notnull where TProxy : TInterface { diff --git a/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForClassWithIgnores.verified.txt b/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForClassWithIgnores.verified.txt index ee07c44..b6784e0 100644 --- a/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForClassWithIgnores.verified.txt +++ b/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForClassWithIgnores.verified.txt @@ -174,7 +174,6 @@ namespace Speckle.ProxyGenerator } private static void Add(Func f) - where T : class where TInterface : notnull where TProxy : TInterface { diff --git a/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForClassWith_BaseInterface.verified.txt b/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForClassWith_BaseInterface.verified.txt index e43337e..8e92e97 100644 --- a/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForClassWith_BaseInterface.verified.txt +++ b/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForClassWith_BaseInterface.verified.txt @@ -176,7 +176,6 @@ namespace Speckle.ProxyGenerator } private static void Add(Func f) - where T : class where TInterface : notnull where TProxy : TInterface { diff --git a/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForClassWith_Extended.verified.txt b/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForClassWith_Extended.verified.txt index ae368bc..99834c9 100644 --- a/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForClassWith_Extended.verified.txt +++ b/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForClassWith_Extended.verified.txt @@ -227,7 +227,6 @@ Add(Func f) - where T : class where TInterface : notnull where TProxy : TInterface { diff --git a/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForStruct_Should_GenerateProxyCode.verified.txt b/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForStruct_Should_GenerateProxyCode.verified.txt new file mode 100644 index 0000000..b62befe --- /dev/null +++ b/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForStruct_Should_GenerateProxyCode.verified.txt @@ -0,0 +1,286 @@ +[ + { + HintName: ProxyInterfaceSourceGeneratorTests.Source.IMyStruct.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 IMyStruct + { + global::ProxyInterfaceSourceGeneratorTests.Source.MyStruct _Instance { get; } + + int Id { get; set; } + + bool TryGetMyStruct2(int i, out global::ProxyInterfaceSourceGeneratorTests.Source.MyStruct2 x, double z); + } +} +#nullable restore + }, + { + HintName: ProxyInterfaceSourceGeneratorTests.Source.IMyStruct2.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 IMyStruct2 + { + global::ProxyInterfaceSourceGeneratorTests.Source.MyStruct2 _Instance { get; } + + int Id { get; set; } + + + } +} +#nullable restore + }, + { + HintName: ProxyInterfaceSourceGeneratorTests.Source.MyStructProxy.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 struct MyStructProxy : global::ProxyInterfaceSourceGeneratorTests.Source.IMyStruct + { + public global::ProxyInterfaceSourceGeneratorTests.Source.MyStruct _Instance { get; } + + public int Id { get => _Instance.Id; } + + public bool TryGetMyStruct2(int i, out global::ProxyInterfaceSourceGeneratorTests.Source.IMyStruct2 x, double z) + { + int i_ = i; + global::ProxyInterfaceSourceGeneratorTests.Source.MyStruct2 x_; + double z_ = z; + var result_222455096 = _Instance.TryGetMyStruct2(i_, out x_, z_); + x = Mapster.TypeAdapter.Adapt(x_); + return result_222455096; + } + + + public MyStructProxy(global::ProxyInterfaceSourceGeneratorTests.Source.MyStruct instance) + { + _Instance = instance; + + } + + static MyStructProxy() + { + Mapster.TypeAdapterConfig.NewConfig().ConstructUsing(instance_1687574103 => new global::ProxyInterfaceSourceGeneratorTests.Source.MyStruct2Proxy(instance_1687574103)); + Mapster.TypeAdapterConfig.NewConfig().MapWith(proxy_1070335295 => ((global::ProxyInterfaceSourceGeneratorTests.Source.MyStruct2Proxy) proxy_1070335295)._Instance); + } + + } +} +#nullable restore + }, + { + HintName: ProxyInterfaceSourceGeneratorTests.Source.MyStruct2Proxy.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 struct MyStruct2Proxy : global::ProxyInterfaceSourceGeneratorTests.Source.IMyStruct2 + { + public global::ProxyInterfaceSourceGeneratorTests.Source.MyStruct2 _Instance { get; } + + public int Id { get => _Instance.Id; } + + + public MyStruct2Proxy(global::ProxyInterfaceSourceGeneratorTests.Source.MyStruct2 instance) + { + _Instance = instance; + + } + + static MyStruct2Proxy() + { + Mapster.TypeAdapterConfig.NewConfig().ConstructUsing(instance_1687574103 => new global::ProxyInterfaceSourceGeneratorTests.Source.MyStruct2Proxy(instance_1687574103)); + Mapster.TypeAdapterConfig.NewConfig().MapWith(proxy_1070335295 => ((global::ProxyInterfaceSourceGeneratorTests.Source.MyStruct2Proxy) proxy_1070335295)._Instance); + } + + } +} +#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 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() + { + Add(x => new ProxyInterfaceSourceGeneratorTests.Source.MyStructProxy(x)); +Add(x => new ProxyInterfaceSourceGeneratorTests.Source.MyStruct2Proxy(x)); + + } + + private static void Add(Func f) + 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); + } +#nullable restore +} + } +] \ No newline at end of file diff --git a/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.cs b/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.cs index f4e278c..c3141ec 100644 --- a/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.cs +++ b/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.cs @@ -26,9 +26,17 @@ public class ProxyInterfaceSourceGeneratorTest } [Fact] - public void GenerateFiles_ForStruct_Should_Not_GenerateProxyCode() + public Task GenerateFiles_ForStruct_Should_GenerateProxyCode() { // Arrange + var fileNames = new[] + { + "ProxyInterfaceSourceGeneratorTests.Source.IMyStruct.g.cs", + "ProxyInterfaceSourceGeneratorTests.Source.MyStructProxy.g.cs", + "ProxyInterfaceSourceGeneratorTests.Source.IMyStruct2.g.cs", + "ProxyInterfaceSourceGeneratorTests.Source.MyStruct2Proxy.g.cs" + }; + var path = "./Source/IMyStruct.cs"; var sourceFile = new SourceFile { @@ -41,12 +49,28 @@ public class ProxyInterfaceSourceGeneratorTest } }; + var path2 = "./Source/IMyStruct2.cs"; + var sourceFile2 = new SourceFile + { + Path = path2, + Text = File.ReadAllText(path2), + AttributeToAddToInterface = new ExtraAttribute + { + Name = "Speckle.ProxyGenerator.Proxy", + ArgumentList = "typeof(ProxyInterfaceSourceGeneratorTests.Source.MyStruct2)" + } + }; + // Act - var result = _sut.Execute(new[] { sourceFile }); + var result = _sut.Execute(new[] { sourceFile, sourceFile2 }); // Assert result.Valid.Should().BeTrue(); - result.Files.Should().HaveCount(1); + result.Files.Should().HaveCount(fileNames.Length + 1); + + // Verify + var results = result.GeneratorDriver.GetRunResult().Results.First().GeneratedSources; + return Verify(results); } [Fact] @@ -123,7 +147,6 @@ public class ProxyInterfaceSourceGeneratorTest return Verify(results); } - [Fact] public Task GenerateFiles_ForClassWith_BaseInterface() { @@ -145,7 +168,8 @@ public class ProxyInterfaceSourceGeneratorTest ArgumentList = new[] { "typeof(ProxyInterfaceSourceGeneratorTests.Source.Foo2)", - "ImplementationOptions.UseExtendedInterfaces", "ProxyClassAccessibility.Public" + "ImplementationOptions.UseExtendedInterfaces", + "ProxyClassAccessibility.Public" } } }; @@ -328,7 +352,7 @@ public class ProxyInterfaceSourceGeneratorTest foreach (var fileName in fileNames.Select((fileName, index) => new { fileName, index })) { - var builder = result.Files[fileName.index ]; // attribute is last + var builder = result.Files[fileName.index]; // attribute is last builder.Path.Should().EndWith(fileName.fileName); if (Write) diff --git a/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTests.csproj b/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTests.csproj index 3b45955..d72c967 100644 --- a/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTests.csproj +++ b/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTests.csproj @@ -72,6 +72,9 @@ PreserveNewest + + PreserveNewest + diff --git a/tests/ProxyInterfaceSourceGeneratorTests/Source/Disposable/RevitLocationPointProxyExtras.cs b/tests/ProxyInterfaceSourceGeneratorTests/Source/Disposable/RevitLocationPointProxyExtras.cs index 2a8ddc6..3ab3984 100644 --- a/tests/ProxyInterfaceSourceGeneratorTests/Source/Disposable/RevitLocationPointProxyExtras.cs +++ b/tests/ProxyInterfaceSourceGeneratorTests/Source/Disposable/RevitLocationPointProxyExtras.cs @@ -1,10 +1,6 @@ namespace ProxyInterfaceSourceGeneratorTests.Source.Disposable; - - -public interface IRevitLocationPoint : IRevitLocation -{ -} +public interface IRevitLocationPoint : IRevitLocation { } public interface IRevitLocationCurve : IRevitLocation { @@ -15,12 +11,15 @@ public class LocationPoint : Location { public XYZ Point => throw new NotImplementedException(); } + public class Location : APIObject { } + public class APIObject { } + public class XYZ { } -public interface IRevitLocation -{ -} + +public interface IRevitLocation { } + public interface IRevitCurve { double Length { get; } diff --git a/tests/ProxyInterfaceSourceGeneratorTests/Source/Foo3.cs b/tests/ProxyInterfaceSourceGeneratorTests/Source/Foo3.cs index 72203fe..fd89c29 100644 --- a/tests/ProxyInterfaceSourceGeneratorTests/Source/Foo3.cs +++ b/tests/ProxyInterfaceSourceGeneratorTests/Source/Foo3.cs @@ -10,6 +10,4 @@ public class Foo3 } } -public class Bar3 -{ -} +public class Bar3 { } diff --git a/tests/ProxyInterfaceSourceGeneratorTests/Source/IBar3.cs b/tests/ProxyInterfaceSourceGeneratorTests/Source/IBar3.cs index ee9480c..17972d3 100644 --- a/tests/ProxyInterfaceSourceGeneratorTests/Source/IBar3.cs +++ b/tests/ProxyInterfaceSourceGeneratorTests/Source/IBar3.cs @@ -1,5 +1,3 @@ namespace ProxyInterfaceSourceGeneratorTests.Source; -public partial interface IBar3 -{ -} +public partial interface IBar3 { } diff --git a/tests/ProxyInterfaceSourceGeneratorTests/Source/IBar3Proxy.cs b/tests/ProxyInterfaceSourceGeneratorTests/Source/IBar3Proxy.cs index daeccf3..b7a8b14 100644 --- a/tests/ProxyInterfaceSourceGeneratorTests/Source/IBar3Proxy.cs +++ b/tests/ProxyInterfaceSourceGeneratorTests/Source/IBar3Proxy.cs @@ -1,7 +1,3 @@ namespace ProxyInterfaceSourceGeneratorTests.Source; - -public partial interface IBar3Proxy : IBar3 -{ - -} +public partial interface IBar3Proxy : IBar3 { } diff --git a/tests/ProxyInterfaceSourceGeneratorTests/Source/IFoo2.cs b/tests/ProxyInterfaceSourceGeneratorTests/Source/IFoo2.cs index 1035b82..0227b7a 100644 --- a/tests/ProxyInterfaceSourceGeneratorTests/Source/IFoo2.cs +++ b/tests/ProxyInterfaceSourceGeneratorTests/Source/IFoo2.cs @@ -1,6 +1,7 @@ namespace ProxyInterfaceSourceGeneratorTests.Source { - public partial interface IFoo2: IFoo2Base { } + public partial interface IFoo2 : IFoo2Base { } + public partial interface IFoo2Base { int Weird2(); diff --git a/tests/ProxyInterfaceSourceGeneratorTests/Source/IFoo3.cs b/tests/ProxyInterfaceSourceGeneratorTests/Source/IFoo3.cs index d06556d..9a181f5 100644 --- a/tests/ProxyInterfaceSourceGeneratorTests/Source/IFoo3.cs +++ b/tests/ProxyInterfaceSourceGeneratorTests/Source/IFoo3.cs @@ -4,5 +4,4 @@ namespace ProxyInterfaceSourceGeneratorTests.Source { IBar3 Weird(); } - } diff --git a/tests/ProxyInterfaceSourceGeneratorTests/Source/IFoo3Proxy.cs b/tests/ProxyInterfaceSourceGeneratorTests/Source/IFoo3Proxy.cs index 060c0fd..cca3c8c 100644 --- a/tests/ProxyInterfaceSourceGeneratorTests/Source/IFoo3Proxy.cs +++ b/tests/ProxyInterfaceSourceGeneratorTests/Source/IFoo3Proxy.cs @@ -1,3 +1,3 @@ namespace ProxyInterfaceSourceGeneratorTests.Source; -public partial interface IFoo3Proxy: IFoo3 { } +public partial interface IFoo3Proxy : IFoo3 { } diff --git a/tests/ProxyInterfaceSourceGeneratorTests/Source/IMyStruct2.cs b/tests/ProxyInterfaceSourceGeneratorTests/Source/IMyStruct2.cs new file mode 100644 index 0000000..938e17d --- /dev/null +++ b/tests/ProxyInterfaceSourceGeneratorTests/Source/IMyStruct2.cs @@ -0,0 +1,4 @@ +namespace ProxyInterfaceSourceGeneratorTests.Source +{ + public partial interface IMyStruct2 { } +} diff --git a/tests/ProxyInterfaceSourceGeneratorTests/Source/MyStruct.cs b/tests/ProxyInterfaceSourceGeneratorTests/Source/MyStruct.cs index ad065e2..c2bc4cc 100644 --- a/tests/ProxyInterfaceSourceGeneratorTests/Source/MyStruct.cs +++ b/tests/ProxyInterfaceSourceGeneratorTests/Source/MyStruct.cs @@ -1,6 +1,17 @@ namespace ProxyInterfaceSourceGeneratorTests.Source; public struct MyStruct +{ + public int Id { get; set; } + + public bool TryGetMyStruct2(int i, out MyStruct2 x, double z) + { + x = default; + return true; + } +} + +public struct MyStruct2 { public int Id { get; set; } }