Skip to content

Commit 5590951

Browse files
Only cast for boxing when it's not implicit - fixes #1071
But since this removes some casts, do still ensure that predefined cast expressions always cast since otherwise casting to T via object gets broken
1 parent d95dcb6 commit 5590951

9 files changed

Lines changed: 38 additions & 11 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
1515
* Conversion of explicit interface implementations now converts optional parameters [#1062](https://github.com/icsharpcode/CodeConverter/issues/1062)
1616
* Constant chars are converted to constant strings where needed
1717
* Select case for a mixture of strings and characters converts correctly [#1062](https://github.com/icsharpcode/CodeConverter/issues/1062)
18+
* Implicit boxing conversion converted correctly to no-op [#1071](https://github.com/icsharpcode/CodeConverter/issues/1071)
1819

1920
### C# -> VB
2021

CodeConverter/CSharp/ExpressionNodeVisitor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ public override async Task<CSharpSyntaxNode> VisitPredefinedCastExpression(VBasi
291291
SyntaxFactory.Argument(expressionSyntax))));
292292
}
293293

294-
var withConversion = CommonConversions.TypeConversionAnalyzer.AddExplicitConversion(node.Expression, expressionSyntax, false, false, forceTargetType: _semanticModel.GetTypeInfo(node).Type);
294+
var withConversion = CommonConversions.TypeConversionAnalyzer.AddExplicitConversion(node.Expression, expressionSyntax, false, true, forceTargetType: _semanticModel.GetTypeInfo(node).Type);
295295
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
296296
}
297297

CodeConverter/CSharp/TypeConversionAnalyzer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ private bool TryAnalyzeCsConversion(VBSyntax.ExpressionSyntax vbNode, ITypeSymbo
311311
} else if (vbConversion.IsNumeric && (csConversion.IsNumeric || nullableVbConvertedType.IsEnumType()) && isConvertFractionalToInt) {
312312
typeConversionKind = TypeConversionKind.FractionalNumberRoundThenCast;
313313
return true;
314-
} else if (csConversion.IsExplicit && csConversion.IsEnumeration || csConversion.IsBoxing) {
314+
} else if (csConversion is {IsExplicit: true, IsEnumeration: true} or {IsBoxing: true, IsImplicit: false}) {
315315
typeConversionKind = TypeConversionKind.NonDestructiveCast;
316316
return true;
317317
} else if (vbConversion.IsNumeric && csConversion.IsNumeric) {

Tests/CSharp/ExpressionTests/BinaryExpressionTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -668,7 +668,7 @@ private object TestMethod()
668668
{
669669
bool? var1 = default;
670670
bool? var2 = default;
671-
return (object)(var1.GetValueOrDefault() ? true : !var2 is not { } arg1 ? null : arg1 ? true : var1);
671+
return var1.GetValueOrDefault() ? true : !var2 is not { } arg1 ? null : arg1 ? true : var1;
672672
}
673673
}");
674674
}

Tests/CSharp/ExpressionTests/ExpressionTests.cs

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,33 @@ public bool IsPointWithinBoundaryBox(double dblLat, double dblLon, object boundb
8080
}");
8181
}
8282

83+
[Fact]
84+
public async Task DynamicAccessAsync()
85+
{
86+
await TestConversionVisualBasicToCSharpAsync(@"Option Strict Off ' Directive gets removed
87+
88+
Public Class TestDynamicUsage
89+
Property Prop As Integer
90+
91+
Sub S()
92+
Dim o As Object
93+
o = New TestDynamicUsage
94+
o.Prop = 1 'Must not cast to object here
95+
End Sub
96+
End Class", @"
97+
public partial class TestDynamicUsage
98+
{
99+
public int Prop { get; set; }
100+
101+
public void S()
102+
{
103+
object o;
104+
o = new TestDynamicUsage();
105+
((dynamic)o).Prop = 1; // Must not cast to object here
106+
}
107+
}");
108+
}
109+
83110
[Fact]
84111
public async Task ConversionOfNotUsesParensIfNeededAsync()
85112
{
@@ -267,12 +294,11 @@ public partial class VisualBasicClass
267294
public void Rounding()
268295
{
269296
object o = 3.0f;
270-
var x = Math.Round(o, (object)2);
297+
var x = Math.Round(o, 2);
271298
}
272299
}
273-
2 target compilation errors:
274-
CS1503: Argument 1: cannot convert from 'object' to 'double'
275-
CS1503: Argument 2: cannot convert from 'object' to 'int'");
300+
1 target compilation errors:
301+
CS1503: Argument 1: cannot convert from 'object' to 'double'");
276302
}
277303

278304
[Fact]

Tests/CSharp/MissingSemanticModelInfo/ExpressionTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ public void Test()
391391
{
392392
SomeUnknownType x = default;
393393
int y = 3;
394-
if (x == null || (object)y == null)
394+
if (x == null || y == null)
395395
{
396396
397397
}

Tests/TestData/MultiFileCharacterization/VBToCSResults/ConvertVbLibraryOnly/VbLibrary/My Project/MyNamespace.Static.2.Designer.cs

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Tests/TestData/MultiFileCharacterization/VBToCSResults/ConvertWholeSolution/VbLibrary/My Project/MyNamespace.Static.2.Designer.cs

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Tests/TestData/MultiFileCharacterization/VBToCSResults/ConvertWholeSolution/VbNetStandardLib/My Project/MyNamespace.Static.2.Designer.cs

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)