diff --git a/rules-tests/TypeDeclaration/Rector/Closure/ClosureReturnTypeFromAssertInstanceOfRector/ClosureReturnTypeFromAssertInstanceOfRectorTest.php b/rules-tests/TypeDeclaration/Rector/Class_/ClosureReturnTypeFromAssertInstanceOfRector/ClosureReturnTypeFromAssertInstanceOfRectorTest.php similarity index 86% rename from rules-tests/TypeDeclaration/Rector/Closure/ClosureReturnTypeFromAssertInstanceOfRector/ClosureReturnTypeFromAssertInstanceOfRectorTest.php rename to rules-tests/TypeDeclaration/Rector/Class_/ClosureReturnTypeFromAssertInstanceOfRector/ClosureReturnTypeFromAssertInstanceOfRectorTest.php index d4c301d5713..42028b94c0f 100644 --- a/rules-tests/TypeDeclaration/Rector/Closure/ClosureReturnTypeFromAssertInstanceOfRector/ClosureReturnTypeFromAssertInstanceOfRectorTest.php +++ b/rules-tests/TypeDeclaration/Rector/Class_/ClosureReturnTypeFromAssertInstanceOfRector/ClosureReturnTypeFromAssertInstanceOfRectorTest.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Rector\Tests\TypeDeclaration\Rector\Closure\ClosureReturnTypeFromAssertInstanceOfRector; +namespace Rector\Tests\TypeDeclaration\Rector\Class_\ClosureReturnTypeFromAssertInstanceOfRector; use Iterator; use PHPUnit\Framework\Attributes\DataProvider; diff --git a/rules-tests/TypeDeclaration/Rector/Closure/ClosureReturnTypeFromAssertInstanceOfRector/Fixture/assert_instance_of_narrowed_return.php.inc b/rules-tests/TypeDeclaration/Rector/Class_/ClosureReturnTypeFromAssertInstanceOfRector/Fixture/assert_instance_of_narrowed_return.php.inc similarity index 74% rename from rules-tests/TypeDeclaration/Rector/Closure/ClosureReturnTypeFromAssertInstanceOfRector/Fixture/assert_instance_of_narrowed_return.php.inc rename to rules-tests/TypeDeclaration/Rector/Class_/ClosureReturnTypeFromAssertInstanceOfRector/Fixture/assert_instance_of_narrowed_return.php.inc index ec6922f0f4c..64ab0d1f9cf 100644 --- a/rules-tests/TypeDeclaration/Rector/Closure/ClosureReturnTypeFromAssertInstanceOfRector/Fixture/assert_instance_of_narrowed_return.php.inc +++ b/rules-tests/TypeDeclaration/Rector/Class_/ClosureReturnTypeFromAssertInstanceOfRector/Fixture/assert_instance_of_narrowed_return.php.inc @@ -1,6 +1,6 @@ returnType instanceof Node) { + $classReflection = $this->fetchClassLikeReflection($node); + if (! $classReflection instanceof ClassReflection) { return null; } - // only handle closures narrowed by assertInstanceOf(); plain returns are handled by ClosureReturnTypeRector - if (! $this->hasAssertInstanceOf($node)) { + // is phpunit test case? + if (! $classReflection->is(ClassName::TEST_CASE_CLASS)) { return null; } - $scope = ScopeFetcher::fetch($node); - if (! $this->isInsideTestCaseClass($scope)) { - return null; - } + $hasChanged = false; - $closureReturnType = $this->returnTypeInferer->inferFunctionLike($node); + /** @var Closure[] $closures */ + $closures = $this->betterNodeFinder->findInstancesOf($node, [Closure::class]); + foreach ($closures as $closure) { + // type is already set + if ($closure->returnType instanceof Node) { + continue; + } - // handled by other rules - if ($closureReturnType instanceof NeverType) { - return null; - } + // only handle closures narrowed by assertInstanceOf(); plain returns are handled by ClosureReturnTypeRector + if (! $this->hasAssertInstanceOf($closure)) { + continue; + } - $returnTypeNode = $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode($closureReturnType, TypeKind::RETURN); - if (! $returnTypeNode instanceof Node) { - return null; + $closureReturnType = $this->returnTypeInferer->inferFunctionLike($closure); + + // handled by other rules + if ($closureReturnType instanceof NeverType) { + continue; + } + + $returnTypeNode = $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode($closureReturnType, TypeKind::RETURN); + if (! $returnTypeNode instanceof Node) { + continue; + } + + $closure->returnType = $returnTypeNode; + $hasChanged = true; } - $node->returnType = $returnTypeNode; + if ($hasChanged) { + return $node; + } - return $node; + return null; } public function provideMinPhpVersion(): int @@ -135,15 +150,4 @@ private function hasAssertInstanceOf(Closure $closure): bool && $this->isName($node->name, 'assertInstanceOf') ); } - - private function isInsideTestCaseClass(Scope $scope): bool - { - $classReflection = $scope->getClassReflection(); - if (! $classReflection instanceof ClassReflection) { - return false; - } - - // is phpunit test case? - return $classReflection->is(ClassName::TEST_CASE_CLASS); - } } diff --git a/src/Config/Level/TypeDeclarationLevel.php b/src/Config/Level/TypeDeclarationLevel.php index f4c421a7ea7..2194ee4471a 100644 --- a/src/Config/Level/TypeDeclarationLevel.php +++ b/src/Config/Level/TypeDeclarationLevel.php @@ -10,6 +10,7 @@ use Rector\TypeDeclaration\Rector\ArrowFunction\AddArrowFunctionReturnTypeRector; use Rector\TypeDeclaration\Rector\Class_\AddTestsVoidReturnTypeWhereNoReturnRector; use Rector\TypeDeclaration\Rector\Class_\ChildDoctrineRepositoryClassTypeRector; +use Rector\TypeDeclaration\Rector\Class_\ClosureReturnTypeFromAssertInstanceOfRector; use Rector\TypeDeclaration\Rector\Class_\MergeDateTimePropertyTypeDeclarationRector; use Rector\TypeDeclaration\Rector\Class_\ObjectTypedPropertyFromJMSSerializerAttributeTypeRector; use Rector\TypeDeclaration\Rector\Class_\PropertyTypeFromStrictSetterGetterRector; @@ -56,7 +57,6 @@ use Rector\TypeDeclaration\Rector\ClassMethod\StringReturnTypeFromStrictStringReturnsRector; use Rector\TypeDeclaration\Rector\Closure\AddClosureNeverReturnTypeRector; use Rector\TypeDeclaration\Rector\Closure\AddClosureVoidReturnTypeWhereNoReturnRector; -use Rector\TypeDeclaration\Rector\Closure\ClosureReturnTypeFromAssertInstanceOfRector; use Rector\TypeDeclaration\Rector\Closure\ClosureReturnTypeRector; use Rector\TypeDeclaration\Rector\FuncCall\AddArrayAnyAllClosureParamTypeRector; use Rector\TypeDeclaration\Rector\FuncCall\AddArrayFunctionClosureParamTypeRector;