Browse Source

[CodeIssue] CompareFloatWithEqualityOperatorIssue: fixed 'NaN' issue

newNRvisualizers
Mansheng Yang 13 years ago
parent
commit
384e0b608f
  1. 53
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/CompareFloatWithEqualityOperatorIssue.cs
  2. 12
      ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/CompareFloatWithEqualityOperatorIssueTests.cs

53
ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/CompareFloatWithEqualityOperatorIssue.cs

@ -60,27 +60,34 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
return IsFloatingPointType (ctx.Resolve (node).Type); return IsFloatingPointType (ctx.Resolve (node).Type);
} }
bool IsNaN (AstNode node) bool IsNaN (AstNode node, out string floatType)
{ {
var memberReferenceExpr = node as MemberReferenceExpression; floatType = "";
if (memberReferenceExpr == null) var rr = ctx.Resolve (node);
if (!rr.IsCompileTimeConstant)
return false; return false;
var typeReferenceExpr = memberReferenceExpr.Target as TypeReferenceExpression;
if (typeReferenceExpr == null) if (rr.ConstantValue is double && double.IsNaN ((double)rr.ConstantValue)) {
return false; floatType = "double";
return IsFloatingPointType (ctx.ResolveType (typeReferenceExpr.Type)) && return true;
memberReferenceExpr.MemberName == "NaN"; }
if (rr.ConstantValue is float && float.IsNaN ((float)rr.ConstantValue)) {
floatType = "float";
return true;
}
return false;
} }
void AddIsNaNIssue(BinaryOperatorExpression binaryOperatorExpr, Expression argExpr) void AddIsNaNIssue(BinaryOperatorExpression binaryOperatorExpr, Expression argExpr, string floatType)
{ {
AddIssue (binaryOperatorExpr, ctx.TranslateString ("Use double.IsNan()"), script => { AddIssue (binaryOperatorExpr, string.Format(ctx.TranslateString ("Use {0}.IsNan()"), floatType),
Expression expr = new InvocationExpression (new MemberReferenceExpression ( script => {
new TypeReferenceExpression (new PrimitiveType ("double")), "IsNaN"), argExpr.Clone ()); Expression expr = new InvocationExpression (new MemberReferenceExpression (
if (binaryOperatorExpr.Operator == BinaryOperatorType.InEquality) new TypeReferenceExpression (new PrimitiveType (floatType)), "IsNaN"), argExpr.Clone ());
expr = new UnaryOperatorExpression (UnaryOperatorType.Not, expr); if (binaryOperatorExpr.Operator == BinaryOperatorType.InEquality)
script.Replace (binaryOperatorExpr, expr); expr = new UnaryOperatorExpression (UnaryOperatorType.Not, expr);
}); script.Replace (binaryOperatorExpr, expr);
});
} }
public override void VisitBinaryOperatorExpression (BinaryOperatorExpression binaryOperatorExpression) public override void VisitBinaryOperatorExpression (BinaryOperatorExpression binaryOperatorExpression)
@ -91,20 +98,20 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
binaryOperatorExpression.Operator != BinaryOperatorType.InEquality) binaryOperatorExpression.Operator != BinaryOperatorType.InEquality)
return; return;
if (IsNaN(binaryOperatorExpression.Left)) { string floatType;
AddIsNaNIssue (binaryOperatorExpression, binaryOperatorExpression.Right); if (IsNaN(binaryOperatorExpression.Left, out floatType)) {
} else if (IsNaN (binaryOperatorExpression.Right)) { AddIsNaNIssue (binaryOperatorExpression, binaryOperatorExpression.Right, floatType);
AddIsNaNIssue (binaryOperatorExpression, binaryOperatorExpression.Left); } else if (IsNaN (binaryOperatorExpression.Right, out floatType)) {
AddIsNaNIssue (binaryOperatorExpression, binaryOperatorExpression.Left, floatType);
} else if (IsFloatingPoint(binaryOperatorExpression.Left) || IsFloatingPoint(binaryOperatorExpression.Right)) { } else if (IsFloatingPoint(binaryOperatorExpression.Left) || IsFloatingPoint(binaryOperatorExpression.Right)) {
AddIssue (binaryOperatorExpression, ctx.TranslateString ("Compare a difference with EPSILON"), AddIssue (binaryOperatorExpression, ctx.TranslateString ("Compare a difference with EPSILON"),
script => script => {
{
// Math.Abs(diff) op EPSILON // Math.Abs(diff) op EPSILON
var diff = new BinaryOperatorExpression (binaryOperatorExpression.Left.Clone (), var diff = new BinaryOperatorExpression (binaryOperatorExpression.Left.Clone (),
BinaryOperatorType.Subtract, binaryOperatorExpression.Right.Clone ()); BinaryOperatorType.Subtract, binaryOperatorExpression.Right.Clone ());
var abs = new InvocationExpression ( var abs = new InvocationExpression (
new MemberReferenceExpression ( new MemberReferenceExpression (
new TypeReferenceExpression (new SimpleType("System.Math")), new TypeReferenceExpression (new SimpleType ("System.Math")),
"Abs"), "Abs"),
diff); diff);
var op = binaryOperatorExpression.Operator == BinaryOperatorType.Equality ? var op = binaryOperatorExpression.Operator == BinaryOperatorType.Equality ?

12
ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/CompareFloatWithEqualityOperatorIssueTests.cs

@ -73,22 +73,26 @@ class TestClass
var input = @" var input = @"
class TestClass class TestClass
{ {
void TestMethod (double x) void TestMethod (double x, float y)
{ {
bool test = x == double.NaN; bool test = x == System.Double.NaN;
bool test2 = x != double.NaN; bool test2 = x != double.NaN;
bool test3 = y == float.NaN;
bool test4 = x != float.NaN
} }
}"; }";
var output = @" var output = @"
class TestClass class TestClass
{ {
void TestMethod (double x) void TestMethod (double x, float y)
{ {
bool test = double.IsNaN (x); bool test = double.IsNaN (x);
bool test2 = !double.IsNaN (x); bool test2 = !double.IsNaN (x);
bool test3 = float.IsNaN (y);
bool test4 = !double.IsNaN (x);
} }
}"; }";
Test<CompareFloatWithEqualityOperatorIssue> (input, 2, output); Test<CompareFloatWithEqualityOperatorIssue> (input, 3, output);
} }
} }
} }

Loading…
Cancel
Save