diff --git a/rules/DeadCode/Rector/Property/RemoveUnusedPrivatePropertyRector.php b/rules/DeadCode/Rector/Property/RemoveUnusedPrivatePropertyRector.php index 8b8dc8d65ef..69bd21eb30a 100644 --- a/rules/DeadCode/Rector/Property/RemoveUnusedPrivatePropertyRector.php +++ b/rules/DeadCode/Rector/Property/RemoveUnusedPrivatePropertyRector.php @@ -69,9 +69,7 @@ public function getNodeTypes(): array public function refactor(Node $node): ?Node { // skip if has no private property - $hasAnyPrivateProperty = array_any($node->getProperties(), function (Property $property): bool { - return $property->isPrivate(); - }); + $hasAnyPrivateProperty = array_any($node->getProperties(), fn(Property $property): bool => $property->isPrivate()); if (! $hasAnyPrivateProperty) { return null; diff --git a/rules/TypeDeclaration/Rector/BooleanAnd/BinaryOpNullableToInstanceofRector.php b/rules/TypeDeclaration/Rector/BooleanAnd/BinaryOpNullableToInstanceofRector.php index 6a4da96603a..bbd61838e94 100644 --- a/rules/TypeDeclaration/Rector/BooleanAnd/BinaryOpNullableToInstanceofRector.php +++ b/rules/TypeDeclaration/Rector/BooleanAnd/BinaryOpNullableToInstanceofRector.php @@ -7,10 +7,13 @@ 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\BooleanNot; +use PhpParser\Node\Expr\Empty_; use PhpParser\Node\Expr\Instanceof_; +use PhpParser\Node\Expr\Isset_; use PhpParser\Node\Name\FullyQualified; use PHPStan\Type\ObjectType; use Rector\Rector\AbstractRector; @@ -89,7 +92,7 @@ public function refactor(Node $node): ?Node */ private function processNullableInstance(BooleanAnd|BooleanOr $node): null|BooleanAnd|BooleanOr { - $nullableObjectType = $this->nullableTypeAnalyzer->resolveNullableObjectType($node->left); + $nullableObjectType = $this->resolveNullableObjectType($node->left); $hasChanged = false; if ($nullableObjectType instanceof ObjectType) { @@ -98,7 +101,7 @@ private function processNullableInstance(BooleanAnd|BooleanOr $node): null|Boole $hasChanged = true; } - $nullableObjectType = $this->nullableTypeAnalyzer->resolveNullableObjectType($node->right); + $nullableObjectType = $this->resolveNullableObjectType($node->right); if ($nullableObjectType instanceof ObjectType) { $node->right = $this->createExprInstanceof($node->right, $nullableObjectType); @@ -117,7 +120,7 @@ private function processNegationBooleanOr(BooleanOr $booleanOr): ?BooleanOr { $hasChanged = false; if ($booleanOr->left instanceof BooleanNot) { - $nullableObjectType = $this->nullableTypeAnalyzer->resolveNullableObjectType($booleanOr->left->expr); + $nullableObjectType = $this->resolveNullableObjectType($booleanOr->left->expr); if ($nullableObjectType instanceof ObjectType) { $booleanOr->left->expr = $this->createExprInstanceof($booleanOr->left->expr, $nullableObjectType); @@ -126,7 +129,7 @@ private function processNegationBooleanOr(BooleanOr $booleanOr): ?BooleanOr } if ($booleanOr->right instanceof BooleanNot) { - $nullableObjectType = $this->nullableTypeAnalyzer->resolveNullableObjectType($booleanOr->right->expr); + $nullableObjectType = $this->resolveNullableObjectType($booleanOr->right->expr); if ($nullableObjectType instanceof ObjectType) { $booleanOr->right->expr = $this->createExprInstanceof($booleanOr->right->expr, $nullableObjectType); @@ -142,6 +145,26 @@ private function processNegationBooleanOr(BooleanOr $booleanOr): ?BooleanOr return $this->processNullableInstance($booleanOr); } + private function resolveNullableObjectType(Expr $expr): ?ObjectType + { + // cheap bail - bool/scalar-shaped operands can never be a nullable object, + // skip the costly native type resolution for them (e.g. chained "$a && $b && $c") + if ($this->isNeverNullableObject($expr)) { + return null; + } + + return $this->nullableTypeAnalyzer->resolveNullableObjectType($expr); + } + + private function isNeverNullableObject(Expr $expr): bool + { + return $expr instanceof BinaryOp + || $expr instanceof BooleanNot + || $expr instanceof Instanceof_ + || $expr instanceof Empty_ + || $expr instanceof Isset_; + } + private function createExprInstanceof(Expr $expr, ObjectType $objectType): Instanceof_ { $fullyQualified = new FullyQualified($objectType->getClassName()); diff --git a/src/Configuration/Option.php b/src/Configuration/Option.php index 72031cceff5..34e5672107a 100644 --- a/src/Configuration/Option.php +++ b/src/Configuration/Option.php @@ -187,7 +187,6 @@ final class Option /** * @experimental Opt-in to the LPT bucket scheduler * @see \Rector\Parallel\Experimental\LptScheduleFactory - * @var string */ public const string LPT = 'lpt'; diff --git a/src/Parallel/Experimental/ExperimentalParallelFileProcessor.php b/src/Parallel/Experimental/ExperimentalParallelFileProcessor.php index acd0efdb3a6..1352ba42f80 100644 --- a/src/Parallel/Experimental/ExperimentalParallelFileProcessor.php +++ b/src/Parallel/Experimental/ExperimentalParallelFileProcessor.php @@ -67,7 +67,7 @@ public function process( ): ProcessResult { // reversed, so that array_pop() hands out the biggest files first $jobsPerWorker = array_map( - static fn (array $jobs): array => array_reverse($jobs), + array_reverse(...), $bucketSchedule->getJobsPerWorker() );