diff --git a/config/set/if.php b/config/set/if.php index 0a0c9db1adf..43cab14516a 100644 --- a/config/set/if.php +++ b/config/set/if.php @@ -3,12 +3,10 @@ declare(strict_types=1); use Rector\CodeQuality\Rector\If_\CombineIfRector; -use Rector\CodeQuality\Rector\If_\ExplicitBoolCompareRector; use Rector\Config\RectorConfig; return static function (RectorConfig $rectorConfig): void { $rectorConfig->rules([ - ExplicitBoolCompareRector::class, CombineIfRector::class, ]); }; diff --git a/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/ExplicitBoolCompareRectorTest.php b/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/ExplicitBoolCompareRectorTest.php deleted file mode 100644 index eb5c4fa1ec0..00000000000 --- a/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/ExplicitBoolCompareRectorTest.php +++ /dev/null @@ -1,28 +0,0 @@ -doTestFile($filePath); - } - - public static function provideData(): Iterator - { - return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); - } - - public function provideConfigFilePath(): string - { - return __DIR__ . '/config/configured_rule.php'; - } -} diff --git a/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/count.php.inc b/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/count.php.inc deleted file mode 100644 index 41747710a38..00000000000 --- a/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/count.php.inc +++ /dev/null @@ -1,35 +0,0 @@ - ------ - 0) { - return 'many items'; - } - } -} - -?> diff --git a/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/explode.php.inc b/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/explode.php.inc deleted file mode 100644 index 4291877dbed..00000000000 --- a/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/explode.php.inc +++ /dev/null @@ -1,37 +0,0 @@ - ------ - diff --git a/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/if_assign_cond.php.inc b/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/if_assign_cond.php.inc deleted file mode 100644 index 21fe987bf2f..00000000000 --- a/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/if_assign_cond.php.inc +++ /dev/null @@ -1,36 +0,0 @@ - ------ - diff --git a/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/numbers.php.inc b/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/numbers.php.inc deleted file mode 100644 index 39c8cc5c52f..00000000000 --- a/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/numbers.php.inc +++ /dev/null @@ -1,53 +0,0 @@ - ------ - diff --git a/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/phpstan_0_12_6break.php.inc b/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/phpstan_0_12_6break.php.inc deleted file mode 100644 index 05bf39096d7..00000000000 --- a/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/phpstan_0_12_6break.php.inc +++ /dev/null @@ -1,31 +0,0 @@ - ------ - diff --git a/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/skip_if_else.php.inc b/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/skip_if_else.php.inc deleted file mode 100644 index a533a32c5a7..00000000000 --- a/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/skip_if_else.php.inc +++ /dev/null @@ -1,17 +0,0 @@ -elseifs) { - return true; - } - - return false; - } -} diff --git a/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/skip_nested_array_mixed.php.inc b/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/skip_nested_array_mixed.php.inc deleted file mode 100644 index 9b70d670e89..00000000000 --- a/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/skip_nested_array_mixed.php.inc +++ /dev/null @@ -1,17 +0,0 @@ -provider(); - $this->value = $data['key'] ? 1 : 2; - } -} diff --git a/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/skip_phpdoc-typed.php.inc b/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/skip_phpdoc-typed.php.inc deleted file mode 100644 index 293a0f3d70f..00000000000 --- a/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/skip_phpdoc-typed.php.inc +++ /dev/null @@ -1,26 +0,0 @@ - diff --git a/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/string.php.inc b/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/string.php.inc deleted file mode 100644 index 34ab2ba5fe4..00000000000 --- a/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/string.php.inc +++ /dev/null @@ -1,39 +0,0 @@ - ------ - diff --git a/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/string_known_value.php.inc b/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/string_known_value.php.inc deleted file mode 100644 index b59f134198a..00000000000 --- a/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/string_known_value.php.inc +++ /dev/null @@ -1,53 +0,0 @@ - ------ - diff --git a/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/string_known_value2.php.inc b/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/string_known_value2.php.inc deleted file mode 100644 index 951eb4714ca..00000000000 --- a/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/string_known_value2.php.inc +++ /dev/null @@ -1,53 +0,0 @@ - ------ - diff --git a/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/string_known_value3.php.inc b/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/string_known_value3.php.inc deleted file mode 100644 index a9fdd29db99..00000000000 --- a/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/string_known_value3.php.inc +++ /dev/null @@ -1,53 +0,0 @@ - ------ - diff --git a/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/with_ternary.php.inc b/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/with_ternary.php.inc deleted file mode 100644 index 5a1ff5d8630..00000000000 --- a/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/Fixture/with_ternary.php.inc +++ /dev/null @@ -1,31 +0,0 @@ - ------ - diff --git a/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/config/configured_rule.php b/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/config/configured_rule.php deleted file mode 100644 index b33ccbcbfcf..00000000000 --- a/rules-tests/CodeQuality/Rector/If_/ExplicitBoolCompareRector/config/configured_rule.php +++ /dev/null @@ -1,9 +0,0 @@ -withRules([ExplicitBoolCompareRector::class]); diff --git a/rules/CodeQuality/Rector/If_/ExplicitBoolCompareRector.php b/rules/CodeQuality/Rector/If_/ExplicitBoolCompareRector.php index 58b33b1933d..b1215030288 100644 --- a/rules/CodeQuality/Rector/If_/ExplicitBoolCompareRector.php +++ b/rules/CodeQuality/Rector/If_/ExplicitBoolCompareRector.php @@ -5,46 +5,20 @@ namespace Rector\CodeQuality\Rector\If_; use PhpParser\Node; -use PhpParser\Node\Expr; -use PhpParser\Node\Expr\Assign; -use PhpParser\Node\Expr\BinaryOp; -use PhpParser\Node\Expr\BinaryOp\BooleanAnd; -use PhpParser\Node\Expr\BinaryOp\BooleanOr; -use PhpParser\Node\Expr\BinaryOp\Greater; -use PhpParser\Node\Expr\BinaryOp\Identical; -use PhpParser\Node\Expr\BinaryOp\NotIdentical; -use PhpParser\Node\Expr\BooleanNot; -use PhpParser\Node\Expr\Cast\Bool_; -use PhpParser\Node\Expr\FuncCall; use PhpParser\Node\Expr\Ternary; -use PhpParser\Node\Scalar\Float_; -use PhpParser\Node\Scalar\Int_; -use PhpParser\Node\Scalar\String_; -use PhpParser\Node\Stmt; use PhpParser\Node\Stmt\ElseIf_; -use PhpParser\Node\Stmt\Expression; use PhpParser\Node\Stmt\If_; -use PHPStan\Type\MixedType; -use PHPStan\Type\ObjectType; -use Rector\NodeTypeResolver\TypeAnalyzer\ArrayTypeAnalyzer; -use Rector\NodeTypeResolver\TypeAnalyzer\StringTypeAnalyzer; -use Rector\PhpParser\Node\Value\ValueResolver; +use Rector\Configuration\Deprecation\Contract\DeprecatedInterface; +use Rector\Exception\ShouldNotHappenException; use Rector\Rector\AbstractRector; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; /** - * @see \Rector\Tests\CodeQuality\Rector\If_\ExplicitBoolCompareRector\ExplicitBoolCompareRectorTest + * @deprecated This rule is deprecated. Array and object bool compares have dedicated rules; the rest is an opinionated approach that depends on context. */ -final class ExplicitBoolCompareRector extends AbstractRector +final class ExplicitBoolCompareRector extends AbstractRector implements DeprecatedInterface { - public function __construct( - private readonly StringTypeAnalyzer $stringTypeAnalyzer, - private readonly ArrayTypeAnalyzer $arrayTypeAnalyzer, - private readonly ValueResolver $valueResolver, - ) { - } - public function getRuleDefinition(): RuleDefinition { return new RuleDefinition('Make if conditions more explicit', [ @@ -86,174 +60,12 @@ public function getNodeTypes(): array /** * @param If_|ElseIf_|Ternary $node - * @return null|Stmt[]|Node */ - public function refactor(Node $node): null|array|Node + public function refactor(Node $node): ?Node { - // skip short ternary - if ($node instanceof Ternary && ! $node->if instanceof Expr) { - return null; - } - - if ($node->cond instanceof BooleanNot) { - $conditionNode = $node->cond->expr; - $isNegated = true; - } else { - $conditionNode = $node->cond; - $isNegated = false; - } - - if ($conditionNode instanceof Bool_) { - return null; - } - - $conditionStaticType = $this->nodeTypeResolver->getNativeType($conditionNode); - if ($conditionStaticType instanceof MixedType || $conditionStaticType->isBoolean()->yes()) { - return null; - } - - // handled by ArrayExplicitBoolCompareRector - if ($this->arrayTypeAnalyzer->isArrayType($conditionNode)) { - return null; - } - - // handled by ObjectExplicitBoolCompareRector - if ($this->nodeTypeResolver->matchNullableTypeOfSpecificType( - $conditionNode, - ObjectType::class - ) instanceof ObjectType) { - return null; - } - - $binaryOp = $this->resolveNewConditionNode($conditionNode, $isNegated); - if (! $binaryOp instanceof Expr) { - return null; - } - - if ($node instanceof If_ && $node->cond instanceof Assign && $binaryOp->left instanceof NotIdentical && $binaryOp->right instanceof NotIdentical) { - $expression = new Expression($node->cond); - $binaryOp->left->left = $node->cond->var; - $binaryOp->right->left = $node->cond->var; - - $node->cond = $binaryOp; - - return [$expression, $node]; - } - - $node->cond = $binaryOp; - - return $node; - } - - private function resolveNewConditionNode(Expr $expr, bool $isNegated): ?BinaryOp - { - if ($expr instanceof FuncCall && $this->isName($expr, 'count')) { - return $this->resolveCount($isNegated, $expr); - } - - if ($this->stringTypeAnalyzer->isStringOrUnionStringOnlyType($expr)) { - return $this->resolveString($isNegated, $expr); - } - - $exprType = $this->getType($expr); - if ($exprType->isInteger()->yes()) { - return $this->resolveInteger($isNegated, $expr); - } - - if ($exprType->isFloat()->yes()) { - return $this->resolveFloat($isNegated, $expr); - } - - return null; - } - - private function resolveCount(bool $isNegated, FuncCall $funcCall): Identical|Greater|null - { - if ($funcCall->isFirstClassCallable()) { - return null; - } - - $countedType = $this->getType($funcCall->getArgs()[0]->value); - - if ($countedType->isArray()->yes()) { - return null; - } - - $int = new Int_(0); - - // compare === 0, assumption - if ($isNegated) { - return new Identical($funcCall, $int); - } - - return new Greater($funcCall, $int); - } - - private function resolveString(bool $isNegated, Expr $expr): Identical|NotIdentical|BooleanAnd|BooleanOr - { - $emptyString = new String_(''); - - $identical = $this->resolveIdentical($expr, $isNegated, $emptyString); - - $value = $this->valueResolver->getValue($expr); - - // unknown value. may be from parameter - if ($value === null) { - return $this->resolveZeroIdenticalString($identical, $isNegated, $expr); - } - - $length = strlen((string) $value); - - if ($length === 1) { - $zeroString = new String_('0'); - return $this->resolveIdentical($expr, $isNegated, $zeroString); - } - - return $identical; - } - - private function resolveIdentical(Expr $expr, bool $isNegated, String_ $string): Identical|NotIdentical - { - /** - * // compare === '' - */ - $identical = $isNegated - ? new Identical($expr, $string) - : new NotIdentical($expr, $string); - - return $identical; - } - - private function resolveZeroIdenticalString( - Identical|NotIdentical $identical, - bool $isNegated, - Expr $expr - ): BooleanAnd|BooleanOr { - $string = new String_('0'); - - $zeroIdentical = $isNegated ? new Identical($expr, $string) : new NotIdentical($expr, $string); - return $isNegated ? new BooleanOr($identical, $zeroIdentical) : new BooleanAnd($identical, $zeroIdentical); - } - - private function resolveInteger(bool $isNegated, Expr $expr): Identical|NotIdentical - { - $int = new Int_(0); - - if ($isNegated) { - return new Identical($expr, $int); - } - - return new NotIdentical($expr, $int); - } - - private function resolveFloat(bool $isNegated, Expr $expr): Identical|NotIdentical - { - $float = new Float_(0.0); - - if ($isNegated) { - return new Identical($expr, $float); - } - - return new NotIdentical($expr, $float); + throw new ShouldNotHappenException(sprintf( + '"%s" rule is deprecated, as array and object bool compares have dedicated rules and the rest is an opinionated approach that depends on context', + self::class + )); } } diff --git a/tests/Issues/Issue7306/Fixture/fixture.php.inc b/tests/Issues/Issue7306/Fixture/fixture.php.inc deleted file mode 100644 index a6a91ea55f3..00000000000 --- a/tests/Issues/Issue7306/Fixture/fixture.php.inc +++ /dev/null @@ -1,38 +0,0 @@ - ------ - diff --git a/tests/Issues/Issue7306/RuleCombinationShouldNotSimplifyIfNotNullReturnTest.php b/tests/Issues/Issue7306/RuleCombinationShouldNotSimplifyIfNotNullReturnTest.php deleted file mode 100644 index 72aae2f279b..00000000000 --- a/tests/Issues/Issue7306/RuleCombinationShouldNotSimplifyIfNotNullReturnTest.php +++ /dev/null @@ -1,31 +0,0 @@ -doTestFile($filePath); - } - - public static function provideData(): Iterator - { - return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); - } - - public function provideConfigFilePath(): string - { - return __DIR__ . '/config/configured_rule.php'; - } -} diff --git a/tests/Issues/Issue7306/config/configured_rule.php b/tests/Issues/Issue7306/config/configured_rule.php deleted file mode 100644 index 05a75d33ea1..00000000000 --- a/tests/Issues/Issue7306/config/configured_rule.php +++ /dev/null @@ -1,17 +0,0 @@ -withRules( - [ - SimplifyIfNotNullReturnRector::class, - ExplicitBoolCompareRector::class, - NewlineBetweenClassLikeStmtsRector::class, - ] - );