Skip to content

Commit

Permalink
Merge pull request #1162 from icsharpcode/issue-1159-inferred-generic…
Browse files Browse the repository at this point in the history
…-integer-type-cast

Issue 1159 inferred generic integer type cast
  • Loading branch information
GrahamTheCoder authored Jan 22, 2025
2 parents 67185b0 + c5180ef commit 71aa79c
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 2 deletions.
10 changes: 8 additions & 2 deletions CodeConverter/CSharp/TypeConversionAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ private ExpressionSyntax AddTypeConversion(VBSyntax.ExpressionSyntax vbNode, Exp
var enumUnderlyingType = ((INamedTypeSymbol) vbType).EnumUnderlyingType;
csNode = AddTypeConversion(vbNode, csNode, TypeConversionKind.NonDestructiveCast, addParenthesisIfNeeded, vbType, enumUnderlyingType);
return AddTypeConversion(vbNode, csNode, TypeConversionKind.Conversion, addParenthesisIfNeeded, enumUnderlyingType, vbConvertedType);
case TypeConversionKind.LiteralSuffix:
if (csNode is CSSyntax.LiteralExpressionSyntax && vbNode is VBSyntax.LiteralExpressionSyntax { Token: { Value: { } val, Text: { } text } } && LiteralConversions.GetLiteralExpression(val, text, vbConvertedType) is { } csLiteral) {
return csLiteral;
}
return csNode;
case TypeConversionKind.Unknown:
case TypeConversionKind.Identity:
return addParenthesisIfNeeded ? vbNode.ParenthesizeIfPrecedenceCouldChange(csNode) : csNode;
Expand Down Expand Up @@ -327,7 +332,7 @@ private bool TryAnalyzeCsConversion(VBasic.VisualBasicCompilation vbCompilation,
// e.g. When VB "&" changes to C# "+", there are lots more overloads available that implicit casts could match.
// e.g. sbyte * ulong uses the decimal * operator in VB. In C# it's ambiguous - see ExpressionTests.vb "TestMul".
typeConversionKind =
isConst && IsImplicitConstantConversion(vbNode) || csUnderlyingConversion.IsIdentity || !sourceForced && IsExactTypeNumericLiteral(vbNode, underlyingVbConvertedType) ? TypeConversionKind.Identity :
isConst && IsImplicitConstantConversion(vbNode) || csUnderlyingConversion.IsIdentity || !sourceForced && IsExactTypeNumericLiteral(vbNode, underlyingVbConvertedType) ? TypeConversionKind.LiteralSuffix :
csUnderlyingConversion.IsImplicit || underlyingVbType.IsNumericType() ? TypeConversionKind.NonDestructiveCast
: TypeConversionKind.Conversion;
return true;
Expand Down Expand Up @@ -502,7 +507,8 @@ public enum TypeConversionKind
NullableBool,
StringToCharArray,
DelegateConstructor,
FractionalNumberRoundThenCast
FractionalNumberRoundThenCast,
LiteralSuffix
}

public static bool ConvertStringToCharLiteral(VBSyntax.ExpressionSyntax node,
Expand Down
78 changes: 78 additions & 0 deletions Tests/CSharp/TypeCastTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1559,6 +1559,84 @@ private static T GenericFunctionWithCastThatExistsInCsharp<T>() where T : TestGe
}

[Fact]
public async Task TestInferringImplicitGenericTypesAsync()
{
await TestConversionVisualBasicToCSharpAsync(@"
Imports System
Imports System.Linq
Public Class TestClass
Public Sub GenerateFromConstants
Dim floatArr = Enumerable.Repeat(1.0F, 5).ToArray()
Dim doubleArr = Enumerable.Repeat(2.0, 5).ToArray()
Dim decimalArr = Enumerable.Repeat(3.0D, 5).ToArray()
Dim boolArr = Enumerable.Repeat(true, 5).ToArray()
Dim intArr = Enumerable.Repeat(1, 5).ToArray()
Dim uintArr = Enumerable.Repeat(1ui, 5).ToArray()
Dim longArr = Enumerable.Repeat(1l, 5).ToArray()
Dim ulongArr = Enumerable.Repeat(1ul, 5).ToArray()
Dim charArr = Enumerable.Repeat(""a""c, 5).ToArray()
Dim strArr = Enumerable.Repeat(""a"", 5).ToArray()
Dim objArr = Enumerable.Repeat(new object(), 5).ToArray()
End Sub
Public Sub GenerateFromCasts
Dim floatArr = Enumerable.Repeat(CSng(1), 5).ToArray()
Dim doubleArr = Enumerable.Repeat(CDbl(2), 5).ToArray()
Dim decimalArr = Enumerable.Repeat(CDec(3), 5).ToArray()
Dim boolArr = Enumerable.Repeat(CBool(1), 5).ToArray()
Dim intArr = Enumerable.Repeat(CInt(1.0), 5).ToArray()
Dim uintArr = Enumerable.Repeat(CUInt(1.0), 5).ToArray()
Dim longArr = Enumerable.Repeat(CLng(1.0), 5).ToArray()
Dim ulongArr = Enumerable.Repeat(CULng(1.0), 5).ToArray()
Dim charArr = Enumerable.Repeat(CChar(""a""), 5).ToArray()
Dim strArr = Enumerable.Repeat(CStr(""a""c), 5).ToArray()
Dim objArr1 = Enumerable.Repeat(CObj(""a""), 5).ToArray()
Dim objArr2 = Enumerable.Repeat(CType(""a"", object), 5).ToArray()
End Sub
End Class
", @"
using System;
using System.Linq;
using Microsoft.VisualBasic.CompilerServices; // Install-Package Microsoft.VisualBasic
public partial class TestClass
{
public void GenerateFromConstants()
{
float[] floatArr = Enumerable.Repeat(1.0f, 5).ToArray();
double[] doubleArr = Enumerable.Repeat(2.0d, 5).ToArray();
decimal[] decimalArr = Enumerable.Repeat(3.0m, 5).ToArray();
bool[] boolArr = Enumerable.Repeat(true, 5).ToArray();
int[] intArr = Enumerable.Repeat(1, 5).ToArray();
uint[] uintArr = Enumerable.Repeat(1U, 5).ToArray();
long[] longArr = Enumerable.Repeat(1L, 5).ToArray();
ulong[] ulongArr = Enumerable.Repeat(1UL, 5).ToArray();
char[] charArr = Enumerable.Repeat('a', 5).ToArray();
string[] strArr = Enumerable.Repeat(""a"", 5).ToArray();
object[] objArr = Enumerable.Repeat(new object(), 5).ToArray();
}
public void GenerateFromCasts()
{
float[] floatArr = Enumerable.Repeat(1f, 5).ToArray();
double[] doubleArr = Enumerable.Repeat(2d, 5).ToArray();
decimal[] decimalArr = Enumerable.Repeat(3m, 5).ToArray();
bool[] boolArr = Enumerable.Repeat(Conversions.ToBoolean(1), 5).ToArray();
int[] intArr = Enumerable.Repeat((int)Math.Round(1.0d), 5).ToArray();
uint[] uintArr = Enumerable.Repeat((uint)Math.Round(1.0d), 5).ToArray();
long[] longArr = Enumerable.Repeat((long)Math.Round(1.0d), 5).ToArray();
ulong[] ulongArr = Enumerable.Repeat((ulong)Math.Round(1.0d), 5).ToArray();
char[] charArr = Enumerable.Repeat('a', 5).ToArray();
string[] strArr = Enumerable.Repeat(""a"", 5).ToArray();
object[] objArr1 = Enumerable.Repeat((object)""a"", 5).ToArray();
object[] objArr2 = Enumerable.Repeat((object)""a"", 5).ToArray();
}
}");
}


[Fact]
public async Task TestCTypeStringToEnumAsync()
{
await TestConversionVisualBasicToCSharpAsync(
Expand Down

0 comments on commit 71aa79c

Please sign in to comment.