From e6724dd4570e71382fd83ca10c8eec4e774da6cd Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Tue, 27 Jul 2021 18:47:00 +0200 Subject: [PATCH] Fix method parameters: 'in', 'out' and 'ref' (#17) * Fix Ref and Out * _ --- src-examples/ProxyInterfaceConsumer/Person.cs | 11 ++ .../Class1pp.cs | 86 ++++++++++++++ .../ProxyInterfaceConsumerViaNuGet/Person.cs | 10 ++ .../Extensions/SymbolExtensions.cs | 18 +++ .../PartialInterfacesGenerator.cs | 2 +- .../FileGenerators/ProxyClassesGenerator.cs | 106 +++++++++++++++++- 6 files changed, 227 insertions(+), 6 deletions(-) create mode 100644 src-examples/ProxyInterfaceConsumerViaNuGet/Class1pp.cs diff --git a/src-examples/ProxyInterfaceConsumer/Person.cs b/src-examples/ProxyInterfaceConsumer/Person.cs index ea91128..858ee7c 100644 --- a/src-examples/ProxyInterfaceConsumer/Person.cs +++ b/src-examples/ProxyInterfaceConsumer/Person.cs @@ -45,6 +45,17 @@ namespace ProxyInterfaceConsumer { } + public void In_Out_Ref1(in int a, out int b, ref int c) + { + b = 1; + } + + public int In_Out_Ref2(in Address a, out Address b, ref Address c) + { + b = new Address(); + return 404; + } + public void Void() { } diff --git a/src-examples/ProxyInterfaceConsumerViaNuGet/Class1pp.cs b/src-examples/ProxyInterfaceConsumerViaNuGet/Class1pp.cs new file mode 100644 index 0000000..5d05d7e --- /dev/null +++ b/src-examples/ProxyInterfaceConsumerViaNuGet/Class1pp.cs @@ -0,0 +1,86 @@ +using System; +using AutoMapper; + +namespace ProxyInterfaceConsumer +{ + public class PersonProxy2 + { + public ProxyInterfaceConsumer.Person _Instance { get; } + + public int Id { get => _Instance.Id; } + + public long? NullableLong { get => _Instance.NullableLong; } + + public string Name { get => _Instance.Name; set => _Instance.Name = value; } + + + public IAddress Address { get => _mapper.Map(_Instance.Address); set => _Instance.Address = _mapper.Map(value); } + + public System.Collections.Generic.List AddressesLIst { get => _mapper.Map>(_Instance.AddressesLIst); set => _Instance.AddressesLIst = _mapper.Map>(value); } + + public System.Collections.Generic.Dictionary AddressesDict { get => _mapper.Map>(_Instance.AddressesDict); set => _Instance.AddressesDict = _mapper.Map>(value); } + + public ProxyInterfaceConsumer.E E { get => _Instance.E; set => _Instance.E = value; } + + public ProxyInterfaceConsumer.IMyInterface MyInterface { get => _Instance.MyInterface; set => _Instance.MyInterface = value; } + + + + public int Add(string s) + { + string s_dbccfd45ed944f58b12d83a4f907aa6c = s; + var result_caf8bee7109d4b77891b141c495b63ff = _Instance.Add(s_dbccfd45ed944f58b12d83a4f907aa6c); + return result_caf8bee7109d4b77891b141c495b63ff; + } + + + + public IAddress AddAddress(IAddress a) + { + ProxyInterfaceConsumer.Address a_23d6262793aa4c90b77bb7a9d46710b2 = _mapper.Map(a); + var result_cd3011159452417bb585e0acfaeefddc = _Instance.AddAddress(a_23d6262793aa4c90b77bb7a9d46710b2); + return _mapper.Map(result_cd3011159452417bb585e0acfaeefddc); + } + + public void In_Out_Ref1(in int a, out int b, ref int c) + { + int a_88b067399c9641d69ebd8f795ddfa7ee = a; + int b_9a4c5b7b7e4c427dbb4779f658602356; + int c_49084012db6e47f0b03626886b8b7848 = c; + _Instance.In_Out_Ref1(in a_88b067399c9641d69ebd8f795ddfa7ee, out b_9a4c5b7b7e4c427dbb4779f658602356, ref c_49084012db6e47f0b03626886b8b7848); + b = b_9a4c5b7b7e4c427dbb4779f658602356; + } + + public void In_Out_Ref2(in IAddress a, out IAddress b, ref IAddress c) + { + ProxyInterfaceConsumer.Address a_e5af7467b9d24729a95a861a8cc87f27 = _mapper.Map(a); + ProxyInterfaceConsumer.Address b_3a7ae9dbab3344bc9f9736b113198331; + ProxyInterfaceConsumer.Address c_afcd2b8abb1a4b7eae2a10656744c28a = _mapper.Map(c); + _Instance.In_Out_Ref2(in a_e5af7467b9d24729a95a861a8cc87f27, out b_3a7ae9dbab3344bc9f9736b113198331, ref c_afcd2b8abb1a4b7eae2a10656744c28a); + b = _mapper.Map(b_3a7ae9dbab3344bc9f9736b113198331); + } + + public void Void() + { + _Instance.Void(); + } + + + + + + public PersonProxy2(ProxyInterfaceConsumer.Person instance) + { + _Instance = instance; + + _mapper = new MapperConfiguration(cfg => + { + cfg.CreateMap(); + cfg.CreateMap(); + }).CreateMapper(); + + } + + private readonly IMapper _mapper; + } +} \ No newline at end of file diff --git a/src-examples/ProxyInterfaceConsumerViaNuGet/Person.cs b/src-examples/ProxyInterfaceConsumerViaNuGet/Person.cs index bdecbe2..4e95d53 100644 --- a/src-examples/ProxyInterfaceConsumerViaNuGet/Person.cs +++ b/src-examples/ProxyInterfaceConsumerViaNuGet/Person.cs @@ -33,6 +33,16 @@ namespace ProxyInterfaceConsumer return a; } + public void In_Out_Ref1(in int a, out int b, ref int c) + { + b = 1; + } + + public void In_Out_Ref2(in Address a, out Address b, ref Address c) + { + b = new Address(); + } + public void Void() { } diff --git a/src/ProxyInterfaceSourceGenerator/Extensions/SymbolExtensions.cs b/src/ProxyInterfaceSourceGenerator/Extensions/SymbolExtensions.cs index a8d376e..55123da 100644 --- a/src/ProxyInterfaceSourceGenerator/Extensions/SymbolExtensions.cs +++ b/src/ProxyInterfaceSourceGenerator/Extensions/SymbolExtensions.cs @@ -5,6 +5,24 @@ namespace ProxyInterfaceSourceGenerator.Extensions { internal static class SymbolExtensions { + public static string GetRefPrefix(this IParameterSymbol ps) + { + switch (ps.RefKind) + { + case RefKind.In: + return "in "; + + case RefKind.Out: + return "out "; + + case RefKind.Ref: + return "ref "; + + default: + return string.Empty; + } + } + public static string GetParamsPrefix(this IParameterSymbol ps) { return ps.IsParams ? "params " : string.Empty; diff --git a/src/ProxyInterfaceSourceGenerator/FileGenerators/PartialInterfacesGenerator.cs b/src/ProxyInterfaceSourceGenerator/FileGenerators/PartialInterfacesGenerator.cs index 9e88a8b..4dcd612 100644 --- a/src/ProxyInterfaceSourceGenerator/FileGenerators/PartialInterfacesGenerator.cs +++ b/src/ProxyInterfaceSourceGenerator/FileGenerators/PartialInterfacesGenerator.cs @@ -89,7 +89,7 @@ namespace {ns} foreach (var ps in method.Parameters) { var type = ps.GetTypeEnum() == TypeEnum.Complex ? GetParameterType(ps, out _) : ps.Type.ToString(); - methodParameters.Add($"{ps.GetParamsPrefix()}{type} {ps.Name}"); + methodParameters.Add($"{ps.GetParamsPrefix()}{ps.GetRefPrefix()}{type} {ps.Name}"); } str.AppendLine($" {GetReplacedType(method.ReturnType, out _)} {method.Name}({string.Join(", ", methodParameters)});"); diff --git a/src/ProxyInterfaceSourceGenerator/FileGenerators/ProxyClassesGenerator.cs b/src/ProxyInterfaceSourceGenerator/FileGenerators/ProxyClassesGenerator.cs index dfbd30f..3436132 100644 --- a/src/ProxyInterfaceSourceGenerator/FileGenerators/ProxyClassesGenerator.cs +++ b/src/ProxyInterfaceSourceGenerator/FileGenerators/ProxyClassesGenerator.cs @@ -1,4 +1,6 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Linq; using System.Text; using Microsoft.CodeAnalysis; using ProxyInterfaceSourceGenerator.Enums; @@ -130,7 +132,101 @@ namespace {ns} if (ps.GetTypeEnum() == TypeEnum.Complex) { var type = GetParameterType(ps, out var isReplaced); - methodParameters.Add($"{ps.GetParamsPrefix()}{type} {ps.Name}"); + methodParameters.Add($"{ps.GetParamsPrefix()}{ps.GetRefPrefix()}{type} {ps.Name}"); + } + else + { + methodParameters.Add($"{ps.GetParamsPrefix()}{ps.GetRefPrefix()}{ps.Type} {ps.Name}"); + } + + invokeParameters.Add($"{ps.GetRefPrefix()}_{ps.Name}"); + } + + string returnTypeAsString = GetReplacedType(method.ReturnType, out var returnIsReplaced); + + str.AppendLine($" public {returnTypeAsString} {method.Name}({string.Join(", ", methodParameters)})"); + str.AppendLine(" {"); + foreach (var ps in method.Parameters) + { + string normalOrMap = $" = {ps.Name}"; + if (ps.RefKind == RefKind.Out) + { + normalOrMap = string.Empty; + } + else + { + var type = GetParameterType(ps, out var isReplaced); + if (isReplaced) + { + normalOrMap = $" = _mapper.Map<{ps.Type}>({ps.Name})"; + } + } + + str.AppendLine($" {ps.Type} _{ps.Name}{normalOrMap};"); + } + +#pragma warning disable RS1024 // Compare symbols correctly + int hash = method.ReturnType.GetHashCode(); +#pragma warning restore RS1024 // Compare symbols correctly + var alternateReturnVariableName = $"result_{Math.Abs(hash)}"; + + if (returnTypeAsString == "void") + { + str.AppendLine($" _Instance.{method.Name}({string.Join(", ", invokeParameters)});"); + } + else + { + str.AppendLine($" var {alternateReturnVariableName} = _Instance.{method.Name}({string.Join(", ", invokeParameters)});"); + } + + foreach (var ps in method.Parameters.Where(p => p.RefKind == RefKind.Out)) + { + string normalOrMap = $" = _{ps.Name}"; + if (ps.GetTypeEnum() == TypeEnum.Complex) + { + var type = GetParameterType(ps, out var isReplaced); + if (isReplaced) + { + normalOrMap = $" = _mapper.Map<{type}>(_{ps.Name})"; + } + } + + str.AppendLine($" {ps.Name}{normalOrMap};"); + } + + if (returnTypeAsString != "void") + { + if (returnIsReplaced) + { + str.AppendLine($" return _mapper.Map<{returnTypeAsString}>({alternateReturnVariableName});"); + } + else + { + str.AppendLine($" return {alternateReturnVariableName};"); + } + } + + str.AppendLine(" }"); + str.AppendLine(); + } + + return str.ToString(); + } + + private string GeneratePublicMethodsOld(INamedTypeSymbol symbol) + { + var str = new StringBuilder(); + foreach (var method in MemberHelper.GetPublicMethods(symbol)) + { + var methodParameters = new List(); + var invokeParameters = new List(); + + foreach (var ps in method.Parameters) + { + if (ps.GetTypeEnum() == TypeEnum.Complex) + { + var type = GetParameterType(ps, out var isReplaced); + methodParameters.Add($"{ps.GetParamsPrefix()}{ps.GetRefPrefix()}{type} {ps.Name}"); if (isReplaced) { @@ -138,14 +234,14 @@ namespace {ns} } else { - invokeParameters.Add($"{ps.Name}"); + invokeParameters.Add($"{ps.GetRefPrefix()}{ps.Name}"); } } else { - methodParameters.Add($"{ps.GetParamsPrefix()}{ps.Type} {ps.Name}"); + methodParameters.Add($"{ps.GetParamsPrefix()}{ps.GetRefPrefix()}{ps.Type} {ps.Name}"); - invokeParameters.Add($"{ps.Name}"); + invokeParameters.Add($"{ps.GetRefPrefix()}{ps.Name}"); } }