Skip to content

Commit 311e1e6

Browse files
Select case for a mixture of strings and characters converts correctly - fixes #1061
1 parent 480e4e8 commit 311e1e6

3 files changed

Lines changed: 52 additions & 5 deletions

File tree

CHANGELOG.md

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

1313
* Remove square brackets from identifiers [#1043](https://github.com/icsharpcode/CodeConverter/issues/1043)
1414
* Conversion of parenthesized ref arguments no longer assigns back [#1046](https://github.com/icsharpcode/CodeConverter/issues/1046)
15+
* Conversion of explicit interface implementations now converts optional parameters [#1062](https://github.com/icsharpcode/CodeConverter/issues/1062)
16+
* Constant chars are converted to constant strings where needed
17+
* Select case for a mixture of strings and characters converts correctly [#1062](https://github.com/icsharpcode/CodeConverter/issues/1062)
18+
1519

1620
### C# -> VB
1721

CodeConverter/CSharp/MethodBodyExecutableStatementVisitor.cs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -770,7 +770,9 @@ public override async Task<SyntaxList<StatementSyntax>> VisitSelectBlock(VBSynta
770770

771771
// CSharp requires an explicit cast from the base type (e.g. int) in most cases switching on an enum
772772
var isBooleanCase = caseTypeInfo.Type?.SpecialType == SpecialType.System_Boolean;
773-
var csExpressionToUse = IsEnumOrNullableEnum(switchExprTypeInfo.ConvertedType) ^ IsEnumOrNullableEnum(caseTypeInfo.Type) && !isBooleanCase ? correctTypeExpressionSyntax.Expr : originalExpressionSyntax;
773+
bool enumRelated = IsEnumOrNullableEnum(switchExprTypeInfo.ConvertedType) || IsEnumOrNullableEnum(caseTypeInfo.Type);
774+
bool convertingEnum = IsEnumOrNullableEnum(switchExprTypeInfo.ConvertedType) ^ IsEnumOrNullableEnum(caseTypeInfo.Type);
775+
var csExpressionToUse = !isBooleanCase && (convertingEnum || !enumRelated && correctTypeExpressionSyntax.IsConst) ? correctTypeExpressionSyntax.Expr : originalExpressionSyntax;
774776

775777
var caseSwitchLabelSyntax = !wrapForStringComparison && correctTypeExpressionSyntax.IsConst && notAlreadyUsed
776778
? (SwitchLabelSyntax)SyntaxFactory.CaseSwitchLabel(csExpressionToUse)
@@ -783,14 +785,19 @@ public override async Task<SyntaxList<StatementSyntax>> VisitSelectBlock(VBSynta
783785
var varName = CommonConversions.CsEscapedIdentifier(GetUniqueVariableNameInScope(node, "case"));
784786
ExpressionSyntax csLeft = ValidSyntaxFactory.IdentifierName(varName);
785787
var operatorKind = VBasic.VisualBasicExtensions.Kind(relational);
786-
var relationalValue = await relational.Value.AcceptAsync<ExpressionSyntax>(_expressionVisitor);
787-
var binaryExp = SyntaxFactory.BinaryExpression(operatorKind.ConvertToken(), csLeft, relationalValue);
788+
var csRelationalValue = await relational.Value.AcceptAsync<ExpressionSyntax>(_expressionVisitor);
789+
csRelationalValue = CommonConversions.TypeConversionAnalyzer.AddExplicitConversion(relational.Value, csRelationalValue);
790+
var binaryExp = SyntaxFactory.BinaryExpression(operatorKind.ConvertToken(), csLeft, csRelationalValue);
788791
labels.Add(VarWhen(varName, binaryExp));
789792
} else if (c is VBSyntax.RangeCaseClauseSyntax range) {
790793
var varName = CommonConversions.CsEscapedIdentifier(GetUniqueVariableNameInScope(node, "case"));
791794
ExpressionSyntax csLeft = ValidSyntaxFactory.IdentifierName(varName);
792-
var lowerBoundCheck = SyntaxFactory.BinaryExpression(SyntaxKind.LessThanOrEqualExpression, await range.LowerBound.AcceptAsync<ExpressionSyntax>(_expressionVisitor), csLeft);
793-
var upperBoundCheck = SyntaxFactory.BinaryExpression(SyntaxKind.LessThanOrEqualExpression, csLeft, await range.UpperBound.AcceptAsync<ExpressionSyntax>(_expressionVisitor));
795+
var lowerBound = await range.LowerBound.AcceptAsync<ExpressionSyntax>(_expressionVisitor);
796+
lowerBound = CommonConversions.TypeConversionAnalyzer.AddExplicitConversion(range.LowerBound, lowerBound);
797+
var lowerBoundCheck = SyntaxFactory.BinaryExpression(SyntaxKind.LessThanOrEqualExpression, lowerBound, csLeft);
798+
var upperBound = await range.UpperBound.AcceptAsync<ExpressionSyntax>(_expressionVisitor);
799+
upperBound = CommonConversions.TypeConversionAnalyzer.AddExplicitConversion(range.UpperBound, upperBound);
800+
var upperBoundCheck = SyntaxFactory.BinaryExpression(SyntaxKind.LessThanOrEqualExpression, csLeft, upperBound);
794801
var withinBounds = SyntaxFactory.BinaryExpression(SyntaxKind.LogicalAndExpression, lowerBoundCheck, upperBoundCheck);
795802
labels.Add(VarWhen(varName, withinBounds));
796803
} else {

Tests/CSharp/TypeCastTests.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1360,6 +1360,42 @@ private string[] QuoteSplit(string text)
13601360
}");
13611361
}
13621362

1363+
1364+
[Fact]
1365+
public async Task TestSelectCaseComparesCharsAndStringsAsync()
1366+
{
1367+
await TestConversionVisualBasicToCSharpAsync(
1368+
@"
1369+
Class CharTestClass
1370+
Private Sub Q()
1371+
Select Case ""a""
1372+
Case ""x""c To ""y""c
1373+
Case ""b""c
1374+
End Select
1375+
End Sub
1376+
End Class", @"
1377+
internal partial class CharTestClass
1378+
{
1379+
private void Q()
1380+
{
1381+
switch (""a"")
1382+
{
1383+
case var @case when ""x"" <= @case && @case <= ""y"":
1384+
{
1385+
break;
1386+
}
1387+
1388+
case ""b"":
1389+
{
1390+
break;
1391+
}
1392+
}
1393+
}
1394+
}
1395+
1 target compilation errors:
1396+
CS0825: The contextual keyword 'var' may only appear within a local variable declaration or in script code");
1397+
}
1398+
13631399
[Fact]
13641400
public async Task TestSingleCharacterStringLiteralBecomesChar_WhenExplictCastAsync()
13651401
{

0 commit comments

Comments
 (0)