diff --git a/rules-tests/DeadCode/Rector/If_/RemoveAlwaysTrueIfConditionRector/Fixture/skip_trait_this.php.inc b/rules-tests/DeadCode/Rector/If_/RemoveAlwaysTrueIfConditionRector/Fixture/skip_trait_this.php.inc new file mode 100644 index 00000000000..403c4e633c1 --- /dev/null +++ b/rules-tests/DeadCode/Rector/If_/RemoveAlwaysTrueIfConditionRector/Fixture/skip_trait_this.php.inc @@ -0,0 +1,17 @@ +getExample() === false) { + $this->setExample('demo'); + } + } + } +} diff --git a/rules/DeadCode/NodeAnalyzer/SafeLeftTypeBooleanAndOrAnalyzer.php b/rules/DeadCode/NodeAnalyzer/SafeLeftTypeBooleanAndOrAnalyzer.php index f1ee68b21be..9c523d2b1f8 100644 --- a/rules/DeadCode/NodeAnalyzer/SafeLeftTypeBooleanAndOrAnalyzer.php +++ b/rules/DeadCode/NodeAnalyzer/SafeLeftTypeBooleanAndOrAnalyzer.php @@ -4,6 +4,7 @@ namespace Rector\DeadCode\NodeAnalyzer; +use PHPStan\Type\ObjectType; use PhpParser\Node; use PhpParser\Node\Expr\ArrayDimFetch; use PhpParser\Node\Expr\BinaryOp\BooleanAnd; @@ -11,14 +12,19 @@ use PhpParser\Node\Expr\PropertyFetch; use PhpParser\Node\Expr\StaticPropertyFetch; use PhpParser\Node\Expr\Variable; +use PHPStan\Reflection\ClassReflection; use Rector\NodeAnalyzer\ExprAnalyzer; +use Rector\NodeTypeResolver\NodeTypeResolver; use Rector\PhpParser\Node\BetterNodeFinder; +use Rector\Reflection\ReflectionResolver; final readonly class SafeLeftTypeBooleanAndOrAnalyzer { public function __construct( private readonly BetterNodeFinder $betterNodeFinder, - private readonly ExprAnalyzer $exprAnalyzer + private readonly ExprAnalyzer $exprAnalyzer, + private readonly ReflectionResolver $reflectionResolver, + private readonly NodeTypeResolver $nodeTypeResolver ) { } @@ -33,10 +39,25 @@ public function isSafe(BooleanAnd|BooleanOr $booleanAnd): bool return false; } - // get type from Property and ArrayDimFetch is unreliable - return ! (bool) $this->betterNodeFinder->findFirst( + $hasPropertyFetchOrArrayDimFetch = (bool) $this->betterNodeFinder->findFirst( $booleanAnd->left, static fn (Node $node): bool => $node instanceof PropertyFetch || $node instanceof StaticPropertyFetch || $node instanceof ArrayDimFetch ); + + // get type from Property and ArrayDimFetch is unreliable + if ($hasPropertyFetchOrArrayDimFetch) { + return false; + } + + // skip trait this + $classReflection = $this->reflectionResolver->resolveClassReflection($booleanAnd); + if ($classReflection instanceof ClassReflection && $classReflection->isTrait()) { + return ! (bool) $this->betterNodeFinder->findFirst( + $booleanAnd->left, + fn (Node $node): bool => $this->nodeTypeResolver->getType($node) instanceof ObjectType + ); + } + + return true; } }