diff --git a/config/set/rector-preset.php b/config/set/rector-preset.php index b3d40f3ce36..ba74445ba5e 100644 --- a/config/set/rector-preset.php +++ b/config/set/rector-preset.php @@ -2,12 +2,12 @@ declare(strict_types=1); -use Rector\Utils\Rector\RemoveRefactorDuplicatedNodeInstanceCheckRector; -use Rector\PHPUnit\CodeQuality\Rector\Class_\AddSeeTestAnnotationRector; use Rector\CodingStyle\Rector\PostInc\PostIncDecToPreIncDecRector; use Rector\Config\RectorConfig; +use Rector\PHPUnit\CodeQuality\Rector\Class_\AddSeeTestAnnotationRector; use Rector\Privatization\Rector\Class_\FinalizeTestCaseClassRector; use Rector\TypeDeclaration\Rector\StmtsAwareInterface\DeclareStrictTypesRector; +use Rector\Utils\Rector\RemoveRefactorDuplicatedNodeInstanceCheckRector; return static function (RectorConfig $rectorConfig): void { $rectorConfig->rules([ diff --git a/rules-tests/DeadCode/Rector/ClassMethod/RemoveUnusedPrivateMethodRector/Fixture/skip_used_method_in_never_type_scope.php.inc b/rules-tests/DeadCode/Rector/ClassMethod/RemoveUnusedPrivateMethodRector/Fixture/skip_used_method_in_never_type_scope.php.inc new file mode 100644 index 00000000000..2d9a45f5df0 --- /dev/null +++ b/rules-tests/DeadCode/Rector/ClassMethod/RemoveUnusedPrivateMethodRector/Fixture/skip_used_method_in_never_type_scope.php.inc @@ -0,0 +1,37 @@ +tokenizationEnabled && !empty($this->queuedRecipients) && !$isQueueFlush) { + return $this->queue(); + } + + if (!$isQueueFlush) { + $this->setFromForSingleMessage(); + } + + return true; + } + + public function queue() + { + if ($this->tokenizationEnabled) { + return true; + } + + return $this->send(); + } + + private function setFromForSingleMessage(): void + { + echo 'used'; + } +} diff --git a/rules/DeadCode/NodeAnalyzer/CallCollectionAnalyzer.php b/rules/DeadCode/NodeAnalyzer/CallCollectionAnalyzer.php index 967e04b74c8..44b06b5d5c1 100644 --- a/rules/DeadCode/NodeAnalyzer/CallCollectionAnalyzer.php +++ b/rules/DeadCode/NodeAnalyzer/CallCollectionAnalyzer.php @@ -11,6 +11,7 @@ use PhpParser\Node\Identifier; use PhpParser\Node\Name; use PHPStan\Type\MixedType; +use PHPStan\Type\NeverType; use Rector\Enum\ObjectReference; use Rector\NodeNameResolver\NodeNameResolver; use Rector\NodeTypeResolver\NodeTypeResolver; @@ -35,6 +36,12 @@ public function isExists(array $calls, string $classMethodName, string $classNam $callerTypeClassName = ClassNameFromObjectTypeResolver::resolve($callerType); if ($callerTypeClassName === null) { + // the caller scope is unreachable, e.g. behind mutual recursion, so the type + // resolves to never; the call still exists in code, keep the method to be safe + if ($callerType instanceof NeverType && $this->shouldSkip($call, $classMethodName)) { + return true; + } + // handle fluent by $this->bar()->baz()->qux() // that methods don't have return type if ($callerType instanceof MixedType && ! $callerType->isExplicitMixed()) {