Merge pull request #42 from icsharpcode/avoid-loss-of-precision
Avoid loss of precision after conversion using "/" or integer doubles
This commit is contained in:
Коммит
4f6bcb3ff7
|
@ -782,13 +782,13 @@ namespace ICSharpCode.CodeConverter.CSharp
|
|||
if (node.Token.Value == null) {
|
||||
var type = semanticModel.GetTypeInfo(node).ConvertedType;
|
||||
if (type == null) {
|
||||
return Literal(null)
|
||||
return Literal("null", null)
|
||||
.WithTrailingTrivia(
|
||||
SyntaxFactory.Comment("/* TODO Change to default(_) if this is not a reference type */"));
|
||||
}
|
||||
return !type.IsReferenceType ? SyntaxFactory.DefaultExpression(SyntaxFactory.ParseTypeName(type.ToMinimalDisplayString(semanticModel, node.SpanStart))) : Literal(null);
|
||||
return !type.IsReferenceType ? SyntaxFactory.DefaultExpression(SyntaxFactory.ParseTypeName(type.ToMinimalDisplayString(semanticModel, node.SpanStart))) : Literal("null", null);
|
||||
}
|
||||
return Literal(node.Token.Value);
|
||||
return Literal(node.Token.Text, node.Token.Value);
|
||||
}
|
||||
|
||||
public override CSharpSyntaxNode VisitInterpolatedStringExpression(VBSyntax.InterpolatedStringExpressionSyntax node)
|
||||
|
@ -1230,13 +1230,30 @@ namespace ICSharpCode.CodeConverter.CSharp
|
|||
return SyntaxFactory.BinaryExpression(SyntaxKind.NotEqualsExpression, otherArgument, SyntaxFactory.LiteralExpression(SyntaxKind.NullLiteralExpression));
|
||||
}
|
||||
}
|
||||
|
||||
var kind = ConvertToken(VBasic.VisualBasicExtensions.Kind(node), TokenContext.Local);
|
||||
return SyntaxFactory.BinaryExpression(
|
||||
kind,
|
||||
(ExpressionSyntax)node.Left.Accept(TriviaConvertingVisitor),
|
||||
SyntaxFactory.Token(CSharpUtil.GetExpressionOperatorTokenKind(kind)),
|
||||
(ExpressionSyntax)node.Right.Accept(TriviaConvertingVisitor)
|
||||
);
|
||||
var lhs = (ExpressionSyntax)node.Left.Accept(TriviaConvertingVisitor);
|
||||
var op = SyntaxFactory.Token(CSharpUtil.GetExpressionOperatorTokenKind(kind));
|
||||
var rhs = (ExpressionSyntax)node.Right.Accept(TriviaConvertingVisitor);
|
||||
|
||||
// VB DivideExpression "/" is always on doubles unless you use the "\" IntegerDivideExpression, so need to cast in C#
|
||||
// Need the unconverted type, since the whole point is that it gets converted to a double by the operator
|
||||
if (node.IsKind(VBasic.SyntaxKind.DivideExpression) && !HasOperandOfUnconvertedType(node, "System.Double")) {
|
||||
var doubleType = SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.DoubleKeyword));
|
||||
rhs = SyntaxFactory.CastExpression(doubleType, rhs);
|
||||
}
|
||||
|
||||
return SyntaxFactory.BinaryExpression(kind, lhs, op, rhs);
|
||||
}
|
||||
|
||||
private bool HasOperandOfUnconvertedType(VBSyntax.BinaryExpressionSyntax node, string operandType)
|
||||
{
|
||||
return new[] {node.Left, node.Right}.Any(e => UnconvertedIsType(e, operandType));
|
||||
}
|
||||
|
||||
private bool UnconvertedIsType(VBSyntax.ExpressionSyntax e, string fullTypeName)
|
||||
{
|
||||
return semanticModel.GetTypeInfo(e).Type?.GetFullMetadataName() == fullTypeName;
|
||||
}
|
||||
|
||||
public override CSharpSyntaxNode VisitInvocationExpression(VBSyntax.InvocationExpressionSyntax node)
|
||||
|
|
|
@ -80,9 +80,9 @@ namespace ICSharpCode.CodeConverter.CSharp
|
|||
return newDecls;
|
||||
}
|
||||
|
||||
static ExpressionSyntax Literal(object o) => GetLiteralExpression(o);
|
||||
static ExpressionSyntax Literal(string valueText, object o) => GetLiteralExpression(valueText, o);
|
||||
|
||||
internal static ExpressionSyntax GetLiteralExpression(object value)
|
||||
internal static ExpressionSyntax GetLiteralExpression(string valueText, object value)
|
||||
{
|
||||
if (value is bool)
|
||||
return SyntaxFactory.LiteralExpression((bool)value ? SyntaxKind.TrueLiteralExpression : SyntaxKind.FalseLiteralExpression);
|
||||
|
@ -105,10 +105,14 @@ namespace ICSharpCode.CodeConverter.CSharp
|
|||
|
||||
if (value is float)
|
||||
return SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal((float)value));
|
||||
if (value is double)
|
||||
return SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal((double)value));
|
||||
if (value is decimal)
|
||||
if (value is double) {
|
||||
// Important to use value text, otherwise "10.0" gets coerced to and integer literal of 10 which can change semantics
|
||||
return SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(valueText, (double)value));
|
||||
}
|
||||
if (value is decimal) {
|
||||
// Don't use value text - it has a "D" in VB, but an "M" in C#
|
||||
return SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal((decimal)value));
|
||||
}
|
||||
|
||||
if (value is char)
|
||||
return SyntaxFactory.LiteralExpression(SyntaxKind.CharacterLiteralExpression, SyntaxFactory.Literal((char)value));
|
||||
|
|
|
@ -104,6 +104,28 @@ End Class", @"class TestClass
|
|||
}");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FloatingPointDivisionIsForced()
|
||||
{
|
||||
TestConversionVisualBasicToCSharp(@"Class TestClass
|
||||
Private Sub TestMethod()
|
||||
Dim x = 10 / 3
|
||||
x /= 2
|
||||
Dim y = 10.0 / 3
|
||||
y /= 2
|
||||
End Sub
|
||||
End Class", @"class TestClass
|
||||
{
|
||||
private void TestMethod()
|
||||
{
|
||||
var x = 10 / (double)3;
|
||||
x /= 2;
|
||||
var y = 10.0 / 3;
|
||||
y /= 2;
|
||||
}
|
||||
}");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FullyTypeInferredEnumerableCreation()
|
||||
{
|
||||
|
@ -482,7 +504,7 @@ class TestClass
|
|||
var test2 = (a, b) =>
|
||||
{
|
||||
if (b > 0)
|
||||
return a / b;
|
||||
return a / (double)b;
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче