From bcdb0d1793530389d27a4fe7fa907b7de835a25a Mon Sep 17 00:00:00 2001 From: Timur Kelman Date: Thu, 18 Jul 2024 17:32:50 +0200 Subject: [PATCH 1/2] generate `unchecked((int)0x91234567)` instead of `int.MinValue + 0x11234567` --- CodeConverter/CSharp/LiteralConversions.cs | 18 ++++++++---------- CodeConverter/Common/DocumentExtensions.cs | 4 +++- Tests/CSharp/SpecialConversionTests.cs | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/CodeConverter/CSharp/LiteralConversions.cs b/CodeConverter/CSharp/LiteralConversions.cs index 30da594c3..41c9b9406 100644 --- a/CodeConverter/CSharp/LiteralConversions.cs +++ b/CodeConverter/CSharp/LiteralConversions.cs @@ -152,18 +152,16 @@ private static (string textForUser, ExpressionSyntax MaybeFullExpression) Conver int parsedHexValue = int.Parse(hexValue, NumberStyles.HexNumber, CultureInfo.InvariantCulture); // This is a very special case where for 8 digit hex strings, C# interprets them as unsigned ints, but VB interprets them as ints - // This can lead to a compile error if assigned to an int in VB. So in a case like 0x91234567, we generate `int.MinValue + 0x11234567` + // This can lead to a compile error if assigned to an int in VB. So in a case like 0x91234567, we generate `unchecked((int)0x91234567)` // This way the value looks pretty close to before and remains a compile time constant if (parsedHexValue < 0) { - int positiveValue = parsedHexValue - int.MinValue; - - var intMinValueExpr = SyntaxFactory.MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - SyntaxFactory.PredefinedType( - SyntaxFactory.Token(SyntaxKind.IntKeyword)), - ValidSyntaxFactory.IdentifierName(nameof(int.MinValue))); - var positiveValueExpr = NumericLiteral(SyntaxFactory.Literal("0x" + positiveValue.ToString("X8", CultureInfo.InvariantCulture), positiveValue)); - return (null, SyntaxFactory.BinaryExpression(SyntaxKind.AddExpression, intMinValueExpr, positiveValueExpr)); + var hexValueExpr = NumericLiteral(SyntaxFactory.Literal(textForUser, parsedHexValue)); + var checkedExpr = SyntaxFactory.CheckedExpression( + CSSyntaxKind.UncheckedExpression, + SyntaxFactory.CastExpression( + SyntaxFactory.PredefinedType(SyntaxFactory.Token(CSSyntaxKind.IntKeyword)), + hexValueExpr)); + return (null, checkedExpr); } } else if (canBeBinaryOrHex && textForUser.StartsWith("&B", StringComparison.OrdinalIgnoreCase)) { textForUser = "0b" + textForUser.Substring(2); diff --git a/CodeConverter/Common/DocumentExtensions.cs b/CodeConverter/Common/DocumentExtensions.cs index 5cf2d89da..1b3db1a65 100644 --- a/CodeConverter/Common/DocumentExtensions.cs +++ b/CodeConverter/Common/DocumentExtensions.cs @@ -50,7 +50,9 @@ private static bool VbWouldBeSimplifiedIncorrectly(SyntaxNode n) private static bool CsWouldBeSimplifiedIncorrectly(SyntaxNode n) { - return false; + //"private int value = unchecked((int)0x80000010);" is simplified to "private int value = unchecked(0x80000010);" + // which causes CS0266: "Cannot implicitly convert type 'uint' to 'int'" + return (n is CSSyntax.CastExpressionSyntax && n.Parent is CSSyntax.CheckedExpressionSyntax); } public static async Task WithExpandedRootAsync(this Document document, CancellationToken cancellationToken) diff --git a/Tests/CSharp/SpecialConversionTests.cs b/Tests/CSharp/SpecialConversionTests.cs index 95b4bbe06..b07f5025d 100644 --- a/Tests/CSharp/SpecialConversionTests.cs +++ b/Tests/CSharp/SpecialConversionTests.cs @@ -154,8 +154,8 @@ await TestConversionVisualBasicToCSharpAsync( End Class", @" internal partial class Test754 { - private int value = int.MinValue + 0x00000000; - private int value2 = int.MinValue + 0x71234567; + private int value = unchecked((int)0x80000000); + private int value2 = unchecked((int)0xF1234567); }"); } From bec2a491fd800c0f3128c9271d22df7c94141c7d Mon Sep 17 00:00:00 2001 From: Timur Kelman Date: Thu, 18 Jul 2024 17:44:06 +0200 Subject: [PATCH 2/2] use slightly more compact syntax --- CodeConverter/Common/DocumentExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CodeConverter/Common/DocumentExtensions.cs b/CodeConverter/Common/DocumentExtensions.cs index 1b3db1a65..b0e0d9de1 100644 --- a/CodeConverter/Common/DocumentExtensions.cs +++ b/CodeConverter/Common/DocumentExtensions.cs @@ -52,7 +52,7 @@ private static bool CsWouldBeSimplifiedIncorrectly(SyntaxNode n) { //"private int value = unchecked((int)0x80000010);" is simplified to "private int value = unchecked(0x80000010);" // which causes CS0266: "Cannot implicitly convert type 'uint' to 'int'" - return (n is CSSyntax.CastExpressionSyntax && n.Parent is CSSyntax.CheckedExpressionSyntax); + return (n is CSSyntax.CastExpressionSyntax { Parent : CSSyntax.CheckedExpressionSyntax }); } public static async Task WithExpandedRootAsync(this Document document, CancellationToken cancellationToken)