From a52676b86bdc4286a572b789f02c4aafecd9594f Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sat, 4 Oct 2025 06:17:46 +0700 Subject: [PATCH 1/7] [CodeQuality] Skip equal to identical on numeric string on UseIdenticalOverEqualWithSameTypeRector --- .../Fixture/skip_equal_numeric_string.php.inc | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 rules-tests/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector/Fixture/skip_equal_numeric_string.php.inc diff --git a/rules-tests/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector/Fixture/skip_equal_numeric_string.php.inc b/rules-tests/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector/Fixture/skip_equal_numeric_string.php.inc new file mode 100644 index 00000000000..f84740aa4f7 --- /dev/null +++ b/rules-tests/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector/Fixture/skip_equal_numeric_string.php.inc @@ -0,0 +1,20 @@ +getValue() == '1') { + return 'yes'; + } + + return 'no'; + } + + private function getValue(): string + { + return '1'; + } +} From 302d60f2436f769b1d2a35c5d39db88e50e869e6 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sat, 4 Oct 2025 06:26:42 +0700 Subject: [PATCH 2/7] fix --- .../Fixture/skip_equal_numeric_string.php.inc | 4 ++++ .../UseIdenticalOverEqualWithSameTypeRector.php | 14 ++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/rules-tests/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector/Fixture/skip_equal_numeric_string.php.inc b/rules-tests/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector/Fixture/skip_equal_numeric_string.php.inc index f84740aa4f7..c0fec0a8b22 100644 --- a/rules-tests/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector/Fixture/skip_equal_numeric_string.php.inc +++ b/rules-tests/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector/Fixture/skip_equal_numeric_string.php.inc @@ -10,6 +10,10 @@ final class SkipIdenticalNumericString return 'yes'; } + if ('1' == $this->getValue()) { + return 'yes 2'; + } + return 'no'; } diff --git a/rules/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector.php b/rules/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector.php index e50d6a8f5b8..c031b53bfed 100644 --- a/rules/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector.php +++ b/rules/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector.php @@ -12,6 +12,7 @@ use PhpParser\Node\Expr\BinaryOp\NotIdentical; use PHPStan\Type\BooleanType; use PHPStan\Type\MixedType; +use PHPStan\Type\Type; use Rector\Rector\AbstractRector; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; @@ -73,6 +74,10 @@ public function refactor(Node $node): ?Node $leftStaticType = $this->nodeTypeResolver->getNativeType($node->left); $rightStaticType = $this->nodeTypeResolver->getNativeType($node->right); + if ($this->shouldSkipCompareNumericString($leftStaticType, $rightStaticType)) { + return null; + } + // objects can be different by content if (! $leftStaticType->isObject()->no() || ! $rightStaticType->isObject()->no()) { return null; @@ -96,6 +101,15 @@ public function refactor(Node $node): ?Node return $this->processIdenticalOrNotIdentical($node); } + private function shouldSkipCompareNumericString(Type $leftStaticType, Type $rightStaticType): bool + { + if ($leftStaticType->isString()->yes() && $rightStaticType->isNumericString()->yes()) { + return true; + } + + return $rightStaticType->isString()->yes() && $leftStaticType->isNumericString()->yes(); + } + private function processIdenticalOrNotIdentical(Equal|NotEqual $node): Identical|NotIdentical { if ($node instanceof Equal) { From c8cb5af5c08586add33b7898c2ace244bd21251e Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sat, 4 Oct 2025 06:28:35 +0700 Subject: [PATCH 3/7] fix --- .../Fixture/skip_equal_numeric_string.php.inc | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/rules-tests/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector/Fixture/skip_equal_numeric_string.php.inc b/rules-tests/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector/Fixture/skip_equal_numeric_string.php.inc index c0fec0a8b22..bb1899b1bf4 100644 --- a/rules-tests/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector/Fixture/skip_equal_numeric_string.php.inc +++ b/rules-tests/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector/Fixture/skip_equal_numeric_string.php.inc @@ -6,19 +6,8 @@ final class SkipIdenticalNumericString { public function equal() { - if ($this->getValue() == '1') { - return 'yes'; - } - - if ('1' == $this->getValue()) { - return 'yes 2'; - } - - return 'no'; - } - - private function getValue(): string - { - return '1'; + $a = 1; + var_dump($a == '1'); + var_dump($a === '1'); } } From 1b73656357e1833e23f532accfd75990609217aa Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sat, 4 Oct 2025 06:28:51 +0700 Subject: [PATCH 4/7] fix --- .../Fixture/skip_equal_numeric_string.php.inc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rules-tests/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector/Fixture/skip_equal_numeric_string.php.inc b/rules-tests/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector/Fixture/skip_equal_numeric_string.php.inc index bb1899b1bf4..ec750bab5ce 100644 --- a/rules-tests/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector/Fixture/skip_equal_numeric_string.php.inc +++ b/rules-tests/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector/Fixture/skip_equal_numeric_string.php.inc @@ -7,7 +7,7 @@ final class SkipIdenticalNumericString public function equal() { $a = 1; - var_dump($a == '1'); - var_dump($a === '1'); + var_dump($a == '1'); // true + var_dump($a === '1'); // false } } From 7bf2b9fc7f7e6eb22d703d936af48b2a6db4f0e5 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sat, 4 Oct 2025 06:31:59 +0700 Subject: [PATCH 5/7] udpdate fixture --- .../Fixture/skip_equal_numeric_string.php.inc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/rules-tests/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector/Fixture/skip_equal_numeric_string.php.inc b/rules-tests/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector/Fixture/skip_equal_numeric_string.php.inc index ec750bab5ce..c0bda6280fb 100644 --- a/rules-tests/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector/Fixture/skip_equal_numeric_string.php.inc +++ b/rules-tests/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector/Fixture/skip_equal_numeric_string.php.inc @@ -6,8 +6,7 @@ final class SkipIdenticalNumericString { public function equal() { - $a = 1; - var_dump($a == '1'); // true - var_dump($a === '1'); // false + var_dump(true == '1'); // true + var_dump(true === '1'); // false } } From 5a87299ef5b4667e522a3786272bd7e02bc4c0a5 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sat, 4 Oct 2025 06:34:46 +0700 Subject: [PATCH 6/7] fix --- .../Fixture/skip_equal_numeric_string.php.inc | 9 ++++++--- .../Equal/UseIdenticalOverEqualWithSameTypeRector.php | 10 +++++++--- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/rules-tests/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector/Fixture/skip_equal_numeric_string.php.inc b/rules-tests/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector/Fixture/skip_equal_numeric_string.php.inc index c0bda6280fb..17b968a9533 100644 --- a/rules-tests/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector/Fixture/skip_equal_numeric_string.php.inc +++ b/rules-tests/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector/Fixture/skip_equal_numeric_string.php.inc @@ -2,11 +2,14 @@ namespace Rector\Tests\CodeQuality\Rector\Equal\UseIdenticalOverEqualWithSameTypeRector\Fixture; -final class SkipIdenticalNumericString +/** + * @see https://3v4l.org/9XRF6 + */ +final class SkipIdenticalNumericStringCompareBool { public function equal() { - var_dump(true == '1'); // true - var_dump(true === '1'); // false + var_dump(true == '1'); + var_dump('1' == true); } } diff --git a/rules/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector.php b/rules/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector.php index c031b53bfed..5d21edd3006 100644 --- a/rules/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector.php +++ b/rules/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector.php @@ -103,11 +103,15 @@ public function refactor(Node $node): ?Node private function shouldSkipCompareNumericString(Type $leftStaticType, Type $rightStaticType): bool { - if ($leftStaticType->isString()->yes() && $rightStaticType->isNumericString()->yes()) { - return true; + if ($leftStaticType instanceof BooleanType) { + return $rightStaticType->isNumericString()->yes(); } - return $rightStaticType->isString()->yes() && $leftStaticType->isNumericString()->yes(); + if ($rightStaticType instanceof BooleanType) { + return $leftStaticType->isNumericString()->yes(); + } + + return false; } private function processIdenticalOrNotIdentical(Equal|NotEqual $node): Identical|NotIdentical From f983655e527423da6f3fbdb61bab3ff9f527dda4 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sat, 4 Oct 2025 06:38:42 +0700 Subject: [PATCH 7/7] fix --- .../Fixture/skip_equal_numeric_string.php.inc | 7 +++++-- .../Equal/UseIdenticalOverEqualWithSameTypeRector.php | 5 +++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/rules-tests/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector/Fixture/skip_equal_numeric_string.php.inc b/rules-tests/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector/Fixture/skip_equal_numeric_string.php.inc index 17b968a9533..512336194c2 100644 --- a/rules-tests/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector/Fixture/skip_equal_numeric_string.php.inc +++ b/rules-tests/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector/Fixture/skip_equal_numeric_string.php.inc @@ -9,7 +9,10 @@ final class SkipIdenticalNumericStringCompareBool { public function equal() { - var_dump(true == '1'); - var_dump('1' == true); + // maybe compare to numeric string + $value = rand(0, 1) ? '1' : null; + + var_dump(true == $value); + var_dump($value == true); } } diff --git a/rules/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector.php b/rules/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector.php index 5d21edd3006..cbe3e39262f 100644 --- a/rules/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector.php +++ b/rules/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector.php @@ -103,12 +103,13 @@ public function refactor(Node $node): ?Node private function shouldSkipCompareNumericString(Type $leftStaticType, Type $rightStaticType): bool { + // use ! ->no() as to support both yes and maybe if ($leftStaticType instanceof BooleanType) { - return $rightStaticType->isNumericString()->yes(); + return ! $rightStaticType->isNumericString()->no(); } if ($rightStaticType instanceof BooleanType) { - return $leftStaticType->isNumericString()->yes(); + return ! $leftStaticType->isNumericString()->no(); } return false;