Skip to content

Commit f191ece

Browse files
Correctly use numeric value - fixes #590
1 parent 9cdda59 commit f191ece

8 files changed

Lines changed: 68 additions & 15 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
1010

1111
### VB -> C#
1212
* Correct logic for conversion "objectWithOverloadedEquals Is Nothing" [#591](https://github.com/icsharpcode/CodeConverter/issues/591)
13+
* Coercing enum to a string now correctly uses its numeric value [#590](https://github.com/icsharpcode/CodeConverter/issues/590)
1314

1415
### C# -> VB
1516

CodeConverter/CSharp/BuiltInVisualBasicOperatorSubstitutions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public async Task<ExpressionSyntax> ConvertNothingComparisonOrNullAsync(VBSyntax
5959
return null;
6060
}
6161
var csOtherArg = (ExpressionSyntax)await ConvertIsOrIsNotExpressionArgAsync(vbOtherArg);
62-
var couldHaveOverloadedOperators = _semanticModel.GetTypeInfo(vbOtherArg).Type.SpecialType == SpecialType.None;
62+
var couldHaveOverloadedOperators = !_semanticModel.GetTypeInfo(vbOtherArg).Type.IsSpecialType();
6363
var isReferenceComparison = node.IsKind(VBasic.SyntaxKind.IsExpression, VBasic.SyntaxKind.IsNotExpression);
6464
var notted = node.IsKind(VBasic.SyntaxKind.IsNotExpression, VBasic.SyntaxKind.NotEqualsExpression) || negateExpression;
6565
return notted ? CommonConversions.NotNothingComparison(csOtherArg, isReferenceComparison) : CommonConversions.NothingComparison(csOtherArg, isReferenceComparison, couldHaveOverloadedOperators);

CodeConverter/CSharp/ExpressionNodeVisitor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -713,7 +713,7 @@ public override async Task<CSharpSyntaxNode> VisitBinaryExpression(VBasic.Syntax
713713
ITypeSymbol forceLhsTargetType = null;
714714
bool omitRightConversion = false;
715715
bool omitConversion = false;
716-
if (node.IsKind(VBasic.SyntaxKind.ConcatenateExpression)) {
716+
if (node.IsKind(VBasic.SyntaxKind.ConcatenateExpression) && !lhsTypeInfo.Type.IsEnumType() && !rhsTypeInfo.Type.IsEnumType()) {
717717
omitRightConversion = true;
718718
omitConversion = lhsTypeInfo.Type.SpecialType == SpecialType.System_String ||
719719
rhsTypeInfo.Type.SpecialType == SpecialType.System_String;

CodeConverter/CSharp/TypeConversionAnalyzer.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,13 @@ private ExpressionSyntax AddTypeConversion(VBSyntax.ExpressionSyntax vbNode, Exp
8383
{
8484
switch (conversionKind) {
8585
case TypeConversionKind.EnumConversionThenCast:
86-
csNode = AddTypeConversion(vbNode, csNode, TypeConversionKind.Conversion, addParenthesisIfNeeded, vbType, ((INamedTypeSymbol) vbConvertedType).EnumUnderlyingType);
87-
return AddTypeConversion(vbNode, csNode, TypeConversionKind.NonDestructiveCast, addParenthesisIfNeeded, vbType, vbConvertedType);
86+
var underlyingType = ((INamedTypeSymbol) vbConvertedType).EnumUnderlyingType;
87+
csNode = AddTypeConversion(vbNode, csNode, TypeConversionKind.Conversion, addParenthesisIfNeeded, vbType, underlyingType);
88+
return AddTypeConversion(vbNode, csNode, TypeConversionKind.NonDestructiveCast, addParenthesisIfNeeded, underlyingType, vbConvertedType);
89+
case TypeConversionKind.EnumCastThenConversion:
90+
var enumUnderlyingType = ((INamedTypeSymbol) vbType).EnumUnderlyingType;
91+
csNode = AddTypeConversion(vbNode, csNode, TypeConversionKind.NonDestructiveCast, addParenthesisIfNeeded, vbType, enumUnderlyingType);
92+
return AddTypeConversion(vbNode, csNode, TypeConversionKind.Conversion, addParenthesisIfNeeded, enumUnderlyingType, vbConvertedType);
8893
case TypeConversionKind.Unknown:
8994
case TypeConversionKind.Identity:
9095
return addParenthesisIfNeeded ? VbSyntaxNodeExtensions.ParenthesizeIfPrecedenceCouldChange(vbNode, csNode) : csNode;
@@ -132,7 +137,9 @@ public TypeConversionKind AnalyzeConversion(Microsoft.CodeAnalysis.VisualBasic.S
132137
(vbConvertedType.IsNullable() && vbType.Equals(vbConvertedType.GetNullableUnderlyingType())) ||
133138
vbConvertedType.SpecialType == SpecialType.System_Object) {
134139
return TypeConversionKind.Identity;
135-
} else {
140+
} else if (vbConvertedType.SpecialType == SpecialType.System_String) {
141+
return TypeConversionKind.EnumCastThenConversion;
142+
}else {
136143
return TypeConversionKind.Conversion;
137144
}
138145
}
@@ -313,8 +320,9 @@ public enum TypeConversionKind
313320
NonDestructiveCast,
314321
Conversion,
315322
EnumConversionThenCast,
323+
EnumCastThenConversion,
316324
NullableBool,
317-
StringToCharArray
325+
StringToCharArray,
318326
}
319327

320328
public static bool ConvertStringToCharLiteral(Microsoft.CodeAnalysis.VisualBasic.Syntax.ExpressionSyntax node,

Tests/CSharp/ExpressionTests/StringExpressionTests.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,5 +361,38 @@ public Issue396ComparisonOperatorForStringsAsync()
361361
private object b;
362362
}");
363363
}
364+
365+
[Fact]
366+
public async Task Issue590EnumConvertsToNumericStringAsync()
367+
{
368+
await TestConversionVisualBasicToCSharpAsync(
369+
@"Public Class EnumTests
370+
Private Enum RankEnum As SByte
371+
First = 1
372+
Second = 2
373+
End Enum
374+
375+
Public Sub TestEnumConcat()
376+
Console.Write(RankEnum.First & RankEnum.Second)
377+
End Sub
378+
End Class",
379+
@"using System;
380+
381+
public partial class EnumTests
382+
{
383+
private enum RankEnum : sbyte
384+
{
385+
First = 1,
386+
Second = 2
387+
}
388+
389+
public void TestEnumConcat()
390+
{
391+
Console.Write(RankEnum.First + RankEnum.Second);
392+
}
393+
}
394+
1 target compilation errors:
395+
CS0019: Operator '+' cannot be applied to operands of type 'EnumTests.RankEnum' and 'EnumTests.RankEnum'");
396+
}
364397
}
365398
}

Tests/CSharp/MissingSemanticModelInfo/ExpressionTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ public string PositionEnumStringFromConstant(PositionEnum pS)
243243
244244
default:
245245
{
246-
tS = Conversions.ToString(pS);
246+
tS = ((int)pS).ToString();
247247
break;
248248
}
249249
}

Tests/CSharp/NamespaceLevelTests.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -861,14 +861,14 @@ public static void Main()
861861
double vDoubleUInteger = (double)EUInteger.M1;
862862
double vDoubleLong = (double)ELong.M1;
863863
double vDoubleULong = (double)EULong.M1;
864-
string vStringSByte = Conversions.ToString(ESByte.M1);
865-
string vStringByte = Conversions.ToString(EByte.M1);
866-
string vStringShort = Conversions.ToString(EShort.M1);
867-
string vStringUShort = Conversions.ToString(EUShort.M1);
868-
string vStringInteger = Conversions.ToString(EInteger.M1);
869-
string vStringUInteger = Conversions.ToString(EUInteger.M1);
870-
string vStringLong = Conversions.ToString(ELong.M1);
871-
string vStringULong = Conversions.ToString(EULong.M1);
864+
string vStringSByte = ((sbyte)ESByte.M1).ToString();
865+
string vStringByte = ((byte)EByte.M1).ToString();
866+
string vStringShort = ((short)EShort.M1).ToString();
867+
string vStringUShort = ((ushort)EUShort.M1).ToString();
868+
string vStringInteger = ((int)EInteger.M1).ToString();
869+
string vStringUInteger = ((uint)EUInteger.M1).ToString();
870+
string vStringLong = ((long)ELong.M1).ToString();
871+
string vStringULong = ((ulong)EULong.M1).ToString();
872872
object vObjectSByte = ESByte.M1;
873873
object vObjectByte = EByte.M1;
874874
object vObjectShort = EShort.M1;

Tests/TestData/SelfVerifyingTests/VBToCS/EnumTests.vb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,15 @@ Public Class EnumTests
5656
}
5757
Console.WriteLine(a)
5858
End Sub
59+
60+
<Fact>
61+
Public Sub TestEnumConcat()
62+
Assert.Equal(RankEnum.Second.ToString() & RankEnum.Second, "Second2")
63+
End Sub
64+
65+
<Fact>
66+
Public Sub TestEnumstringCoerce()
67+
Dim s As String = RankEnum.Second
68+
Assert.Equal(s & RankEnum.Second, "22")
69+
End Sub
5970
End Class

0 commit comments

Comments
 (0)