[Downgrade PHP 7.4] Fixed bug for CovariantReturnType downgrading (#4850)

This commit is contained in:
Leonardo Losoviz 2020-12-12 07:32:52 +08:00 committed by GitHub
parent 35ceeff106
commit a3d38b8e98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 108 additions and 6 deletions

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Rector\DowngradePhp74\Rector\ClassMethod;
use PhpParser\Node;
use PhpParser\Node\Name;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\NullableType;
use PhpParser\Node\Stmt\ClassMethod;
@ -13,6 +14,7 @@ use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassReflection;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\Core\Rector\AbstractRector;
use Rector\NodeTypeResolver\ClassExistenceStaticHelper;
use Rector\NodeTypeResolver\Node\AttributeKey;
use ReflectionMethod;
use ReflectionNamedType;
@ -88,8 +90,11 @@ CODE_SAMPLE
}
/** @var string */
$parentReflectionMethodClassname = $this->getDifferentReturnTypeClassnameFromAncestorClass($node);
$newType = new FullyQualified($parentReflectionMethodClassname);
$parentReflectionMethodName = $this->getDifferentReturnTypeNameFromAncestorClass($node);
// The return type name could either be a classname, without the leading "\",
// or one among the reserved identifiers ("static", "self", "iterable", etc)
// To find out which is the case, check if this name exists as a class
$newType = ClassExistenceStaticHelper::doesClassLikeExist($parentReflectionMethodName) ? new FullyQualified($parentReflectionMethodName) : new Name($parentReflectionMethodName);
// Make it nullable?
if ($node->returnType instanceof NullableType) {
@ -106,10 +111,10 @@ CODE_SAMPLE
private function shouldRefactor(ClassMethod $classMethod): bool
{
return $this->getDifferentReturnTypeClassnameFromAncestorClass($classMethod) !== null;
return $this->getDifferentReturnTypeNameFromAncestorClass($classMethod) !== null;
}
private function getDifferentReturnTypeClassnameFromAncestorClass(ClassMethod $classMethod): ?string
private function getDifferentReturnTypeNameFromAncestorClass(ClassMethod $classMethod): ?string
{
/** @var Scope|null $scope */
$scope = $classMethod->getAttribute(AttributeKey::SCOPE);
@ -127,7 +132,9 @@ CODE_SAMPLE
if ($nodeReturnType === null || $nodeReturnType instanceof UnionType) {
return null;
}
$nodeReturnTypeName = $this->getName($nodeReturnType);
$nodeReturnTypeName = $this->getName(
$nodeReturnType instanceof NullableType ? $nodeReturnType->type : $nodeReturnType
);
/** @var string $methodName */
$methodName = $this->getName($classMethod->name);
@ -153,7 +160,6 @@ CODE_SAMPLE
if ($parentReflectionMethodReturnType === null || $parentReflectionMethodReturnType->getName() === $nodeReturnTypeName) {
continue;
}
// This is an ancestor class with a different return type
return $parentReflectionMethodReturnType->getName();
}

View File

@ -0,0 +1,38 @@
<?php
namespace Rector\DowngradePhp74\Tests\Rector\ClassMethod\DowngradeCovariantReturnTypeRector\Fixture;
class InterableA
{
public function covariantReturnTypes(): iterable
{ /* … */ }
}
class InterableB extends InterableA
{
public function covariantReturnTypes(): array
{ /* … */ }
}
?>
-----
<?php
namespace Rector\DowngradePhp74\Tests\Rector\ClassMethod\DowngradeCovariantReturnTypeRector\Fixture;
class InterableA
{
public function covariantReturnTypes(): iterable
{ /* … */ }
}
class InterableB extends InterableA
{
/**
* @return mixed[]
*/
public function covariantReturnTypes(): iterable
{ /* … */ }
}
?>

View File

@ -0,0 +1,20 @@
<?php
namespace Rector\DowngradePhp74\Tests\Rector\ClassMethod\DowngradeCovariantReturnTypeRector\Fixture;
class NullableScalarParentType {}
class NullableScalarChildType extends NullableScalarParentType {}
class NullableScalarA
{
public function covariantReturnTypes(): ?string
{ /* … */ }
}
class NullableScalarB extends NullableScalarA
{
public function covariantReturnTypes(): ?string
{ /* … */ }
}
?>

View File

@ -0,0 +1,38 @@
<?php
namespace Rector\DowngradePhp74\Tests\Rector\ClassMethod\DowngradeCovariantReturnTypeRector\Fixture;
class SelfA
{
public function covariantReturnTypes(): self
{ /* … */ }
}
class SelfB extends SelfA
{
public function covariantReturnTypes(): SelfB
{ /* … */ }
}
?>
-----
<?php
namespace Rector\DowngradePhp74\Tests\Rector\ClassMethod\DowngradeCovariantReturnTypeRector\Fixture;
class SelfA
{
public function covariantReturnTypes(): self
{ /* … */ }
}
class SelfB extends SelfA
{
/**
* @return \Rector\DowngradePhp74\Tests\Rector\ClassMethod\DowngradeCovariantReturnTypeRector\Fixture\SelfB
*/
public function covariantReturnTypes(): self
{ /* … */ }
}
?>