Merge pull request #3576 from rectorphp/fix-return-child-type

fix return type in abstract class
This commit is contained in:
kodiakhq[bot] 2020-06-23 20:05:28 +00:00 committed by GitHub
commit 1bc1c6fde7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 69 additions and 4 deletions

View File

@ -53,9 +53,12 @@ final class ReturnTypeInferer extends AbstractPriorityAwareTypeInferer
$type = $this->typeNormalizer->uniqueateConstantArrayType($type);
$type = $this->typeNormalizer->normalizeArrayOfUnionToUnionArray($type);
if (! $type instanceof MixedType) {
return $type;
// in case of void, check return type of children methods
if ($type instanceof MixedType) {
continue;
}
return $type;
}
return new MixedType();

View File

@ -8,6 +8,7 @@ use PhpParser\Node;
use PhpParser\Node\Expr\Closure;
use PhpParser\Node\FunctionLike;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassLike;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Function_;
use PhpParser\Node\Stmt\Interface_;
@ -30,15 +31,18 @@ final class ReturnedNodesReturnTypeInferer extends AbstractTypeInferer implement
{
/** @var Class_|Trait_|Interface_|null $classLike */
$classLike = $functionLike->getAttribute(AttributeKey::CLASS_NODE);
if ($classLike === null) {
return new MixedType();
}
if ($functionLike instanceof ClassMethod && $classLike instanceof Interface_) {
return new MixedType();
}
$localReturnNodes = $this->collectReturns($functionLike);
if ($localReturnNodes === []) {
// void type
if ($functionLike instanceof ClassMethod && ! $functionLike->isAbstract()) {
if (! $this->isAbstractMethod($classLike, $functionLike)) {
return new VoidType();
}
@ -92,4 +96,15 @@ final class ReturnedNodesReturnTypeInferer extends AbstractTypeInferer implement
return $returns;
}
private function isAbstractMethod(ClassLike $classLike, FunctionLike $functionLike): bool
{
// abstract class method
if ($functionLike instanceof ClassMethod && $functionLike->isAbstract()) {
return true;
}
// abstract class
return $classLike instanceof Class_ && $classLike->isAbstract();
}
}

View File

@ -0,0 +1,47 @@
<?php
namespace Rector\TypeDeclaration\Tests\Rector\ClassMethod\ReturnTypeDeclarationRector\Fixture;
use Rector\Core\Exception\NotImplementedYetException;
abstract class ParentOverride
{
public function getValue()
{
throw new NotImplementedYetException();
}
}
class OverrideParent extends ParentOverride
{
public function getValue()
{
return 'string';
}
}
?>
-----
<?php
namespace Rector\TypeDeclaration\Tests\Rector\ClassMethod\ReturnTypeDeclarationRector\Fixture;
use Rector\Core\Exception\NotImplementedYetException;
abstract class ParentOverride
{
public function getValue()
{
throw new NotImplementedYetException();
}
}
class OverrideParent extends ParentOverride
{
public function getValue(): string
{
return 'string';
}
}
?>