[TypedPropertyRector] Handle nullable collection on TypedPropertyRector (#986)

* [TypedPropertyRector] Handle nullable collection on TypedPropertyRector

* [ci-review] Rector Rectify

* patch

* fix

* clean up

* Fix

Co-authored-by: GitHub Action <action@github.com>
This commit is contained in:
Abdul Malik Ikhsan 2021-10-11 13:31:02 +07:00 committed by GitHub
parent f6d00371f9
commit 65c3a44c63
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 74 additions and 3 deletions

View File

@ -196,7 +196,7 @@ final class UnionTypeMapper implements TypeMapperInterface
}
/**
* @return Name|FullyQualified|PhpParserUnionType|null
* @return Name|FullyQualified|PhpParserUnionType|NullableType|null
*/
private function matchTypeForUnionedObjectTypes(UnionType $unionType, TypeKind $typeKind): ?Node
{
@ -222,8 +222,20 @@ final class UnionTypeMapper implements TypeMapperInterface
return new Name('bool');
}
return $this->processResolveCompatibleObjectCandidates($unionType);
}
private function processResolveCompatibleObjectCandidates(UnionType $unionType): ?Node
{
// the type should be compatible with all other types, e.g. A extends B, B
$compatibleObjectType = $this->resolveCompatibleObjectCandidate($unionType);
if ($compatibleObjectType instanceof UnionType) {
$type = $this->matchTypeForNullableUnionType($compatibleObjectType);
if ($type instanceof ObjectType) {
return new NullableType(new FullyQualified($type->getClassName()));
}
}
if (! $compatibleObjectType instanceof ObjectType) {
return null;
}
@ -258,10 +270,24 @@ final class UnionTypeMapper implements TypeMapperInterface
return new PhpParserUnionType($phpParserUnionedTypes);
}
private function resolveCompatibleObjectCandidate(UnionType $unionType): ?TypeWithClassName
private function isNullable(UnionType $unionType): bool
{
foreach ($unionType->getTypes() as $type) {
if ($type instanceof NullType) {
return true;
}
}
return false;
}
private function resolveCompatibleObjectCandidate(UnionType $unionType): UnionType|TypeWithClassName|null
{
if ($this->doctrineTypeAnalyzer->isDoctrineCollectionWithIterableUnionType($unionType)) {
return new ObjectType('Doctrine\Common\Collections\Collection');
$objectType = new ObjectType('Doctrine\Common\Collections\Collection');
return $this->isNullable($unionType)
? new UnionType([new NullType(), $objectType])
: $objectType;
}
if (! $this->unionTypeAnalyzer->hasTypeClassNameOnly($unionType)) {

View File

@ -0,0 +1,45 @@
<?php
namespace Rector\Tests\Php74\Rector\Property\TypedPropertyRector\FixtureClassLikeTypeOnly;
use Doctrine\ORM\Mapping as ORM;
class Loc
{
/**
* @ORM\OneToMany(targetEntity=Loc::class, mappedBy="parent", cascade={"persist", "remove"}, fetch="LAZY")
*/
private $children;
public function setChildren($children)
{
$this->children = $children;
return $this;
}
}
?>
-----
<?php
namespace Rector\Tests\Php74\Rector\Property\TypedPropertyRector\FixtureClassLikeTypeOnly;
use Doctrine\ORM\Mapping as ORM;
class Loc
{
/**
* @ORM\OneToMany(targetEntity=Loc::class, mappedBy="parent", cascade={"persist", "remove"}, fetch="LAZY")
*/
private ?\Doctrine\Common\Collections\Collection $children = null;
public function setChildren($children)
{
$this->children = $children;
return $this;
}
}
?>