From e0ff3e4d544050feba12148596cab5355b381056 Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Thu, 2 Mar 2023 11:02:00 +0100 Subject: [PATCH] Fix "ref" parameter (#61) --- src-examples/ProxyInterfaceConsumer/Person.cs | 2 ++ .../Builders/MethodParameterBuilder.cs | 2 +- .../Extensions/ParameterSymbolExtensions.cs | 7 ++++++- .../Extensions/StringExtensions.cs | 5 +++++ .../FileGenerators/ProxyClassesGenerator.cs | 9 ++++++--- ...ourceGeneratorTests.Source.PersonExtendsProxy.g.cs | 4 +--- ...erfaceSourceGeneratorTests.Source.PersonProxy.g.cs | 4 +--- ...WithArray_Should_GenerateCorrectFiles.verified.txt | 4 ++-- .../ProxyInterfaceSourceGeneratorTest.cs | 11 +++++++++-- .../Source/Person.cs | 1 + 10 files changed, 34 insertions(+), 15 deletions(-) diff --git a/src-examples/ProxyInterfaceConsumer/Person.cs b/src-examples/ProxyInterfaceConsumer/Person.cs index f189917..d0e9432 100644 --- a/src-examples/ProxyInterfaceConsumer/Person.cs +++ b/src-examples/ProxyInterfaceConsumer/Person.cs @@ -68,11 +68,13 @@ namespace ProxyInterfaceConsumer public void In_Out_Ref1(in int a, out int b, ref int c) { b = 1; + c++; } public int In_Out_Ref2(in Address a, out Address b, ref Address c) { b = new Address(); + c.HouseNumber = 11; return 404; } diff --git a/src/ProxyInterfaceSourceGenerator/Builders/MethodParameterBuilder.cs b/src/ProxyInterfaceSourceGenerator/Builders/MethodParameterBuilder.cs index b3871c3..6b6feab 100644 --- a/src/ProxyInterfaceSourceGenerator/Builders/MethodParameterBuilder.cs +++ b/src/ProxyInterfaceSourceGenerator/Builders/MethodParameterBuilder.cs @@ -13,7 +13,7 @@ internal static class MethodParameterBuilder { stringBuilder.Append(parameterSymbol.GetAttributesPrefix()); // "" or [NotNullWhen(true)] stringBuilder.Append(parameterSymbol.GetParamsPrefix()); // "" or "params " - stringBuilder.Append(parameterSymbol.GetRefPrefix()); // "" or "out " + stringBuilder.Append(parameterSymbol.GetRefKindPrefix()); // "" or "out " stringBuilder.AppendFormat("{0} ", type); // string or another type } diff --git a/src/ProxyInterfaceSourceGenerator/Extensions/ParameterSymbolExtensions.cs b/src/ProxyInterfaceSourceGenerator/Extensions/ParameterSymbolExtensions.cs index bc2682c..0e45469 100644 --- a/src/ProxyInterfaceSourceGenerator/Extensions/ParameterSymbolExtensions.cs +++ b/src/ProxyInterfaceSourceGenerator/Extensions/ParameterSymbolExtensions.cs @@ -8,7 +8,12 @@ internal static class ParameterSymbolExtensions { private const string ParameterValueNull = "null"; - public static string GetRefPrefix(this IParameterSymbol ps) + public static bool IsRef(this IParameterSymbol ps) + { + return ps.RefKind is RefKind.Ref or RefKind.RefReadOnly; + } + + public static string GetRefKindPrefix(this IParameterSymbol ps) { return ps.RefKind switch { diff --git a/src/ProxyInterfaceSourceGenerator/Extensions/StringExtensions.cs b/src/ProxyInterfaceSourceGenerator/Extensions/StringExtensions.cs index ddc566a..ea7dfc0 100644 --- a/src/ProxyInterfaceSourceGenerator/Extensions/StringExtensions.cs +++ b/src/ProxyInterfaceSourceGenerator/Extensions/StringExtensions.cs @@ -4,6 +4,11 @@ namespace ProxyInterfaceSourceGenerator.Extensions; internal static class StringExtensions { + public static string IIf(this bool value, string valueTrue, string valueFalse = "") + { + return value ? valueTrue : valueFalse; + } + // See https://andrewlock.net/why-is-string-gethashcode-different-each-time-i-run-my-program-in-net-core/ public static string GetDeterministicHashCodeAsString(this string str) { diff --git a/src/ProxyInterfaceSourceGenerator/FileGenerators/ProxyClassesGenerator.cs b/src/ProxyInterfaceSourceGenerator/FileGenerators/ProxyClassesGenerator.cs index 0eb1639..5b25858 100644 --- a/src/ProxyInterfaceSourceGenerator/FileGenerators/ProxyClassesGenerator.cs +++ b/src/ProxyInterfaceSourceGenerator/FileGenerators/ProxyClassesGenerator.cs @@ -208,7 +208,9 @@ using System; var type = GetParameterType(parameterSymbol, out _); methodParameters.Add(MethodParameterBuilder.Build(parameterSymbol, type)); - invokeParameters.Add($"{parameterSymbol.GetRefPrefix()}{parameterSymbol.GetSanitizedName()}_"); + + // Do not add the '_' for a 'ref' parameter. + invokeParameters.Add($"{parameterSymbol.GetRefKindPrefix()}{parameterSymbol.GetSanitizedName()}{(!parameterSymbol.IsRef()).IIf("_")}"); } string overrideOrVirtual = string.Empty; @@ -235,8 +237,9 @@ using System; } str.AppendLine($" public {overrideOrVirtual}{returnTypeAsString} {method.GetMethodNameWithOptionalTypeParameters()}({string.Join(", ", methodParameters)}){whereStatement}"); - str.AppendLine(" {"); - foreach (var ps in method.Parameters) + str.AppendLine(@" {"); + + foreach (var ps in method.Parameters.Where(p => !p.IsRef())) { var type = FixType(ps.Type.ToString()); string normalOrMap = $" = {ps.GetSanitizedName()}"; diff --git a/tests/ProxyInterfaceSourceGeneratorTests/Destination/ProxyInterfaceSourceGeneratorTests.Source.PersonExtendsProxy.g.cs b/tests/ProxyInterfaceSourceGeneratorTests/Destination/ProxyInterfaceSourceGeneratorTests.Source.PersonExtendsProxy.g.cs index 052bbd6..851951a 100644 --- a/tests/ProxyInterfaceSourceGeneratorTests/Destination/ProxyInterfaceSourceGeneratorTests.Source.PersonExtendsProxy.g.cs +++ b/tests/ProxyInterfaceSourceGeneratorTests/Destination/ProxyInterfaceSourceGeneratorTests.Source.PersonExtendsProxy.g.cs @@ -76,10 +76,8 @@ namespace ProxyInterfaceSourceGeneratorTests.Source public void In_Out_Ref1(in int a, out int b, ref int c) { - int a_ = a; int b_; - int c_ = c; - _Instance.In_Out_Ref1(in a_, out b_, ref c_); + _Instance.In_Out_Ref1(in a, out b_, ref c); b = b_; } diff --git a/tests/ProxyInterfaceSourceGeneratorTests/Destination/ProxyInterfaceSourceGeneratorTests.Source.PersonProxy.g.cs b/tests/ProxyInterfaceSourceGeneratorTests/Destination/ProxyInterfaceSourceGeneratorTests.Source.PersonProxy.g.cs index 094cd9b..8b51790 100644 --- a/tests/ProxyInterfaceSourceGeneratorTests/Destination/ProxyInterfaceSourceGeneratorTests.Source.PersonProxy.g.cs +++ b/tests/ProxyInterfaceSourceGeneratorTests/Destination/ProxyInterfaceSourceGeneratorTests.Source.PersonProxy.g.cs @@ -103,10 +103,8 @@ namespace ProxyInterfaceSourceGeneratorTests.Source public void In_Out_Ref1(in int a, out int b, ref int c) { - int a_ = a; int b_; - int c_ = c; - _Instance.In_Out_Ref1(in a_, out b_, ref c_); + _Instance.In_Out_Ref1(in a, out b_, ref c); b = b_; } diff --git a/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForClassWithArray_Should_GenerateCorrectFiles.verified.txt b/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForClassWithArray_Should_GenerateCorrectFiles.verified.txt index a2cdd6a..107d15c 100644 --- a/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForClassWithArray_Should_GenerateCorrectFiles.verified.txt +++ b/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.GenerateFiles_ForClassWithArray_Should_GenerateCorrectFiles.verified.txt @@ -1,6 +1,6 @@ [ { - HintName: ProxyInterfaceGenerator.ProxyAttribute.g.cs, + HintName: ProxyInterfaceGenerator.Extra.g.cs, Source: //---------------------------------------------------------------------------------------- // @@ -16,7 +16,7 @@ using System; namespace ProxyInterfaceGenerator { [AttributeUsage(AttributeTargets.Interface)] - public class ProxyAttribute : Attribute + internal sealed class ProxyAttribute : Attribute { public Type Type { get; } public bool ProxyBaseClasses { get; } diff --git a/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.cs b/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.cs index 9341635..b7f4d4b 100644 --- a/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.cs +++ b/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.cs @@ -273,7 +273,7 @@ public class ProxyInterfaceSourceGeneratorTest public void GenerateFiles_ForSingleClass_Should_GenerateCorrectFiles() { // Arrange - var attributeFilename = "ProxyInterfaceGenerator.ProxyAttribute.g.cs"; + var attributeFilename = "ProxyInterfaceGenerator.Extra.g.cs"; var interfaceFilename = "ProxyInterfaceSourceGeneratorTests.Source.IPersonExtends.g.cs"; var proxyClassFilename = "ProxyInterfaceSourceGeneratorTests.Source.PersonExtendsProxy.g.cs"; @@ -364,7 +364,7 @@ public class ProxyInterfaceSourceGeneratorTest public void GenerateFiles_ForTwoClasses_Should_GenerateCorrectFiles() { // Arrange - var attributeFilename = "ProxyInterfaceGenerator.ProxyAttribute.g.cs"; + var attributeFilename = "ProxyInterfaceGenerator.Extra.g.cs"; var interfaceHumanFilename = "ProxyInterfaceSourceGeneratorTests.Source.IHuman.g.cs"; var proxyClassHumanFilename = "ProxyInterfaceSourceGeneratorTests.Source.HumanProxy.g.cs"; var interfacePersonFilename = "ProxyInterfaceSourceGeneratorTests.Source.IPerson.g.cs"; @@ -440,5 +440,12 @@ public class ProxyInterfaceSourceGeneratorTest var proxyCode = proxyClassPerson.ToString(); if (Write) File.WriteAllText($"../../../Destination/{proxyClassPersonFilename}", proxyCode); proxyCode.Should().NotBeNullOrEmpty().And.Be(File.ReadAllText($"../../../Destination/{proxyClassPersonFilename}")); + + var personProxy = new PersonProxy(new Person()); + + int c = 100; + personProxy.In_Out_Ref1(1, out var b, ref c); + + c.Should().Be(101); } } \ No newline at end of file diff --git a/tests/ProxyInterfaceSourceGeneratorTests/Source/Person.cs b/tests/ProxyInterfaceSourceGeneratorTests/Source/Person.cs index 8d9a138..4608016 100644 --- a/tests/ProxyInterfaceSourceGeneratorTests/Source/Person.cs +++ b/tests/ProxyInterfaceSourceGeneratorTests/Source/Person.cs @@ -83,6 +83,7 @@ namespace ProxyInterfaceSourceGeneratorTests.Source public void In_Out_Ref1(in int a, out int b, ref int c) { b = 1; + c++; } public double[,] Out_MultiDimensionIssue54(out double[,] x)