From 798974f5235309b30387149b7c7f48654c23ca31 Mon Sep 17 00:00:00 2001 From: Timur Kelman Date: Mon, 22 Jul 2024 16:36:17 +0200 Subject: [PATCH 1/4] add a test for omitter arguments --- Tests/CSharp/MemberTests/MemberTests.cs | 43 +++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/Tests/CSharp/MemberTests/MemberTests.cs b/Tests/CSharp/MemberTests/MemberTests.cs index 148aa6a5..f4af8cd1 100644 --- a/Tests/CSharp/MemberTests/MemberTests.cs +++ b/Tests/CSharp/MemberTests/MemberTests.cs @@ -4047,6 +4047,49 @@ public static int StaticTestProperty return _StaticTestProperty_sPrevPosition + 1; } } +}"); + } + + [Fact] + public async Task TestOmittedArgumentsAsync() + { + await TestConversionVisualBasicToCSharpAsync( + @"Class OmittedArguments + Sub M(Optional a As String = ""a"", ByRef Optional b As String = ""b"") + Dim s As String = """" + + M() 'omitted implicitely + M(,) 'omitted explicitely + + M(s) 'omitted implicitely + M(s,) 'omitted explicitely + + M(a:=s) 'omitted implicitely + M(a:=s, ) 'omitted explicitely + End Sub +End Class", @"using System.Runtime.InteropServices; + +internal partial class OmittedArguments +{ + public void M([Optional, DefaultParameterValue(""a"")] string a, [Optional, DefaultParameterValue(""b"")] ref string b) + { + string s = """"; + + string argb = ""b""; + M(b: ref argb); // omitted implicitely + string argb1 = ""b""; + M(b: ref argb1); // omitted explicitely + + string argb2 = ""b""; + M(s, b: ref argb2); // omitted implicitely + string argb3 = ""b""; + M(s, b: ref argb3); // omitted explicitely + + string argb4 = ""b""; + M(a: s, b: ref argb4); // omitted implicitely + string argb5 = ""b""; + M(a: s, b: ref argb5); // omitted explicitely + } }"); } } \ No newline at end of file From ce55c8e9293459e507fa2c62c88467902904d7d3 Mon Sep 17 00:00:00 2001 From: Timur Kelman Date: Mon, 22 Jul 2024 16:37:50 +0200 Subject: [PATCH 2/4] unmark a parameter as processed by ConvertArg in case named parameters will be used --- CodeConverter/CSharp/ExpressionNodeVisitor.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/CodeConverter/CSharp/ExpressionNodeVisitor.cs b/CodeConverter/CSharp/ExpressionNodeVisitor.cs index 1084ed19..089af3b1 100644 --- a/CodeConverter/CSharp/ExpressionNodeVisitor.cs +++ b/CodeConverter/CSharp/ExpressionNodeVisitor.cs @@ -1739,6 +1739,7 @@ async Task ConvertArg(VBSyntax.ArgumentSyntax arg, int argIndex) if (arg.IsOmitted) { if (invocationSymbol != null && !invocationHasOverloads) { forceNamedParameters = true; + processedParameters.Remove(parameterSymbol?.Name); return null; //Prefer to skip omitted and use named parameters when the symbol has only one overload } From a90b9dbcdc44931f86227e293ff792aeb20b88f4 Mon Sep 17 00:00:00 2001 From: GrahamTheCoder Date: Mon, 22 Jul 2024 22:53:23 +0100 Subject: [PATCH 3/4] Fix typo --- Tests/CSharp/MemberTests/MemberTests.cs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Tests/CSharp/MemberTests/MemberTests.cs b/Tests/CSharp/MemberTests/MemberTests.cs index f4af8cd1..2427ed6b 100644 --- a/Tests/CSharp/MemberTests/MemberTests.cs +++ b/Tests/CSharp/MemberTests/MemberTests.cs @@ -4058,14 +4058,14 @@ await TestConversionVisualBasicToCSharpAsync( Sub M(Optional a As String = ""a"", ByRef Optional b As String = ""b"") Dim s As String = """" - M() 'omitted implicitely - M(,) 'omitted explicitely + M() 'omitted implicitly + M(,) 'omitted explicitly - M(s) 'omitted implicitely - M(s,) 'omitted explicitely + M(s) 'omitted implicitly + M(s,) 'omitted explicitly - M(a:=s) 'omitted implicitely - M(a:=s, ) 'omitted explicitely + M(a:=s) 'omitted implicitly + M(a:=s, ) 'omitted explicitly End Sub End Class", @"using System.Runtime.InteropServices; @@ -4076,19 +4076,19 @@ public void M([Optional, DefaultParameterValue(""a"")] string a, [Optional, Defa string s = """"; string argb = ""b""; - M(b: ref argb); // omitted implicitely + M(b: ref argb); // omitted implicitly string argb1 = ""b""; - M(b: ref argb1); // omitted explicitely + M(b: ref argb1); // omitted explicitly string argb2 = ""b""; - M(s, b: ref argb2); // omitted implicitely + M(s, b: ref argb2); // omitted implicitly string argb3 = ""b""; - M(s, b: ref argb3); // omitted explicitely + M(s, b: ref argb3); // omitted explicitly string argb4 = ""b""; - M(a: s, b: ref argb4); // omitted implicitely + M(a: s, b: ref argb4); // omitted implicitly string argb5 = ""b""; - M(a: s, b: ref argb5); // omitted explicitely + M(a: s, b: ref argb5); // omitted explicitly } }"); } From d686ca03611ff7a1f34f7e3f0685001f1c7c645a Mon Sep 17 00:00:00 2001 From: GrahamTheCoder Date: Mon, 22 Jul 2024 23:04:33 +0100 Subject: [PATCH 4/4] Extract extra local function Hopefully this stops someone tweaking the logic and forgetting to remove the parameter - there's already enough mutation of state going on with the forceNamedParameters aspect --- CodeConverter/CSharp/ExpressionNodeVisitor.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/CodeConverter/CSharp/ExpressionNodeVisitor.cs b/CodeConverter/CSharp/ExpressionNodeVisitor.cs index 089af3b1..530bd74e 100644 --- a/CodeConverter/CSharp/ExpressionNodeVisitor.cs +++ b/CodeConverter/CSharp/ExpressionNodeVisitor.cs @@ -1731,18 +1731,22 @@ async Task ConvertArg(VBSyntax.ArgumentSyntax arg, int argIndex) { var argName = arg is VBSyntax.SimpleArgumentSyntax { IsNamed: true } namedArg ? namedArg.NameColonEquals.Name.Identifier.Text : null; var parameterSymbol = invocationSymbol?.GetParameters().GetArgument(argName, argIndex); + var convertedArg = await ConvertArgForParameter(arg, parameterSymbol); - if (parameterSymbol != null) { + if (convertedArg is not null && parameterSymbol is not null) { processedParameters.Add(parameterSymbol.Name); } + return convertedArg; + } + + async Task ConvertArgForParameter(VBSyntax.ArgumentSyntax arg, IParameterSymbol parameterSymbol) + { if (arg.IsOmitted) { if (invocationSymbol != null && !invocationHasOverloads) { forceNamedParameters = true; - processedParameters.Remove(parameterSymbol?.Name); return null; //Prefer to skip omitted and use named parameters when the symbol has only one overload } - return ConvertOmittedArgument(parameterSymbol); }