From 105bbb6cecf7be07fe02561b01b79cfadd3bf26d Mon Sep 17 00:00:00 2001 From: webard Date: Wed, 29 Jul 2026 08:47:24 +0200 Subject: [PATCH 1/2] guard boolean-simplification rules against non-boolean subjects --- src/Rules/SimplifyExpectNotRector.php | 4 ++++ src/Rules/ToBeTrueNotFalseRector.php | 3 ++- .../Fixture/simplify_expect_not.php.inc | 6 ++++++ .../Fixture/skip_non_bool_type.php.inc | 8 ++++++++ .../Fixture/skip_union_string_false.php.inc | 7 +++++++ 5 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 tests/Rules/SimplifyExpectNotRector/Fixture/skip_non_bool_type.php.inc create mode 100644 tests/Rules/ToBeTrueNotFalseRector/Fixture/skip_union_string_false.php.inc diff --git a/src/Rules/SimplifyExpectNotRector.php b/src/Rules/SimplifyExpectNotRector.php index bfb441d..e935493 100644 --- a/src/Rules/SimplifyExpectNotRector.php +++ b/src/Rules/SimplifyExpectNotRector.php @@ -100,6 +100,10 @@ public function refactor(Node $node): ?Node } if (isset(self::FLIPPABLE_MATCHERS[$finalMethodName])) { + if (! $this->getType($arg->value->expr)->isBoolean()->yes()) { + return null; + } + $expectCall->args[0] = $this->nodeFactory->createArg($arg->value->expr); $this->flipFinalMatcher($node, self::FLIPPABLE_MATCHERS[$finalMethodName]); diff --git a/src/Rules/ToBeTrueNotFalseRector.php b/src/Rules/ToBeTrueNotFalseRector.php index d19ea43..2ec8936 100644 --- a/src/Rules/ToBeTrueNotFalseRector.php +++ b/src/Rules/ToBeTrueNotFalseRector.php @@ -81,7 +81,8 @@ public function refactor(Node $node): ?Node return null; } - if ($this->getType($expectArgument)->isBoolean()->no()) { + // ->no() misses T|false unions, `false` is a bool + if (! $this->getType($expectArgument)->isBoolean()->yes()) { return null; } diff --git a/tests/Rules/SimplifyExpectNotRector/Fixture/simplify_expect_not.php.inc b/tests/Rules/SimplifyExpectNotRector/Fixture/simplify_expect_not.php.inc index 3178e6c..693dea0 100644 --- a/tests/Rules/SimplifyExpectNotRector/Fixture/simplify_expect_not.php.inc +++ b/tests/Rules/SimplifyExpectNotRector/Fixture/simplify_expect_not.php.inc @@ -1,5 +1,8 @@ toBeTrue(); expect(!$value)->toBeFalse(); expect(!empty($array))->toBeTrue(); @@ -9,6 +12,9 @@ expect(!is_null($variable))->toBeTrue(); ----- toBeFalse(); expect($value)->toBeTrue(); expect(empty($array))->toBeFalse(); diff --git a/tests/Rules/SimplifyExpectNotRector/Fixture/skip_non_bool_type.php.inc b/tests/Rules/SimplifyExpectNotRector/Fixture/skip_non_bool_type.php.inc new file mode 100644 index 0000000..fa1885c --- /dev/null +++ b/tests/Rules/SimplifyExpectNotRector/Fixture/skip_non_bool_type.php.inc @@ -0,0 +1,8 @@ +toBeTrue(); +expect(!mb_strstr($haystack, 'needle'))->toBeTrue(); + +?> diff --git a/tests/Rules/ToBeTrueNotFalseRector/Fixture/skip_union_string_false.php.inc b/tests/Rules/ToBeTrueNotFalseRector/Fixture/skip_union_string_false.php.inc new file mode 100644 index 0000000..f46a489 --- /dev/null +++ b/tests/Rules/ToBeTrueNotFalseRector/Fixture/skip_union_string_false.php.inc @@ -0,0 +1,7 @@ +not->toBeFalse(); +}); + +?> From 4978647402bc2860cee8492cfcd7ae50f4ad36f9 Mon Sep 17 00:00:00 2001 From: webard Date: Wed, 29 Jul 2026 13:15:15 +0200 Subject: [PATCH 2/2] ci --- src/Rules/ToBeTrueNotFalseRector.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Rules/ToBeTrueNotFalseRector.php b/src/Rules/ToBeTrueNotFalseRector.php index 2ec8936..9fb53a7 100644 --- a/src/Rules/ToBeTrueNotFalseRector.php +++ b/src/Rules/ToBeTrueNotFalseRector.php @@ -81,7 +81,6 @@ public function refactor(Node $node): ?Node return null; } - // ->no() misses T|false unions, `false` is a bool if (! $this->getType($expectArgument)->isBoolean()->yes()) { return null; }