diff --git a/CodeConverter/CSharp/ExpressionNodeVisitor.cs b/CodeConverter/CSharp/ExpressionNodeVisitor.cs index c9026526c..d6a29023a 100644 --- a/CodeConverter/CSharp/ExpressionNodeVisitor.cs +++ b/CodeConverter/CSharp/ExpressionNodeVisitor.cs @@ -1904,10 +1904,10 @@ private ArgumentListSyntax CreateArgList(ISymbol invocationSymbol) private async Task SubstituteVisualBasicMethodOrNullAsync(VBSyntax.InvocationExpressionSyntax node, ISymbol symbol) { ExpressionSyntax cSharpSyntaxNode = null; - if (symbol?.ContainingNamespace.MetadataName == nameof(Microsoft.VisualBasic) && symbol.Name == "ChrW" || symbol?.Name == "Chr") { + if (IsVisualBasicChrMethod(symbol)) { var vbArg = node.ArgumentList.Arguments.Single().GetExpression(); var constValue = _semanticModel.GetConstantValue(vbArg); - if (IsCultureInvariant(symbol, constValue)) { + if (IsCultureInvariant(constValue)) { var csArg = await vbArg.AcceptAsync(TriviaConvertingExpressionVisitor); cSharpSyntaxNode = CommonConversions.TypeConversionAnalyzer.AddExplicitConversion(node, csArg, true, true, true, forceTargetType: _semanticModel.GetTypeInfo(node).Type); } @@ -1928,11 +1928,16 @@ private static bool RequiresStringCompareMethodToBeAppended(ISymbol symbol) => symbol.ContainingType.ContainingNamespace.ContainingNamespace.Name == nameof(Microsoft) && symbol.Name is "InStr" or "InStrRev" or "Replace" or "Split" or "StrComp"; + private static bool IsVisualBasicChrMethod(ISymbol symbol) => + symbol is not null + && symbol.ContainingNamespace.MetadataName == nameof(Microsoft.VisualBasic) + && (symbol.Name == "ChrW" || symbol.Name == "Chr"); + /// /// https://github.com/icsharpcode/CodeConverter/issues/745 /// - private static bool IsCultureInvariant(ISymbol symbol, Optional constValue) => - (symbol.Name == "ChrW" || symbol.Name == "Chr") && constValue.HasValue && Convert.ToUInt64(constValue.Value, CultureInfo.InvariantCulture) <= 127; + private static bool IsCultureInvariant(Optional constValue) => + constValue.HasValue && Convert.ToUInt64(constValue.Value, CultureInfo.InvariantCulture) <= 127; private CSharpSyntaxNode AddEmptyArgumentListIfImplicit(SyntaxNode node, ExpressionSyntax id) { diff --git a/Tests/CSharp/SpecialConversionTests.cs b/Tests/CSharp/SpecialConversionTests.cs index 436aa423f..d858bbc9d 100644 --- a/Tests/CSharp/SpecialConversionTests.cs +++ b/Tests/CSharp/SpecialConversionTests.cs @@ -277,6 +277,73 @@ public void Test(byte b) }"); } + [Fact] + public async Task TestNonVisualBasicChrMethodConversionsAsync() + { + await TestConversionVisualBasicToCSharpAsync(@" +Class TestConversions + Sub Test() + Dim a As String + a = Chr(2) + a = Me.Chr(2) + a = Strings.Chr(2) + a = Microsoft.VisualBasic.Strings.Chr(2) + a = Microsoft.VisualBasic.Chr(2) + End Sub + + Sub TestW() + Dim a As String + a = ChrW(2) + a = Me.ChrW(2) + a = Strings.ChrW(2) + a = Microsoft.VisualBasic.Strings.ChrW(2) + a = Microsoft.VisualBasic.ChrW(2) + End Sub + + Function Chr(o As Object) As Char + Return Microsoft.VisualBasic.Chr(o) + End Function + + Function ChrW(o As Object) As Char + Return Microsoft.VisualBasic.ChrW(o) + End Function +End Class", @"using Microsoft.VisualBasic; // Install-Package Microsoft.VisualBasic +using Microsoft.VisualBasic.CompilerServices; // Install-Package Microsoft.VisualBasic + +internal partial class TestConversions +{ + public void Test() + { + string a; + a = Conversions.ToString(Chr(2)); + a = Conversions.ToString(Chr(2)); + a = Conversions.ToString('\u0002'); + a = Conversions.ToString('\u0002'); + a = Conversions.ToString('\u0002'); + } + + public void TestW() + { + string a; + a = Conversions.ToString(ChrW(2)); + a = Conversions.ToString(ChrW(2)); + a = Conversions.ToString('\u0002'); + a = Conversions.ToString('\u0002'); + a = Conversions.ToString('\u0002'); + } + + public char Chr(object o) + { + return Strings.Chr(Conversions.ToInteger(o)); + } + + public char ChrW(object o) + { + return Strings.ChrW(Conversions.ToInteger(o)); + } +}"); + } + [Fact] public async Task UsingBoolInToExpressionAsync() {