diff --git a/src/Rules/Operators/OperandsInComparisonRule.php b/src/Rules/Operators/OperandsInComparisonRule.php new file mode 100644 index 00000000..268fb17f --- /dev/null +++ b/src/Rules/Operators/OperandsInComparisonRule.php @@ -0,0 +1,70 @@ +getType($node->right); + $leftType = $scope->getType($node->left); + + if ($rightType instanceof FloatType || $leftType instanceof FloatType) { + if ($node instanceof BinaryOp\Equal || $node instanceof BinaryOp\Identical) { + return [ + 'Exact comparison of floating-point numbers is not accurate.' . PHP_EOL + . 'You should use `abs($left - $right) < $epsilon`, where $epsilon is maximum allowed deviation.', + ]; + } + + if ($node instanceof BinaryOp\NotEqual || $node instanceof BinaryOp\NotIdentical) { + return [ + 'Exact comparison of floating-point numbers is not accurate.' . PHP_EOL + . 'You should use `abs($left - $right) >= $epsilon`, where $epsilon is maximum allowed deviation.', + ]; + } + + if ($node instanceof BinaryOp\GreaterOrEqual) { + return [ + 'Exact comparison of floating-point numbers is not accurate.' . PHP_EOL + . 'You should use `$left - $right >= $epsilon`, where $epsilon is maximum allowed deviation.', + ]; + } + + return [ + 'Exact comparison of floating-point numbers is not accurate.' . PHP_EOL + . 'You should use `$right - $left >= $epsilon`, where $epsilon is maximum allowed deviation.', + ]; + } + + return []; + } + +} diff --git a/tests/Rules/Operators/OperandsInComparisonRuleTest.php b/tests/Rules/Operators/OperandsInComparisonRuleTest.php new file mode 100644 index 00000000..b96a4c1f --- /dev/null +++ b/tests/Rules/Operators/OperandsInComparisonRuleTest.php @@ -0,0 +1,51 @@ +analyse([__DIR__ . '/data/operators.php'], [ + [ + 'Exact comparison of floating-point numbers is not accurate.' . PHP_EOL + . 'You should use `abs($left - $right) < $epsilon`, where $epsilon is maximum allowed deviation.', + 113, + ], + [ + 'Exact comparison of floating-point numbers is not accurate.' . PHP_EOL + . 'You should use `abs($left - $right) < $epsilon`, where $epsilon is maximum allowed deviation.', + 114, + ], + [ + 'Exact comparison of floating-point numbers is not accurate.' . PHP_EOL + . 'You should use `abs($left - $right) >= $epsilon`, where $epsilon is maximum allowed deviation.', + 115, + ], + [ + 'Exact comparison of floating-point numbers is not accurate.' . PHP_EOL + . 'You should use `abs($left - $right) >= $epsilon`, where $epsilon is maximum allowed deviation.', + 116, + ], + [ + 'Exact comparison of floating-point numbers is not accurate.' . PHP_EOL + . 'You should use `$left - $right >= $epsilon`, where $epsilon is maximum allowed deviation.', + 117, + ], + [ + 'Exact comparison of floating-point numbers is not accurate.' . PHP_EOL + . 'You should use `$right - $left >= $epsilon`, where $epsilon is maximum allowed deviation.', + 118, + ], + ]); + } + +} diff --git a/tests/Rules/Operators/data/operators.php b/tests/Rules/Operators/data/operators.php index 4a4bf9e2..54c98013 100644 --- a/tests/Rules/Operators/data/operators.php +++ b/tests/Rules/Operators/data/operators.php @@ -109,3 +109,10 @@ function (array $array, int $int, $mixed) { explode($mixed, $mixed) + $int; }; + +$float === 123.2; +$float == 123.2; +$float !== 123.2; +$float != 123.2; +$float >= 123.2; +$float <= 123.2;