Skip to content

Commit ab93df3

Browse files
Fix issue 886: Optional ByRef parameters default value conversion
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
1 parent c289dcd commit ab93df3

File tree

3 files changed

+66
-4
lines changed

3 files changed

+66
-4
lines changed

CodeConverter/CSharp/ArgumentConverter.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,10 +226,18 @@ private CSSyntax.ArgumentSyntax CreateOptionalRefArg(IParameterSymbol p, RefKind
226226
var type = CommonConversions.GetTypeSyntax(p.Type);
227227
CSSyntax.ExpressionSyntax initializer;
228228
if (p.HasExplicitDefaultValue) {
229-
initializer = CommonConversions.Literal(p.ExplicitDefaultValue);
229+
if (p.ExplicitDefaultValue == null && p.Type.IsValueType && p.Type.OriginalDefinition.SpecialType != SpecialType.System_Nullable_T) {
230+
initializer = CS.SyntaxFactory.DefaultExpression(type);
231+
} else {
232+
initializer = CommonConversions.Literal(p.ExplicitDefaultValue);
233+
}
230234
} else if (HasOptionalAttribute(p)) {
231235
if (TryGetDefaultParameterValueAttributeValue(p, out var defaultValue)) {
232-
initializer = CommonConversions.Literal(defaultValue);
236+
if (defaultValue == null && p.Type.IsValueType && p.Type.OriginalDefinition.SpecialType != SpecialType.System_Nullable_T) {
237+
initializer = CS.SyntaxFactory.DefaultExpression(type);
238+
} else {
239+
initializer = CommonConversions.Literal(defaultValue);
240+
}
233241
} else {
234242
initializer = CS.SyntaxFactory.DefaultExpression(type);
235243
}

CodeConverter/CSharp/ExpressionNodeVisitor.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,22 @@ public override async Task<CSharpSyntaxNode> VisitParameter(VBSyntax.ParameterSy
471471
CS.SyntaxFactory.Attribute(ValidSyntaxFactory.IdentifierName("Optional")),
472472
};
473473
if (!node.Default.Value.IsKind(VBasic.SyntaxKind.NothingLiteralExpression)) {
474-
optionalAttributes.Add(CS.SyntaxFactory.Attribute(ValidSyntaxFactory.IdentifierName("DefaultParameterValue"), arg));
474+
if (vbSymbol?.Type?.SpecialType == SpecialType.System_Decimal && defaultExpression is CSSyntax.LiteralExpressionSyntax literalExpr) {
475+
var literalValue = literalExpr.Token.Value;
476+
if (literalValue is decimal decimalVal) {
477+
var isInteger = decimalVal == Math.Round(decimalVal);
478+
var newLiteral = isInteger ? CommonConversions.Literal((int)decimalVal) : CommonConversions.Literal((double)decimalVal);
479+
arg = CommonConversions.CreateAttributeArgumentList(CS.SyntaxFactory.AttributeArgument(newLiteral));
480+
}
481+
}
482+
483+
if (vbSymbol?.Type?.TypeKind == TypeKind.Struct && vbSymbol?.Type?.SpecialType == SpecialType.None) {
484+
arg = null;
485+
}
486+
487+
if (arg != null) {
488+
optionalAttributes.Add(CS.SyntaxFactory.Attribute(ValidSyntaxFactory.IdentifierName("DefaultParameterValue"), arg));
489+
}
475490
}
476491
attributes.Insert(0,
477492
CS.SyntaxFactory.AttributeList(CS.SyntaxFactory.SeparatedList(optionalAttributes)));

Tests/CSharp/MemberTests/MemberTests.cs

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1576,4 +1576,43 @@ private void OptionalByRefWithDefault([Optional][DefaultParameterValue(""a"")] r
15761576
CS7036: There is no argument given that corresponds to the required parameter 'str1' of 'MissingByRefArgumentWithNoExplicitDefaultValue.ByRefNoDefault(ref string)'
15771577
");
15781578
}
1579-
}
1579+
[Fact]
1580+
public async Task OptionalByRefParameterAsync886()
1581+
{
1582+
await TestConversionVisualBasicToCSharpAsync(@"Class Issue886
1583+
Private Shared Sub OptionalParams()
1584+
FunctionWithOptionalParams()
1585+
End Sub
1586+
1587+
Private Shared Sub FunctionWithOptionalParams(Optional ByRef structParam As TestStruct = Nothing, Optional ByRef decimalParam As Decimal = 0)
1588+
structParam = New TestStruct
1589+
decimalParam = 0
1590+
End Sub
1591+
1592+
Friend Structure TestStruct
1593+
Friend A As Boolean
1594+
End Structure
1595+
End Class", @"using System.Runtime.InteropServices;
1596+
1597+
internal partial class Issue886
1598+
{
1599+
private static void OptionalParams()
1600+
{
1601+
TestStruct argstructParam = default;
1602+
decimal argdecimalParam = 0m;
1603+
FunctionWithOptionalParams(structParam: ref argstructParam, decimalParam: ref argdecimalParam);
1604+
}
1605+
1606+
private static void FunctionWithOptionalParams([Optional] ref TestStruct structParam, [Optional, DefaultParameterValue(0)] ref decimal decimalParam)
1607+
{
1608+
structParam = new TestStruct();
1609+
decimalParam = 0m;
1610+
}
1611+
1612+
internal partial struct TestStruct
1613+
{
1614+
internal bool A;
1615+
}
1616+
}");
1617+
}
1618+
}

0 commit comments

Comments
 (0)