diff --git a/src/voku/PHPStan/Rules/IfConditionBooleanAndRule.php b/src/voku/PHPStan/Rules/IfConditionBooleanAndRule.php index 881df16..ff9b4d6 100644 --- a/src/voku/PHPStan/Rules/IfConditionBooleanAndRule.php +++ b/src/voku/PHPStan/Rules/IfConditionBooleanAndRule.php @@ -40,10 +40,12 @@ public function getNodeType(): string public function processNode(Node $node, Scope $scope): array { $cond = $node->getOriginalNode(); - $rightScope = $node->getRightScope(); - $errors = IfConditionHelper::processNode($cond->left, $scope, $this->classesNotInIfConditions); - $errors = array_merge($errors, IfConditionHelper::processNode($cond->right, $rightScope, $this->classesNotInIfConditions)); + $left = $scope->getType($cond->left); + $right = $scope->getType($cond->right); + $errors = []; + $errors = IfConditionHelper::processNodeHelper($left, $right, $node, $errors, $this->classesNotInIfConditions); + $errors = IfConditionHelper::processNodeHelper($right, $left, $node, $errors, $this->classesNotInIfConditions); return $errors; } diff --git a/src/voku/PHPStan/Rules/IfConditionBooleanNotRule.php b/src/voku/PHPStan/Rules/IfConditionBooleanNotRule.php index 2f0f749..8b2c492 100644 --- a/src/voku/PHPStan/Rules/IfConditionBooleanNotRule.php +++ b/src/voku/PHPStan/Rules/IfConditionBooleanNotRule.php @@ -41,6 +41,6 @@ public function processNode(Node $node, Scope $scope): array { $cond = $node->expr; - return IfConditionHelper::processNode($cond, $scope, $this->classesNotInIfConditions); + return IfConditionHelper::processNodeHelper($scope->getType($cond), null, $node, [], $this->classesNotInIfConditions); } } diff --git a/src/voku/PHPStan/Rules/IfConditionBooleanOrRule.php b/src/voku/PHPStan/Rules/IfConditionBooleanOrRule.php index 8952e5e..acaa402 100644 --- a/src/voku/PHPStan/Rules/IfConditionBooleanOrRule.php +++ b/src/voku/PHPStan/Rules/IfConditionBooleanOrRule.php @@ -40,10 +40,12 @@ public function getNodeType(): string public function processNode(Node $node, Scope $scope): array { $cond = $node->getOriginalNode(); - $rightScope = $node->getRightScope(); - $errors = IfConditionHelper::processNode($cond->left, $scope, $this->classesNotInIfConditions); - $errors = array_merge($errors, IfConditionHelper::processNode($cond->right, $rightScope, $this->classesNotInIfConditions)); + $left = $scope->getType($cond->left); + $right = $scope->getType($cond->right); + $errors = []; + $errors = IfConditionHelper::processNodeHelper($left, $right, $node, $errors, $this->classesNotInIfConditions); + $errors = IfConditionHelper::processNodeHelper($right, $left, $node, $errors, $this->classesNotInIfConditions); return $errors; } diff --git a/src/voku/PHPStan/Rules/IfConditionHelper.php b/src/voku/PHPStan/Rules/IfConditionHelper.php index 59cfa0a..b05b0b6 100644 --- a/src/voku/PHPStan/Rules/IfConditionHelper.php +++ b/src/voku/PHPStan/Rules/IfConditionHelper.php @@ -9,66 +9,14 @@ final class IfConditionHelper { - - /** - * @param \PhpParser\Node\Expr $cond - * @param array $classesNotInIfConditions - * - * @return array - */ - public static function processNode( - Node $cond, - Scope $scope, - array $classesNotInIfConditions - ): array - { - // init - $errors = []; - - // ignore mixed types - $condType = $scope->getType($cond); - if ($condType instanceof \PHPStan\Type\MixedType) { - return []; - } - - if ( - !property_exists($cond, 'left') - && - !property_exists($cond, 'right') - ) { - $errors = self::prcessNodeHelper($condType, null, $cond, $errors, $classesNotInIfConditions); - - return $errors; - } - - if (property_exists($cond, 'left')) { - $leftType = $scope->getType($cond->left); - } else { - $leftType = null; - } - - if (property_exists($cond, 'right')) { - $rightType = $scope->getType($cond->right); - } else { - $rightType = null; - } - - // left <-> right - $errors = self::prcessNodeHelper($leftType, $rightType, $cond, $errors, $classesNotInIfConditions); - // right <-> left - $errors = self::prcessNodeHelper($rightType, $leftType, $cond, $errors, $classesNotInIfConditions); - - return $errors; - } - /** - * @param \PhpParser\Node\Expr $cond + * @param \PhpParser\Node $cond * @param array $errors * @param array $classesNotInIfConditions * * @return array */ - private static function prcessNodeHelper( + public static function processNodeHelper( ?\PHPStan\Type\Type $type_1, ?\PHPStan\Type\Type $type_2, Node $cond, diff --git a/src/voku/PHPStan/Rules/IfConditionRule.php b/src/voku/PHPStan/Rules/IfConditionRule.php index a654153..eb8ee97 100644 --- a/src/voku/PHPStan/Rules/IfConditionRule.php +++ b/src/voku/PHPStan/Rules/IfConditionRule.php @@ -9,7 +9,7 @@ use PHPStan\Rules\Rule; /** - * @implements Rule<\PhpParser\Node\Stmt> + * @implements Rule<\PhpParser\Node\Expr\BinaryOp> */ final class IfConditionRule implements Rule { @@ -29,22 +29,23 @@ public function __construct(array $classesNotInIfConditions = []) public function getNodeType(): string { - return \PhpParser\Node\Stmt::class; + return \PhpParser\Node\Expr\BinaryOp::class; } /** - * @param \PhpParser\Node\Stmt $node + * @param \PhpParser\Node\Expr\BinaryOp $node * * @return array */ public function processNode(Node $node, Scope $scope): array { - if (!($node instanceof \PhpParser\Node\Stmt\If_) && !($node instanceof \PhpParser\Node\Stmt\ElseIf_)) { - return []; - } + $leftType = $scope->getType($node->left); + $rightType = $scope->getType($node->right); - $cond = $node->cond; + $errors = []; + $errors = IfConditionHelper::processNodeHelper($leftType, $rightType, $node, $errors, $this->classesNotInIfConditions); + $errors = IfConditionHelper::processNodeHelper($rightType, $leftType, $node, $errors, $this->classesNotInIfConditions); - return IfConditionHelper::processNode($cond, $scope, $this->classesNotInIfConditions); + return $errors; } } diff --git a/src/voku/PHPStan/Rules/IfConditionTernaryOperatorRule.php b/src/voku/PHPStan/Rules/IfConditionTernaryOperatorRule.php index e4c9840..d7a2d39 100644 --- a/src/voku/PHPStan/Rules/IfConditionTernaryOperatorRule.php +++ b/src/voku/PHPStan/Rules/IfConditionTernaryOperatorRule.php @@ -43,8 +43,6 @@ public function processNode(Node $node, Scope $scope): array return []; // elvis ?: } - $cond = $node->cond; - - return IfConditionHelper::processNode($cond, $scope, $this->classesNotInIfConditions); + return IfConditionHelper::processNodeHelper($scope->getType($node->cond), null, $node, [], $this->classesNotInIfConditions); } } diff --git a/tests/IfConditionBooleanAndRuleTest.php b/tests/IfConditionBooleanAndRuleTest.php index 37e875a..6318058 100644 --- a/tests/IfConditionBooleanAndRuleTest.php +++ b/tests/IfConditionBooleanAndRuleTest.php @@ -29,6 +29,10 @@ public function testIfConditions(): void 'Use a method to check the condition e.g. `$foo->value()` instead of `$foo`.', 8, ], + [ + 'Do not compare objects directly.', + 8, + ], ] ); } diff --git a/tests/IfConditionRuleTest.php b/tests/IfConditionRuleTest.php index 6af949c..cf5a02c 100644 --- a/tests/IfConditionRuleTest.php +++ b/tests/IfConditionRuleTest.php @@ -81,6 +81,10 @@ public function testIfConditions(): void 'Do not compare objects directly.', 55 ], + [ + 'Do not compare objects directly.', + 72 + ], ] ); } diff --git a/tests/fixtures/IfConditionsFixtures.php b/tests/fixtures/IfConditionsFixtures.php index 0494e70..0d53652 100644 --- a/tests/fixtures/IfConditionsFixtures.php +++ b/tests/fixtures/IfConditionsFixtures.php @@ -66,3 +66,8 @@ public function foo(self $bar) } } } + +// Intercept binary op wherever they are +$var = function(): bool { + return '2032-03-04' <= new \DateTimeImmutable(); +};