Skip to content

Commit 79b9bdb

Browse files
Remove explicit cast where possible - fixes #388
1 parent 6e73565 commit 79b9bdb

File tree

7 files changed

+139
-89
lines changed

7 files changed

+139
-89
lines changed

CodeConverter/CSharp/ExpressionNodeVisitor.cs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -237,15 +237,7 @@ public override async Task<CSharpSyntaxNode> VisitPredefinedCastExpression(VBasi
237237
SyntaxFactory.Argument(expressionSyntax))));
238238
}
239239

240-
var convertMethodForKeywordOrNull = GetConvertMethodForKeywordOrNull(node);
241-
242-
return convertMethodForKeywordOrNull != null ? (ExpressionSyntax)
243-
SyntaxFactory.InvocationExpression(convertMethodForKeywordOrNull,
244-
SyntaxFactory.ArgumentList(
245-
SyntaxFactory.SingletonSeparatedList(
246-
SyntaxFactory.Argument(expressionSyntax)))
247-
) // Hopefully will be a compile error if it's wrong
248-
: ValidSyntaxFactory.CastExpression(SyntaxFactory.PredefinedType(node.Keyword.ConvertToken()), expressionSyntax);
240+
return CommonConversions.TypeConversionAnalyzer.AddExplicitConversion(node.Expression, expressionSyntax, true, false, forceTargetType: _semanticModel.GetTypeInfo(node).Type);
249241
}
250242

251243
public override async Task<CSharpSyntaxNode> VisitTryCastExpression(VBasic.Syntax.TryCastExpressionSyntax node)

CodeConverter/CSharp/TypeConversionAnalyzer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ private bool TryAnalyzeCsConversion(Microsoft.CodeAnalysis.VisualBasic.Syntax.Ex
196196
// e.g. sbyte * ulong uses the decimal * operator in VB. In C# it's ambiguous - see ExpressionTests.vb "TestMul".
197197
typeConversionKind = TypeConversionKind.NonDestructiveCast;
198198
return true;
199-
} else if (csConversion.IsExplicit && csConversion.IsEnumeration) {
199+
} else if (csConversion.IsExplicit && csConversion.IsEnumeration || csConversion.IsBoxing) {
200200
typeConversionKind = TypeConversionKind.NonDestructiveCast;
201201
return true;
202202
} else if (isArithmetic) {

CodeConverter/Shared/ProjectConversion.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ public static async IAsyncEnumerable<ConversionResult> ConvertProject(Project pr
9595
await foreach (var result in results) yield return result;
9696
}
9797

98-
/// <remarks>Perf: Keep lazy so that we don't keep all files in memory at once</remarks>
98+
/// <remarks>Perf: Keep lazy so that we don't keep an extra copy of all files in memory at once</remarks>
9999
private static async IAsyncEnumerable<ConversionResult> WithProjectFile(IProjectContentsConverter projectContentsConverter, ILanguageConversion languageConversion, ImmutableHashSet<string> originalSourcePaths, IAsyncEnumerable<ConversionResult> convertProjectContents, (string Find, string Replace, bool FirstOnly)[] replacements)
100100
{
101101
var project = projectContentsConverter.Project;

Tests/CSharp/ExpressionTests/ExpressionTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,7 +1023,7 @@ private void TestMethod()
10231023
object test(object a) => a * 2;
10241024
object test2(object a, object b)
10251025
{
1026-
if (Conversions.ToBoolean(b > 0))
1026+
if (Conversions.ToBoolean(b > (object)0))
10271027
return a / b;
10281028
return 0;
10291029
};
@@ -1032,8 +1032,8 @@ object test2(object a, object b)
10321032
}
10331033
}
10341034
4 target compilation errors:
1035-
CS0019: Operator '*' cannot be applied to operands of type 'object' and 'int'
1036-
CS0019: Operator '>' cannot be applied to operands of type 'object' and 'int'
1035+
CS0019: Operator '*' cannot be applied to operands of type 'object' and 'object'
1036+
CS0019: Operator '>' cannot be applied to operands of type 'object' and 'object'
10371037
CS0019: Operator '/' cannot be applied to operands of type 'object' and 'object'
10381038
CS0019: Operator '%' cannot be applied to operands of type 'object' and 'object'");
10391039
}

Tests/CSharp/StatementTests/LoopStatementTests.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,6 @@ Private Sub TestMethod()
512512
Next
513513
End Sub
514514
End Class", @"using System;
515-
using Microsoft.VisualBasic.CompilerServices;
516515
517516
internal partial class TestClass
518517
{
@@ -521,7 +520,7 @@ private void TestMethod()
521520
string stringValue = ""42"";
522521
for (int i = 1, loopTo = 10 - stringValue.Length; i <= loopTo; i++)
523522
{
524-
stringValue = stringValue + "" "" + Conversions.ToString(i);
523+
stringValue = stringValue + "" "" + i.ToString();
525524
Console.WriteLine(stringValue);
526525
}
527526
}

Tests/CSharp/TypeCastTests.cs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,19 @@ private string[] QuoteSplit(string text)
326326
}");
327327
}
328328

329+
[Fact]
330+
public async Task TestSingleCharacterStringLiteralBecomesChar_WhenExplictCastAsync()
331+
{
332+
await TestConversionVisualBasicToCSharpAsync(
333+
@"Class ExplicitCastClass
334+
Dim wordArray As String() = 1.ToString().Split(CChar("",""))
335+
End Class", @"
336+
internal partial class ExplicitCastClass
337+
{
338+
private string[] wordArray = 1.ToString().Split(',');
339+
}");
340+
}
341+
329342
[Fact]
330343
public async Task TestCastHasBracketsWhenElementAccessAsync()
331344
{
@@ -342,6 +355,52 @@ private int Casting(object sender)
342355
{
343356
return Conversions.ToInteger(((object[])sender)[0]);
344357
}
358+
}");
359+
}
360+
361+
[Fact]
362+
public async Task MultipleNestedCastsAsync()
363+
{
364+
await TestConversionVisualBasicToCSharpAsync(
365+
@"Public Class MultipleCasts
366+
Public Shared Function ToGenericParameter(Of T)(Value As Object) As T
367+
If Value Is Nothing Then
368+
Return Nothing
369+
End If
370+
Dim reflectedType As Global.System.Type = GetType(T)
371+
If Global.System.Type.Equals(reflectedType, GetType(Global.System.Int16)) Then
372+
Return DirectCast(CObj(CShort(Value)), T)
373+
ElseIf Global.System.Type.Equals(reflectedType, GetType(Global.System.UInt64)) Then
374+
Return DirectCast(CObj(CULng(Value)), T)
375+
Else
376+
Return DirectCast(Value, T)
377+
End If
378+
End Function
379+
End Class", @"using Microsoft.VisualBasic.CompilerServices;
380+
381+
public partial class MultipleCasts
382+
{
383+
public static T ToGenericParameter<T>(object Value)
384+
{
385+
if (Value is null)
386+
{
387+
return default;
388+
}
389+
390+
var reflectedType = typeof(T);
391+
if (Equals(reflectedType, typeof(short)))
392+
{
393+
return (T)(object)Conversions.ToShort(Value);
394+
}
395+
else if (Equals(reflectedType, typeof(ulong)))
396+
{
397+
return (T)(object)Conversions.ToULong(Value);
398+
}
399+
else
400+
{
401+
return (T)Value;
402+
}
403+
}
345404
}");
346405
}
347406
}

0 commit comments

Comments
 (0)