diff --git a/rules/TypeDeclaration/Rector/ClassMethod/AddVoidReturnTypeWhereNoReturnRector.php b/rules/TypeDeclaration/Rector/ClassMethod/AddVoidReturnTypeWhereNoReturnRector.php index 4c0aa0712ec..27b07ad169b 100644 --- a/rules/TypeDeclaration/Rector/ClassMethod/AddVoidReturnTypeWhereNoReturnRector.php +++ b/rules/TypeDeclaration/Rector/ClassMethod/AddVoidReturnTypeWhereNoReturnRector.php @@ -8,10 +8,10 @@ use PhpParser\Node\Expr\Closure; use PhpParser\Node\Identifier; use PhpParser\Node\Stmt\ClassMethod; use PhpParser\Node\Stmt\Function_; -use PHPStan\Reflection\ClassReflection; +use PhpParser\Node\Stmt\Throw_; use Rector\Core\NodeAnalyzer\MagicClassMethodAnalyzer; use Rector\Core\Rector\AbstractRector; -use Rector\Core\Reflection\ReflectionResolver; +use Rector\Core\Reflection\ClassModifierChecker; use Rector\Core\ValueObject\PhpVersionFeature; use Rector\TypeDeclaration\TypeInferer\SilentVoidResolver; use Rector\VendorLocker\NodeVendorLocker\ClassMethodReturnVendorLockResolver; @@ -33,22 +33,22 @@ final class AddVoidReturnTypeWhereNoReturnRector extends AbstractRector implemen * @var \Rector\VendorLocker\NodeVendorLocker\ClassMethodReturnVendorLockResolver */ private $classMethodReturnVendorLockResolver; - /** - * @readonly - * @var \Rector\Core\Reflection\ReflectionResolver - */ - private $reflectionResolver; /** * @readonly * @var \Rector\Core\NodeAnalyzer\MagicClassMethodAnalyzer */ private $magicClassMethodAnalyzer; - public function __construct(SilentVoidResolver $silentVoidResolver, ClassMethodReturnVendorLockResolver $classMethodReturnVendorLockResolver, ReflectionResolver $reflectionResolver, MagicClassMethodAnalyzer $magicClassMethodAnalyzer) + /** + * @readonly + * @var \Rector\Core\Reflection\ClassModifierChecker + */ + private $classModifierChecker; + public function __construct(SilentVoidResolver $silentVoidResolver, ClassMethodReturnVendorLockResolver $classMethodReturnVendorLockResolver, MagicClassMethodAnalyzer $magicClassMethodAnalyzer, ClassModifierChecker $classModifierChecker) { $this->silentVoidResolver = $silentVoidResolver; $this->classMethodReturnVendorLockResolver = $classMethodReturnVendorLockResolver; - $this->reflectionResolver = $reflectionResolver; $this->magicClassMethodAnalyzer = $magicClassMethodAnalyzer; + $this->classModifierChecker = $classModifierChecker; } public function getRuleDefinition() : RuleDefinition { @@ -119,25 +119,24 @@ CODE_SAMPLE if ($functionLike->isAbstract()) { return \true; } + // is not final and has only exception? possibly implemented by child + if ($this->isNotFinalAndHasExceptionOnly($functionLike)) { + return \true; + } if ($functionLike->isProtected()) { - return !$this->isInsideFinalClass($functionLike); + return !$this->classModifierChecker->isInsideFinalClass($functionLike); } - return $this->isInsideAbstractClass($functionLike) && $functionLike->getStmts() === []; + return $this->classModifierChecker->isInsideAbstractClass($functionLike) && $functionLike->getStmts() === []; } - private function isInsideFinalClass(ClassMethod $classMethod) : bool + private function isNotFinalAndHasExceptionOnly(ClassMethod $classMethod) : bool { - $classReflection = $this->reflectionResolver->resolveClassReflection($classMethod); - if (!$classReflection instanceof ClassReflection) { + if ($this->classModifierChecker->isInsideFinalClass($classMethod)) { return \false; } - return $classReflection->isFinalByKeyword(); - } - private function isInsideAbstractClass(ClassMethod $classMethod) : bool - { - $classReflection = $this->reflectionResolver->resolveClassReflection($classMethod); - if (!$classReflection instanceof ClassReflection) { + if (\count((array) $classMethod->stmts) !== 1) { return \false; } - return $classReflection->isAbstract(); + $onlyStmt = $classMethod->stmts[0] ?? null; + return $onlyStmt instanceof Throw_; } } diff --git a/src/Application/VersionResolver.php b/src/Application/VersionResolver.php index 0920c7fb768..270e6a9f637 100644 --- a/src/Application/VersionResolver.php +++ b/src/Application/VersionResolver.php @@ -19,12 +19,12 @@ final class VersionResolver * @api * @var string */ - public const PACKAGE_VERSION = '5259090faea9e744c79da1115ad299d31b649bb1'; + public const PACKAGE_VERSION = '3cef752763be750ea221c5c5eb1681d27398a3d5'; /** * @api * @var string */ - public const RELEASE_DATE = '2023-12-23 14:01:33'; + public const RELEASE_DATE = '2023-12-23 15:26:18'; /** * @var int */ diff --git a/src/Reflection/ClassModifierChecker.php b/src/Reflection/ClassModifierChecker.php new file mode 100644 index 00000000000..3ec3bd65c95 --- /dev/null +++ b/src/Reflection/ClassModifierChecker.php @@ -0,0 +1,35 @@ +reflectionResolver = $reflectionResolver; + } + public function isInsideFinalClass(Node $node) : bool + { + $classReflection = $this->reflectionResolver->resolveClassReflection($node); + if (!$classReflection instanceof ClassReflection) { + return \false; + } + return $classReflection->isFinalByKeyword(); + } + public function isInsideAbstractClass(Node $node) : bool + { + $classReflection = $this->reflectionResolver->resolveClassReflection($node); + if (!$classReflection instanceof ClassReflection) { + return \false; + } + return $classReflection->isAbstract(); + } +} diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index 877d09bab3c..f07431d2445 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -1277,6 +1277,7 @@ return array( 'Rector\\Core\\Rector\\AbstractCollectorRector' => $baseDir . '/src/Rector/AbstractCollectorRector.php', 'Rector\\Core\\Rector\\AbstractRector' => $baseDir . '/src/Rector/AbstractRector.php', 'Rector\\Core\\Rector\\AbstractScopeAwareRector' => $baseDir . '/src/Rector/AbstractScopeAwareRector.php', + 'Rector\\Core\\Reflection\\ClassModifierChecker' => $baseDir . '/src/Reflection/ClassModifierChecker.php', 'Rector\\Core\\Reflection\\ClassReflectionAnalyzer' => $baseDir . '/src/Reflection/ClassReflectionAnalyzer.php', 'Rector\\Core\\Reflection\\MethodReflectionResolver' => $baseDir . '/src/Reflection/MethodReflectionResolver.php', 'Rector\\Core\\Reflection\\ReflectionResolver' => $baseDir . '/src/Reflection/ReflectionResolver.php', diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 630111d76ad..adc954ee7d7 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -1495,6 +1495,7 @@ class ComposerStaticInit8339caf294dd12447c06647e5d0dc118 'Rector\\Core\\Rector\\AbstractCollectorRector' => __DIR__ . '/../..' . '/src/Rector/AbstractCollectorRector.php', 'Rector\\Core\\Rector\\AbstractRector' => __DIR__ . '/../..' . '/src/Rector/AbstractRector.php', 'Rector\\Core\\Rector\\AbstractScopeAwareRector' => __DIR__ . '/../..' . '/src/Rector/AbstractScopeAwareRector.php', + 'Rector\\Core\\Reflection\\ClassModifierChecker' => __DIR__ . '/../..' . '/src/Reflection/ClassModifierChecker.php', 'Rector\\Core\\Reflection\\ClassReflectionAnalyzer' => __DIR__ . '/../..' . '/src/Reflection/ClassReflectionAnalyzer.php', 'Rector\\Core\\Reflection\\MethodReflectionResolver' => __DIR__ . '/../..' . '/src/Reflection/MethodReflectionResolver.php', 'Rector\\Core\\Reflection\\ReflectionResolver' => __DIR__ . '/../..' . '/src/Reflection/ReflectionResolver.php',