diff --git a/CHANGELOG.md b/CHANGELOG.md index eb0f4f4b..ed22740c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) * Remove square brackets from identifiers [#1043](https://github.com/icsharpcode/CodeConverter/issues/1043) * Conversion of parenthesized ref arguments no longer assigns back [#1046](https://github.com/icsharpcode/CodeConverter/issues/1046) +* Conversion of explicit interface implementations now converts optional parameters [#1062](https://github.com/icsharpcode/CodeConverter/issues/1062) +* Constant chars are converted to constant strings where needed +* Select case for a mixture of strings and characters converts correctly [#1062](https://github.com/icsharpcode/CodeConverter/issues/1062) + ### C# -> VB diff --git a/CodeConverter/CSharp/MethodBodyExecutableStatementVisitor.cs b/CodeConverter/CSharp/MethodBodyExecutableStatementVisitor.cs index eef51dde..9e36972c 100644 --- a/CodeConverter/CSharp/MethodBodyExecutableStatementVisitor.cs +++ b/CodeConverter/CSharp/MethodBodyExecutableStatementVisitor.cs @@ -770,7 +770,9 @@ public override async Task> VisitSelectBlock(VBSynta // CSharp requires an explicit cast from the base type (e.g. int) in most cases switching on an enum var isBooleanCase = caseTypeInfo.Type?.SpecialType == SpecialType.System_Boolean; - var csExpressionToUse = IsEnumOrNullableEnum(switchExprTypeInfo.ConvertedType) ^ IsEnumOrNullableEnum(caseTypeInfo.Type) && !isBooleanCase ? correctTypeExpressionSyntax.Expr : originalExpressionSyntax; + bool enumRelated = IsEnumOrNullableEnum(switchExprTypeInfo.ConvertedType) || IsEnumOrNullableEnum(caseTypeInfo.Type); + bool convertingEnum = IsEnumOrNullableEnum(switchExprTypeInfo.ConvertedType) ^ IsEnumOrNullableEnum(caseTypeInfo.Type); + var csExpressionToUse = !isBooleanCase && (convertingEnum || !enumRelated && correctTypeExpressionSyntax.IsConst) ? correctTypeExpressionSyntax.Expr : originalExpressionSyntax; var caseSwitchLabelSyntax = !wrapForStringComparison && correctTypeExpressionSyntax.IsConst && notAlreadyUsed ? (SwitchLabelSyntax)SyntaxFactory.CaseSwitchLabel(csExpressionToUse) @@ -783,14 +785,19 @@ public override async Task> VisitSelectBlock(VBSynta var varName = CommonConversions.CsEscapedIdentifier(GetUniqueVariableNameInScope(node, "case")); ExpressionSyntax csLeft = ValidSyntaxFactory.IdentifierName(varName); var operatorKind = VBasic.VisualBasicExtensions.Kind(relational); - var relationalValue = await relational.Value.AcceptAsync(_expressionVisitor); - var binaryExp = SyntaxFactory.BinaryExpression(operatorKind.ConvertToken(), csLeft, relationalValue); + var csRelationalValue = await relational.Value.AcceptAsync(_expressionVisitor); + csRelationalValue = CommonConversions.TypeConversionAnalyzer.AddExplicitConversion(relational.Value, csRelationalValue); + var binaryExp = SyntaxFactory.BinaryExpression(operatorKind.ConvertToken(), csLeft, csRelationalValue); labels.Add(VarWhen(varName, binaryExp)); } else if (c is VBSyntax.RangeCaseClauseSyntax range) { var varName = CommonConversions.CsEscapedIdentifier(GetUniqueVariableNameInScope(node, "case")); ExpressionSyntax csLeft = ValidSyntaxFactory.IdentifierName(varName); - var lowerBoundCheck = SyntaxFactory.BinaryExpression(SyntaxKind.LessThanOrEqualExpression, await range.LowerBound.AcceptAsync(_expressionVisitor), csLeft); - var upperBoundCheck = SyntaxFactory.BinaryExpression(SyntaxKind.LessThanOrEqualExpression, csLeft, await range.UpperBound.AcceptAsync(_expressionVisitor)); + var lowerBound = await range.LowerBound.AcceptAsync(_expressionVisitor); + lowerBound = CommonConversions.TypeConversionAnalyzer.AddExplicitConversion(range.LowerBound, lowerBound); + var lowerBoundCheck = SyntaxFactory.BinaryExpression(SyntaxKind.LessThanOrEqualExpression, lowerBound, csLeft); + var upperBound = await range.UpperBound.AcceptAsync(_expressionVisitor); + upperBound = CommonConversions.TypeConversionAnalyzer.AddExplicitConversion(range.UpperBound, upperBound); + var upperBoundCheck = SyntaxFactory.BinaryExpression(SyntaxKind.LessThanOrEqualExpression, csLeft, upperBound); var withinBounds = SyntaxFactory.BinaryExpression(SyntaxKind.LogicalAndExpression, lowerBoundCheck, upperBoundCheck); labels.Add(VarWhen(varName, withinBounds)); } else { diff --git a/Tests/CSharp/TypeCastTests.cs b/Tests/CSharp/TypeCastTests.cs index fd19ce16..19b304e5 100644 --- a/Tests/CSharp/TypeCastTests.cs +++ b/Tests/CSharp/TypeCastTests.cs @@ -1360,6 +1360,42 @@ private string[] QuoteSplit(string text) }"); } + + [Fact] + public async Task TestSelectCaseComparesCharsAndStringsAsync() + { + await TestConversionVisualBasicToCSharpAsync( + @" +Class CharTestClass + Private Sub Q() + Select Case ""a"" + Case ""x""c To ""y""c + Case ""b""c + End Select + End Sub +End Class", @" +internal partial class CharTestClass +{ + private void Q() + { + switch (""a"") + { + case var @case when ""x"" <= @case && @case <= ""y"": + { + break; + } + + case ""b"": + { + break; + } + } + } +} +1 target compilation errors: +CS0825: The contextual keyword 'var' may only appear within a local variable declaration or in script code"); + } + [Fact] public async Task TestSingleCharacterStringLiteralBecomesChar_WhenExplictCastAsync() {