diff --git a/rules-tests/CodeQuality/Rector/Property/ImproveDoctrineCollectionDocTypeInEntityRector/Fixture/OneToMany/var_and_attribute.php.inc b/rules-tests/CodeQuality/Rector/Property/ImproveDoctrineCollectionDocTypeInEntityRector/Fixture/OneToMany/var_and_attribute.php.inc index d8b12065..85cb54a6 100644 --- a/rules-tests/CodeQuality/Rector/Property/ImproveDoctrineCollectionDocTypeInEntityRector/Fixture/OneToMany/var_and_attribute.php.inc +++ b/rules-tests/CodeQuality/Rector/Property/ImproveDoctrineCollectionDocTypeInEntityRector/Fixture/OneToMany/var_and_attribute.php.inc @@ -35,14 +35,11 @@ use Rector\Doctrine\Tests\CodeQuality\Rector\Property\ImproveDoctrineCollectionD class VarAndAttribute { /** - * @var Collection + * @var \Doctrine\Common\Collections\Collection */ #[ORM\OneToMany(targetEntity:Training::class, mappedBy:"trainer")] private $trainings = []; - /** - * @param Collection|\Training[] $trainings - */ public function setTrainings($trainings) { $this->trainings = $trainings; diff --git a/rules/CodeQuality/Rector/Property/ImproveDoctrineCollectionDocTypeInEntityRector.php b/rules/CodeQuality/Rector/Property/ImproveDoctrineCollectionDocTypeInEntityRector.php index fc71d0b0..7d6eab2b 100644 --- a/rules/CodeQuality/Rector/Property/ImproveDoctrineCollectionDocTypeInEntityRector.php +++ b/rules/CodeQuality/Rector/Property/ImproveDoctrineCollectionDocTypeInEntityRector.php @@ -126,6 +126,7 @@ private function refactorProperty(Property $property): ?Property CollectionMapping::TO_MANY_CLASSES, 'targetEntity' ); + if (! $targetEntityExpr instanceof Expr) { return null; } @@ -240,14 +241,24 @@ private function refactorPropertyPhpDocInfo(Property $property, PhpDocInfo $phpD private function refactorAttribute(Expr $expr, PhpDocInfo $phpDocInfo, Property $property): ?Property { - $phpDocVarTagValueNode = $phpDocInfo->getVarTagValueNode(); - $phpDocCollectionVarTagValueNode = $this->collectionVarTagValueNodeResolver->resolve($property); - if ($phpDocVarTagValueNode instanceof VarTagValueNode && ! $phpDocCollectionVarTagValueNode instanceof VarTagValueNode) { - return null; + $toManyAttribute = $this->attributeFinder->findAttributeByClasses( + $property, + CollectionMapping::TO_MANY_CLASSES + ); + if ($toManyAttribute instanceof Node\Attribute) { + $targetEntityClassName = $this->targetEntityResolver->resolveFromAttribute($toManyAttribute); + } else { + $phpDocVarTagValueNode = $phpDocInfo->getVarTagValueNode(); + $phpDocCollectionVarTagValueNode = $this->collectionVarTagValueNodeResolver->resolve($property); + + if ($phpDocVarTagValueNode instanceof VarTagValueNode && ! $phpDocCollectionVarTagValueNode instanceof VarTagValueNode) { + return null; + } + + $targetEntityClassName = $this->targetEntityResolver->resolveFromExpr($expr); } - $targetEntityClassName = $this->targetEntityResolver->resolveFromExpr($expr); if ($targetEntityClassName === null) { return null; } diff --git a/src/NodeAnalyzer/TargetEntityResolver.php b/src/NodeAnalyzer/TargetEntityResolver.php index a7120da5..ef7c0f4c 100644 --- a/src/NodeAnalyzer/TargetEntityResolver.php +++ b/src/NodeAnalyzer/TargetEntityResolver.php @@ -4,8 +4,10 @@ namespace Rector\Doctrine\NodeAnalyzer; +use PhpParser\Node\Attribute; use PhpParser\Node\Expr; use PhpParser\Node\Expr\ClassConstFetch; +use PhpParser\Node\Identifier; use PhpParser\Node\Scalar\String_; use PHPStan\Reflection\ReflectionProvider; use Rector\Exception\NotImplementedYetException; @@ -19,6 +21,23 @@ public function __construct( ) { } + public function resolveFromAttribute(Attribute $attribute): ?string + { + foreach ($attribute->args as $arg) { + if (! $arg->name instanceof Identifier) { + continue; + } + + if ($arg->name->toString() !== 'targetEntity') { + continue; + } + + return $this->resolveFromExpr($arg->value); + } + + return null; + } + public function resolveFromExpr(Expr $targetEntityExpr): string|null { if ($targetEntityExpr instanceof ClassConstFetch) {