[TypeDeclaration] Avoid adding param type in case of different default type (#1956)

This commit is contained in:
Tomas Votruba 2022-03-23 10:28:29 +01:00 committed by GitHub
parent 8f86f525f7
commit cbefb243e2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 94 additions and 1 deletions

View File

@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\AddMethodCallBasedStrictParamTypeRector\Fixture;
final class SkipDefault
{
public function runFirst()
{
$this->process('first');
}
public function runEmpty()
{
$this->process();
}
private function process($data = false)
{
}
}

View File

@ -0,0 +1,49 @@
<?php
declare(strict_types=1);
namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\AddMethodCallBasedStrictParamTypeRector\Fixture;
final class TypeCompatibleDefault
{
public function runFirst()
{
$this->process('first');
}
public function runEmpty()
{
$this->process();
}
private function process($data = 'yes')
{
}
}
?>
-----
<?php
declare(strict_types=1);
namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\AddMethodCallBasedStrictParamTypeRector\Fixture;
final class TypeCompatibleDefault
{
public function runFirst()
{
$this->process('first');
}
public function runEmpty()
{
$this->process();
}
private function process(string $data = 'yes')
{
}
}
?>

View File

@ -5,6 +5,8 @@ declare(strict_types=1);
namespace Rector\TypeDeclaration\NodeAnalyzer;
use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\ClassMethod;
use PHPStan\Type\CallableType;
use PHPStan\Type\MixedType;
@ -36,6 +38,7 @@ final class ClassMethodParamTypeCompleter
$hasChanged = false;
foreach ($classParameterTypes as $position => $argumentStaticType) {
/** @var Type $argumentStaticType */
if ($this->shouldSkipArgumentStaticType($classMethod, $argumentStaticType, $position, $maxUnionTypes)) {
continue;
}
@ -49,8 +52,15 @@ final class ClassMethodParamTypeCompleter
continue;
}
// check default override
$param = $classMethod->params[$position];
if (! $this->isAcceptedByDefault($param, $argumentStaticType)) {
continue;
}
// update parameter
$classMethod->params[$position]->type = $phpParserTypeNode;
$param->type = $phpParserTypeNode;
$hasChanged = true;
}
@ -165,4 +175,16 @@ final class ClassMethodParamTypeCompleter
return $type;
}
private function isAcceptedByDefault(Param $param, Type $argumentStaticType): bool
{
if (! $param->default instanceof Expr) {
return true;
}
$defaultExpr = $param->default;
$defaultStaticType = $this->staticTypeMapper->mapPhpParserNodePHPStanType($defaultExpr);
return $argumentStaticType->accepts($defaultStaticType, false)
->yes();
}
}