From 885ef768e50b8ef86bdf2eb99e290f5dccebd8c1 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 24 Aug 2021 21:44:45 +0700 Subject: [PATCH] [Php80] Handle Generic TemplateType on ClassPropertyAssignToConstructorPromotionRector (#751) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 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 --- .../Fixture/generic.php.inc | 41 +++++++++++++++++++ .../PromotedPropertyCandidateResolver.php | 40 ++++++++++++++---- 2 files changed, 72 insertions(+), 9 deletions(-) create mode 100644 rules-tests/Php80/Rector/Class_/ClassPropertyAssignToConstructorPromotionRector/Fixture/generic.php.inc diff --git a/rules-tests/Php80/Rector/Class_/ClassPropertyAssignToConstructorPromotionRector/Fixture/generic.php.inc b/rules-tests/Php80/Rector/Class_/ClassPropertyAssignToConstructorPromotionRector/Fixture/generic.php.inc new file mode 100644 index 00000000000..4172dfbc3ab --- /dev/null +++ b/rules-tests/Php80/Rector/Class_/ClassPropertyAssignToConstructorPromotionRector/Fixture/generic.php.inc @@ -0,0 +1,41 @@ +value = $value; + } +} +?> +----- + diff --git a/rules/Php80/NodeAnalyzer/PromotedPropertyCandidateResolver.php b/rules/Php80/NodeAnalyzer/PromotedPropertyCandidateResolver.php index 654ca3e9eed..462f6551ed4 100644 --- a/rules/Php80/NodeAnalyzer/PromotedPropertyCandidateResolver.php +++ b/rules/Php80/NodeAnalyzer/PromotedPropertyCandidateResolver.php @@ -12,6 +12,7 @@ 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 @@ private function hasConflictingParamType(Param $param, Type $propertyType): bool $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 @@ private function hasConflictingParamType(Param $param, Type $propertyType): bool ); } + 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 @@ private function shouldSkipParam( 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); } }