[Php80] Handle Generic TemplateType on ClassPropertyAssignToConstructorPromotionRector (#751)

* Add failing test fixture for ClassPropertyAssignToConstructorPromotionRector

# Failing Test for ClassPropertyAssignToConstructorPromotionRector

Based on https://getrector.org/demo/1ec04a84-bde1-6cb0-a397-d7c0f606a738

* Closes #749

* naming

* phpstan

* early check is param used before assign

Co-authored-by: Jáchym Toušek <enumag@gmail.com>
This commit is contained in:
Abdul Malik Ikhsan 2021-08-24 21:44:45 +07:00 committed by GitHub
parent 6ff80ba037
commit 885ef768e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 72 additions and 9 deletions

View File

@ -0,0 +1,41 @@
<?php
namespace Rector\Tests\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector\Fixture;
/**
* @template T
*/
final class Generic
{
/**
* @var T
*/
public mixed $value;
/**
* @param T $value
*/
public function __construct(mixed $value)
{
$this->value = $value;
}
}
?>
-----
<?php
namespace Rector\Tests\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector\Fixture;
/**
* @template T
*/
final class Generic
{
/**
* @param T $value
*/
public function __construct(public mixed $value)
{
}
}
?>

View File

@ -12,6 +12,7 @@ use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Expression;
use PhpParser\Node\Stmt\Property;
use PHPStan\Type\Generic\TemplateType;
use PHPStan\Type\Type;
use PHPStan\Type\UnionType;
use Rector\Core\PhpParser\Comparing\NodeComparator;
@ -186,12 +187,11 @@ final class PromotedPropertyCandidateResolver
$isAllFullyQualifiedObjectType = true;
if ($propertyType instanceof UnionType) {
foreach ($propertyType->getTypes() as $type) {
if (! $type instanceof FullyQualifiedObjectType) {
$isAllFullyQualifiedObjectType = false;
break;
}
if ($this->hasGenericTemplateType($propertyType)) {
return false;
}
$isAllFullyQualifiedObjectType = ! $this->hasNonFullyQualifiedObjectType($propertyType);
}
// different types, not a good to fit
@ -201,6 +201,28 @@ final class PromotedPropertyCandidateResolver
);
}
private function hasNonFullyQualifiedObjectType(UnionType $unionType): bool
{
foreach ($unionType->getTypes() as $type) {
if (! $type instanceof FullyQualifiedObjectType) {
return true;
}
}
return false;
}
private function hasGenericTemplateType(UnionType $unionType): bool
{
foreach ($unionType->getTypes() as $type) {
if ($type instanceof TemplateType) {
return true;
}
}
return false;
}
/**
* @param int[] $firstParamAsVariable
*/
@ -215,12 +237,12 @@ final class PromotedPropertyCandidateResolver
return true;
}
// @todo unknown type, not suitable?
$propertyType = $this->propertyTypeInferer->inferProperty($property);
if ($this->hasConflictingParamType($matchedParam, $propertyType)) {
if ($this->isParamUsedBeforeAssign($assignedVariable, $firstParamAsVariable)) {
return true;
}
return $this->isParamUsedBeforeAssign($assignedVariable, $firstParamAsVariable);
// @todo unknown type, not suitable?
$propertyType = $this->propertyTypeInferer->inferProperty($property);
return $this->hasConflictingParamType($matchedParam, $propertyType);
}
}