Skip to content

Commit

Permalink
Only cast for boxing when it's not implicit - fixes #1071
Browse files Browse the repository at this point in the history
But since this removes some casts, do still ensure that predefined cast expressions always cast since otherwise casting to T via object gets broken
  • Loading branch information
GrahamTheCoder committed Jan 29, 2024
1 parent d95dcb6 commit 5590951
Show file tree
Hide file tree
Showing 9 changed files with 38 additions and 11 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
* Conversion of explicit interface implementations now converts optional parameters [#1062](https://github.com/icsharpcode/CodeConverter/issues/1062)
* Constant chars are converted to constant strings where needed
* Select case for a mixture of strings and characters converts correctly [#1062](https://github.com/icsharpcode/CodeConverter/issues/1062)
* Implicit boxing conversion converted correctly to no-op [#1071](https://github.com/icsharpcode/CodeConverter/issues/1071)

### C# -> VB

Expand Down
2 changes: 1 addition & 1 deletion CodeConverter/CSharp/ExpressionNodeVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ public override async Task<CSharpSyntaxNode> VisitPredefinedCastExpression(VBasi
SyntaxFactory.Argument(expressionSyntax))));
}

var withConversion = CommonConversions.TypeConversionAnalyzer.AddExplicitConversion(node.Expression, expressionSyntax, false, false, forceTargetType: _semanticModel.GetTypeInfo(node).Type);
var withConversion = CommonConversions.TypeConversionAnalyzer.AddExplicitConversion(node.Expression, expressionSyntax, false, true, forceTargetType: _semanticModel.GetTypeInfo(node).Type);
return node.ParenthesizeIfPrecedenceCouldChange(withConversion); // Use context of outer node, rather than just its exprssion, as the above method call would do if allowed to add parenthesis
}

Expand Down
2 changes: 1 addition & 1 deletion CodeConverter/CSharp/TypeConversionAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ private ITypeSymbol GetCSType(ITypeSymbol vbType, VBSyntax.ExpressionSyntax vbNo
} else if (vbConversion.IsNumeric && (csConversion.IsNumeric || nullableVbConvertedType.IsEnumType()) && isConvertFractionalToInt) {
typeConversionKind = TypeConversionKind.FractionalNumberRoundThenCast;
return true;
} else if (csConversion.IsExplicit && csConversion.IsEnumeration || csConversion.IsBoxing) {
} else if (csConversion is {IsExplicit: true, IsEnumeration: true} or {IsBoxing: true, IsImplicit: false}) {
typeConversionKind = TypeConversionKind.NonDestructiveCast;
return true;
} else if (vbConversion.IsNumeric && csConversion.IsNumeric) {
Expand Down
2 changes: 1 addition & 1 deletion Tests/CSharp/ExpressionTests/BinaryExpressionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -668,7 +668,7 @@ private object TestMethod()
{
bool? var1 = default;
bool? var2 = default;
return (object)(var1.GetValueOrDefault() ? true : !var2 is not { } arg1 ? null : arg1 ? true : var1);
return var1.GetValueOrDefault() ? true : !var2 is not { } arg1 ? null : arg1 ? true : var1;
}
}");
}
Expand Down
34 changes: 30 additions & 4 deletions Tests/CSharp/ExpressionTests/ExpressionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,33 @@ public bool IsPointWithinBoundaryBox(double dblLat, double dblLon, object boundb
}");
}

[Fact]
public async Task DynamicAccessAsync()
{
await TestConversionVisualBasicToCSharpAsync(@"Option Strict Off ' Directive gets removed
Public Class TestDynamicUsage
Property Prop As Integer
Sub S()
Dim o As Object
o = New TestDynamicUsage
o.Prop = 1 'Must not cast to object here
End Sub
End Class", @"
public partial class TestDynamicUsage
{
public int Prop { get; set; }
public void S()
{
object o;
o = new TestDynamicUsage();
((dynamic)o).Prop = 1; // Must not cast to object here
}
}");
}

[Fact]
public async Task ConversionOfNotUsesParensIfNeededAsync()
{
Expand Down Expand Up @@ -267,12 +294,11 @@ public partial class VisualBasicClass
public void Rounding()
{
object o = 3.0f;
var x = Math.Round(o, (object)2);
var x = Math.Round(o, 2);
}
}
2 target compilation errors:
CS1503: Argument 1: cannot convert from 'object' to 'double'
CS1503: Argument 2: cannot convert from 'object' to 'int'");
1 target compilation errors:
CS1503: Argument 1: cannot convert from 'object' to 'double'");
}

[Fact]
Expand Down
2 changes: 1 addition & 1 deletion Tests/CSharp/MissingSemanticModelInfo/ExpressionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ public void Test()
{
SomeUnknownType x = default;
int y = 3;
if (x == null || (object)y == null)
if (x == null || y == null)
{
}
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 5590951

Please sign in to comment.