mirror of
https://github.com/rectorphp/rector.git
synced 2024-06-30 14:43:31 +00:00
make use of Types of doc types (#4444)
This commit is contained in:
parent
26ab509d7a
commit
f96372e1c0
|
@ -337,9 +337,9 @@ final class PhpDocInfo
|
|||
return $paramTypesByName;
|
||||
}
|
||||
|
||||
public function changeVarType(Type $newType): void
|
||||
public function changeVarType(Type $type): void
|
||||
{
|
||||
$this->phpDocTypeChanger->changeVarType($this, $newType);
|
||||
$this->phpDocTypeChanger->changeVarType($this, $type);
|
||||
}
|
||||
|
||||
public function changeReturnType(Type $newType): void
|
||||
|
|
|
@ -7,6 +7,7 @@ namespace Rector\NodeTypeResolver\PHPStan;
|
|||
use PHPStan\ShouldNotHappenException;
|
||||
use PHPStan\Type\ArrayType;
|
||||
use PHPStan\Type\ConstantType;
|
||||
use PHPStan\Type\Generic\GenericObjectType;
|
||||
use PHPStan\Type\MixedType;
|
||||
use PHPStan\Type\Type;
|
||||
use PHPStan\Type\TypeWithClassName;
|
||||
|
@ -40,6 +41,10 @@ final class TypeHasher
|
|||
return $type->getFullyQualifiedName();
|
||||
}
|
||||
|
||||
if ($type instanceof GenericObjectType) {
|
||||
return $this->phpStanStaticTypeMapper->mapToDocString($type);
|
||||
}
|
||||
|
||||
if ($type instanceof TypeWithClassName) {
|
||||
return $type->getClassName();
|
||||
}
|
||||
|
|
|
@ -4,31 +4,28 @@ declare(strict_types=1);
|
|||
|
||||
namespace Rector\DoctrineCodeQuality\PhpDoc;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\Type\GenericTypeNode;
|
||||
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\Type\AttributeAwareArrayTypeNode;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\Type\AttributeAwareFullyQualifiedIdentifierTypeNode;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\Type\AttributeAwareIdentifierTypeNode;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\Type\AttributeAwareUnionTypeNode;
|
||||
use PHPStan\Type\ArrayType;
|
||||
use PHPStan\Type\Generic\GenericObjectType;
|
||||
use PHPStan\Type\IntegerType;
|
||||
use PHPStan\Type\MixedType;
|
||||
use PHPStan\Type\Type;
|
||||
use PHPStan\Type\UnionType;
|
||||
use Rector\PHPStan\Type\FullyQualifiedObjectType;
|
||||
|
||||
final class CollectionTypeFactory
|
||||
{
|
||||
public function createFromIdentifierType(IdentifierTypeNode $identifierTypeNode): AttributeAwareUnionTypeNode
|
||||
public function createType(FullyQualifiedObjectType $fullyQualifiedObjectType): UnionType
|
||||
{
|
||||
$genericTypeNode = $this->createGenericTypeNode($identifierTypeNode);
|
||||
$genericType = $this->createGenericObjectType($fullyQualifiedObjectType);
|
||||
$arrayType = new ArrayType(new MixedType(), $fullyQualifiedObjectType);
|
||||
|
||||
return new AttributeAwareUnionTypeNode([
|
||||
$genericTypeNode,
|
||||
new AttributeAwareArrayTypeNode($identifierTypeNode),
|
||||
]);
|
||||
return new UnionType([$genericType, $arrayType]);
|
||||
}
|
||||
|
||||
private function createGenericTypeNode(IdentifierTypeNode $identifierTypeNode): GenericTypeNode
|
||||
private function createGenericObjectType(FullyQualifiedObjectType $fullyQualifiedObjectType): Type
|
||||
{
|
||||
$genericTypesNodes = [new AttributeAwareIdentifierTypeNode('int'), $identifierTypeNode];
|
||||
$genericTypes = [new IntegerType(), $fullyQualifiedObjectType];
|
||||
|
||||
return new GenericTypeNode(new AttributeAwareFullyQualifiedIdentifierTypeNode(
|
||||
'Doctrine\Common\Collections\Collection'
|
||||
), $genericTypesNodes);
|
||||
return new GenericObjectType('Doctrine\Common\Collections\Collection', $genericTypes);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,37 +4,52 @@ declare(strict_types=1);
|
|||
|
||||
namespace Rector\DoctrineCodeQuality\PhpDoc;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Stmt\Property;
|
||||
use PHPStan\PhpDocParser\Ast\Type\ArrayTypeNode;
|
||||
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
|
||||
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
|
||||
use PHPStan\PhpDocParser\Ast\Type\UnionTypeNode;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\Type\AttributeAwareIdentifierTypeNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
use Rector\BetterPhpDocParser\PhpDocNode\Doctrine\Property_\OneToManyTagValueNode;
|
||||
use Rector\Core\Exception\ShouldNotHappenException;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\PHPStan\Type\FullyQualifiedObjectType;
|
||||
use Rector\StaticTypeMapper\PHPStan\NameScopeFactory;
|
||||
|
||||
final class CollectionTypeResolver
|
||||
{
|
||||
public function resolveFromType(TypeNode $typeNode): ?IdentifierTypeNode
|
||||
/**
|
||||
* @var NameScopeFactory
|
||||
*/
|
||||
private $nameScopeFactory;
|
||||
|
||||
public function __construct(NameScopeFactory $nameScopeFactory)
|
||||
{
|
||||
$this->nameScopeFactory = $nameScopeFactory;
|
||||
}
|
||||
|
||||
public function resolveFromTypeNode(TypeNode $typeNode, Node $node): ?FullyQualifiedObjectType
|
||||
{
|
||||
if ($typeNode instanceof UnionTypeNode) {
|
||||
foreach ($typeNode->types as $unionedTypeNode) {
|
||||
if ($this->resolveFromType($unionedTypeNode) !== null) {
|
||||
return $this->resolveFromType($unionedTypeNode);
|
||||
$resolvedUnionedType = $this->resolveFromTypeNode($unionedTypeNode, $node);
|
||||
if ($resolvedUnionedType !== null) {
|
||||
return $resolvedUnionedType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($typeNode instanceof ArrayTypeNode && $typeNode->type instanceof IdentifierTypeNode) {
|
||||
return $typeNode->type;
|
||||
$nameScope = $this->nameScopeFactory->createNameScopeFromNode($node);
|
||||
$fullyQualifiedName = $nameScope->resolveStringName($typeNode->type->name);
|
||||
return new FullyQualifiedObjectType($fullyQualifiedName);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function resolveFromOneToManyProperty(Property $property): ?IdentifierTypeNode
|
||||
public function resolveFromOneToManyProperty(Property $property): ?FullyQualifiedObjectType
|
||||
{
|
||||
$phpDocInfo = $property->getAttribute(AttributeKey::PHP_DOC_INFO);
|
||||
if (! $phpDocInfo instanceof PhpDocInfo) {
|
||||
|
@ -51,6 +66,6 @@ final class CollectionTypeResolver
|
|||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
return new AttributeAwareIdentifierTypeNode($fullyQualifiedTargetEntity);
|
||||
return new FullyQualifiedObjectType($fullyQualifiedTargetEntity);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ use PhpParser\Node\Stmt\Class_;
|
|||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PhpParser\Node\Stmt\Property;
|
||||
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwareVarTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
use Rector\BetterPhpDocParser\PhpDocNode\Doctrine\Property_\OneToManyTagValueNode;
|
||||
use Rector\Core\PhpParser\Node\Manipulator\AssignManipulator;
|
||||
|
@ -139,27 +138,25 @@ CODE_SAMPLE
|
|||
|
||||
$attributeAwareVarTagValueNode = $this->collectionVarTagValueNodeResolver->resolve($property);
|
||||
if ($attributeAwareVarTagValueNode !== null) {
|
||||
$collectionObjectType = $this->collectionTypeResolver->resolveFromType(
|
||||
$attributeAwareVarTagValueNode->type
|
||||
$collectionObjectType = $this->collectionTypeResolver->resolveFromTypeNode(
|
||||
$attributeAwareVarTagValueNode->type,
|
||||
$property
|
||||
);
|
||||
|
||||
if ($collectionObjectType === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$attributeAwareVarTagValueNode->type = $this->collectionTypeFactory->createFromIdentifierType(
|
||||
$collectionObjectType
|
||||
);
|
||||
$newVarType = $this->collectionTypeFactory->createType($collectionObjectType);
|
||||
$phpDocInfo->changeVarType($newVarType);
|
||||
} else {
|
||||
$collectionObjectType = $this->collectionTypeResolver->resolveFromOneToManyProperty($property);
|
||||
if ($collectionObjectType === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$attributeAwareUnionTypeNode = $this->collectionTypeFactory->createFromIdentifierType(
|
||||
$collectionObjectType
|
||||
);
|
||||
$attributeAwareVarTagValueNode = new AttributeAwareVarTagValueNode($attributeAwareUnionTypeNode, '', '');
|
||||
$phpDocInfo->addTagValueNode($attributeAwareVarTagValueNode);
|
||||
$newVarType = $this->collectionTypeFactory->createType($collectionObjectType);
|
||||
$phpDocInfo->changeVarType($newVarType);
|
||||
}
|
||||
|
||||
return $property;
|
||||
|
|
|
@ -4,6 +4,7 @@ namespace Rector\DoctrineCodeQuality\Tests\Rector\Property\ImproveDoctrineCollec
|
|||
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Rector\DoctrineCodeQuality\Tests\Rector\Property\ImproveDoctrineCollectionDocTypeInEntityRector\Source\Training;
|
||||
|
||||
/**
|
||||
* @ORM\Entity
|
||||
|
@ -24,6 +25,7 @@ namespace Rector\DoctrineCodeQuality\Tests\Rector\Property\ImproveDoctrineCollec
|
|||
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Rector\DoctrineCodeQuality\Tests\Rector\Property\ImproveDoctrineCollectionDocTypeInEntityRector\Source\Training;
|
||||
|
||||
/**
|
||||
* @ORM\Entity
|
||||
|
@ -32,7 +34,7 @@ class NoVar
|
|||
{
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity=Training::class, mappedBy="trainer")
|
||||
* @var \Doctrine\Common\Collections\Collection<int, Training>|Training[]
|
||||
* @var \Rector\DoctrineCodeQuality\Tests\Rector\Property\ImproveDoctrineCollectionDocTypeInEntityRector\Source\Training[]|\Doctrine\Common\Collections\Collection<int, \Rector\DoctrineCodeQuality\Tests\Rector\Property\ImproveDoctrineCollectionDocTypeInEntityRector\Source\Training>
|
||||
*/
|
||||
private $trainings = [];
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ namespace Rector\DoctrineCodeQuality\Tests\Rector\Property\ImproveDoctrineCollec
|
|||
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Rector\DoctrineCodeQuality\Tests\Rector\Property\ImproveDoctrineCollectionDocTypeInEntityRector\Source\Training;
|
||||
|
||||
/**
|
||||
* @ORM\Entity
|
||||
|
@ -32,6 +33,7 @@ namespace Rector\DoctrineCodeQuality\Tests\Rector\Property\ImproveDoctrineCollec
|
|||
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Rector\DoctrineCodeQuality\Tests\Rector\Property\ImproveDoctrineCollectionDocTypeInEntityRector\Source\Training;
|
||||
|
||||
/**
|
||||
* @ORM\Entity
|
||||
|
@ -40,12 +42,12 @@ class ParamWithoutArray
|
|||
{
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity=Training::class, mappedBy="trainer")
|
||||
* @var \Doctrine\Common\Collections\Collection<int, Training>|Training[]
|
||||
* @var \Rector\DoctrineCodeQuality\Tests\Rector\Property\ImproveDoctrineCollectionDocTypeInEntityRector\Source\Training[]|\Doctrine\Common\Collections\Collection<int, \Rector\DoctrineCodeQuality\Tests\Rector\Property\ImproveDoctrineCollectionDocTypeInEntityRector\Source\Training>
|
||||
*/
|
||||
private $trainings = [];
|
||||
|
||||
/**
|
||||
* @param \Doctrine\Common\Collections\Collection<int, Training>|Training[] $collection
|
||||
* @param \Rector\DoctrineCodeQuality\Tests\Rector\Property\ImproveDoctrineCollectionDocTypeInEntityRector\Source\Training[]|\Doctrine\Common\Collections\Collection<int, \Rector\DoctrineCodeQuality\Tests\Rector\Property\ImproveDoctrineCollectionDocTypeInEntityRector\Source\Training> $collection
|
||||
*/
|
||||
public function setTrainings($collection): void
|
||||
{
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\DoctrineCodeQuality\Tests\Rector\Property\ImproveDoctrineCollectionDocTypeInEntityRector\Fixture;
|
||||
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Rector\DoctrineCodeQuality\Tests\Rector\Property\ImproveDoctrineCollectionDocTypeInEntityRector\Source\Training;
|
||||
|
||||
/**
|
||||
* @ORM\Entity
|
||||
*/
|
||||
class SkipAlready
|
||||
{
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity=Training::class, mappedBy="trainer")
|
||||
* @var Collection<int, Training>|Training[]
|
||||
*/
|
||||
private $trainings = [];
|
||||
}
|
|
@ -4,6 +4,7 @@ namespace Rector\DoctrineCodeQuality\Tests\Rector\Property\ImproveDoctrineCollec
|
|||
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Rector\DoctrineCodeQuality\Tests\Rector\Property\ImproveDoctrineCollectionDocTypeInEntityRector\Source\Training;
|
||||
|
||||
/**
|
||||
* @ORM\Entity
|
||||
|
@ -25,6 +26,7 @@ namespace Rector\DoctrineCodeQuality\Tests\Rector\Property\ImproveDoctrineCollec
|
|||
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Rector\DoctrineCodeQuality\Tests\Rector\Property\ImproveDoctrineCollectionDocTypeInEntityRector\Source\Training;
|
||||
|
||||
/**
|
||||
* @ORM\Entity
|
||||
|
@ -33,7 +35,7 @@ class VarSomeClass
|
|||
{
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity=Training::class, mappedBy="trainer")
|
||||
* @var \Doctrine\Common\Collections\Collection<int, Training>|Training[]
|
||||
* @var \Rector\DoctrineCodeQuality\Tests\Rector\Property\ImproveDoctrineCollectionDocTypeInEntityRector\Source\Training[]|\Doctrine\Common\Collections\Collection<int, \Rector\DoctrineCodeQuality\Tests\Rector\Property\ImproveDoctrineCollectionDocTypeInEntityRector\Source\Training>
|
||||
*/
|
||||
private $trainings = [];
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
namespace Rector\DoctrineCodeQuality\Tests\Rector\Property\ImproveDoctrineCollectionDocTypeInEntityRector\Fixture;
|
||||
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Rector\DoctrineCodeQuality\Tests\Rector\Property\ImproveDoctrineCollectionDocTypeInEntityRector\Source\Training;
|
||||
|
||||
/**
|
||||
* @ORM\Entity
|
||||
|
@ -23,8 +23,8 @@ class VarWithoutArray
|
|||
|
||||
namespace Rector\DoctrineCodeQuality\Tests\Rector\Property\ImproveDoctrineCollectionDocTypeInEntityRector\Fixture;
|
||||
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Rector\DoctrineCodeQuality\Tests\Rector\Property\ImproveDoctrineCollectionDocTypeInEntityRector\Source\Training;
|
||||
|
||||
/**
|
||||
* @ORM\Entity
|
||||
|
@ -33,7 +33,7 @@ class VarWithoutArray
|
|||
{
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity=Training::class, mappedBy="trainer")
|
||||
* @var \Doctrine\Common\Collections\Collection<int, Training>|Training[]
|
||||
* @var \Rector\DoctrineCodeQuality\Tests\Rector\Property\ImproveDoctrineCollectionDocTypeInEntityRector\Source\Training[]|\Doctrine\Common\Collections\Collection<int, \Rector\DoctrineCodeQuality\Tests\Rector\Property\ImproveDoctrineCollectionDocTypeInEntityRector\Source\Training>
|
||||
*/
|
||||
private $trainings = [];
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace Rector\DoctrineCodeQuality\Tests\Rector\Property\ImproveDoctrineCollectionDocTypeInEntityRector\Fixture;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Rector\DoctrineCodeQuality\Tests\Rector\Property\ImproveDoctrineCollectionDocTypeInEntityRector\Source\Training;
|
||||
|
||||
/**
|
||||
* @ORM\Entity
|
||||
|
@ -23,6 +24,7 @@ class VarWithoutCollection
|
|||
namespace Rector\DoctrineCodeQuality\Tests\Rector\Property\ImproveDoctrineCollectionDocTypeInEntityRector\Fixture;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Rector\DoctrineCodeQuality\Tests\Rector\Property\ImproveDoctrineCollectionDocTypeInEntityRector\Source\Training;
|
||||
|
||||
/**
|
||||
* @ORM\Entity
|
||||
|
@ -31,7 +33,7 @@ class VarWithoutCollection
|
|||
{
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity=Training::class, mappedBy="trainer")
|
||||
* @var \Doctrine\Common\Collections\Collection<int, Training>|Training[]
|
||||
* @var \Rector\DoctrineCodeQuality\Tests\Rector\Property\ImproveDoctrineCollectionDocTypeInEntityRector\Source\Training[]|\Doctrine\Common\Collections\Collection<int, \Rector\DoctrineCodeQuality\Tests\Rector\Property\ImproveDoctrineCollectionDocTypeInEntityRector\Source\Training>
|
||||
*/
|
||||
private $trainings = [];
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\DoctrineCodeQuality\Tests\Rector\Property\ImproveDoctrineCollectionDocTypeInEntityRector\Source;
|
||||
|
||||
final class Training
|
||||
{
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user