Updated Rector to commit 22915933d05f2a3e38355cd150ec67401a0fe3b9

22915933d0 [automated] Apply Coding Standard (#6627)
This commit is contained in:
Tomas Votruba 2024-12-24 01:25:19 +00:00
parent 0aa5d110fd
commit b40bc10c7c
8 changed files with 159 additions and 14 deletions

View File

@ -1691,12 +1691,12 @@
"source": {
"type": "git",
"url": "https:\/\/github.com\/rectorphp\/rector-doctrine.git",
"reference": "1523ce5841f90a9b76c454410d7f6495640f5248"
"reference": "f740789641b7a6f7e58397a88725a73ca1402d61"
},
"dist": {
"type": "zip",
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-doctrine\/zipball\/1523ce5841f90a9b76c454410d7f6495640f5248",
"reference": "1523ce5841f90a9b76c454410d7f6495640f5248",
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-doctrine\/zipball\/f740789641b7a6f7e58397a88725a73ca1402d61",
"reference": "f740789641b7a6f7e58397a88725a73ca1402d61",
"shasum": ""
},
"require": {
@ -1719,7 +1719,7 @@
"tomasvotruba\/class-leak": "^2.0",
"tracy\/tracy": "^2.10"
},
"time": "2024-12-21T00:29:21+00:00",
"time": "2024-12-24T01:21:32+00:00",
"default-branch": true,
"type": "rector-extension",
"extra": {

File diff suppressed because one or more lines are too long

View File

@ -9,7 +9,7 @@ namespace Rector\RectorInstaller;
*/
final class GeneratedConfig
{
public const EXTENSIONS = array('rector/rector-doctrine' => array('install_path' => '/home/runner/work/rector-src/rector-src/rector-build/vendor/rector/rector-doctrine', 'relative_install_path' => '../../rector-doctrine', 'extra' => NULL, 'version' => 'dev-main 1523ce5'), 'rector/rector-downgrade-php' => array('install_path' => '/home/runner/work/rector-src/rector-src/rector-build/vendor/rector/rector-downgrade-php', 'relative_install_path' => '../../rector-downgrade-php', 'extra' => NULL, 'version' => 'dev-main 183795c'), 'rector/rector-phpunit' => array('install_path' => '/home/runner/work/rector-src/rector-src/rector-build/vendor/rector/rector-phpunit', 'relative_install_path' => '../../rector-phpunit', 'extra' => NULL, 'version' => 'dev-main bd24ae1'), 'rector/rector-symfony' => array('install_path' => '/home/runner/work/rector-src/rector-src/rector-build/vendor/rector/rector-symfony', 'relative_install_path' => '../../rector-symfony', 'extra' => NULL, 'version' => 'dev-main 29a1abf'));
public const EXTENSIONS = array('rector/rector-doctrine' => array('install_path' => '/home/runner/work/rector-src/rector-src/rector-build/vendor/rector/rector-doctrine', 'relative_install_path' => '../../rector-doctrine', 'extra' => NULL, 'version' => 'dev-main f740789'), 'rector/rector-downgrade-php' => array('install_path' => '/home/runner/work/rector-src/rector-src/rector-build/vendor/rector/rector-downgrade-php', 'relative_install_path' => '../../rector-downgrade-php', 'extra' => NULL, 'version' => 'dev-main 183795c'), 'rector/rector-phpunit' => array('install_path' => '/home/runner/work/rector-src/rector-src/rector-build/vendor/rector/rector-phpunit', 'relative_install_path' => '../../rector-phpunit', 'extra' => NULL, 'version' => 'dev-main bd24ae1'), 'rector/rector-symfony' => array('install_path' => '/home/runner/work/rector-src/rector-src/rector-build/vendor/rector/rector-symfony', 'relative_install_path' => '../../rector-symfony', 'extra' => NULL, 'version' => 'dev-main 29a1abf'));
private function __construct()
{
}

View File

@ -135,7 +135,7 @@ CODE_SAMPLE
}
// update docblock with known collection type
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($classMethod);
$newVarType = $this->collectionTypeFactory->createType($collectionObjectType, $this->collectionTypeResolver->hasIndexBy($property));
$newVarType = $this->collectionTypeFactory->createType($collectionObjectType, $this->collectionTypeResolver->hasIndexBy($property), $property);
$this->phpDocTypeChanger->changeReturnType($classMethod, $phpDocInfo, $newVarType);
$hasChanged = \true;
}

View File

@ -197,14 +197,14 @@ CODE_SAMPLE
if (!$collectionObjectType instanceof FullyQualifiedObjectType) {
return null;
}
$newVarType = $this->collectionTypeFactory->createType($collectionObjectType, $this->collectionTypeResolver->hasIndexBy($property));
$newVarType = $this->collectionTypeFactory->createType($collectionObjectType, $this->collectionTypeResolver->hasIndexBy($property), $property);
$this->phpDocTypeChanger->changeVarType($property, $phpDocInfo, $newVarType);
} else {
$collectionObjectType = $this->collectionTypeResolver->resolveFromToManyProperty($property);
if (!$collectionObjectType instanceof FullyQualifiedObjectType) {
return null;
}
$newVarType = $this->collectionTypeFactory->createType($collectionObjectType, $this->collectionTypeResolver->hasIndexBy($property));
$newVarType = $this->collectionTypeFactory->createType($collectionObjectType, $this->collectionTypeResolver->hasIndexBy($property), $property);
$this->phpDocTypeChanger->changeVarType($property, $phpDocInfo, $newVarType);
}
return $property;
@ -226,7 +226,7 @@ CODE_SAMPLE
return null;
}
$fullyQualifiedObjectType = new FullyQualifiedObjectType($targetEntityClassName);
$genericObjectType = $this->collectionTypeFactory->createType($fullyQualifiedObjectType, $this->collectionTypeResolver->hasIndexBy($property));
$genericObjectType = $this->collectionTypeFactory->createType($fullyQualifiedObjectType, $this->collectionTypeResolver->hasIndexBy($property), $property);
$this->phpDocTypeChanger->changeVarType($property, $phpDocInfo, $genericObjectType);
return $property;
}

View File

@ -94,7 +94,7 @@ final class SetterCollectionResolver
if (\count($nonCollectionTypes) === 1) {
$soleType = $nonCollectionTypes[0];
if ($soleType instanceof ArrayType && $soleType->getItemType() instanceof ObjectType) {
return $this->collectionTypeFactory->createType($soleType->getItemType(), $this->collectionTypeResolver->hasIndexBy($property));
return $this->collectionTypeFactory->createType($soleType->getItemType(), $this->collectionTypeResolver->hasIndexBy($property), $property);
}
}
}

View File

@ -98,6 +98,6 @@ final class ToManyRelationPropertyTypeResolver
}
$entityFullyQualifiedClass = $this->shortClassExpander->resolveFqnTargetEntity($targetEntity, $property);
$fullyQualifiedObjectType = new FullyQualifiedObjectType($entityFullyQualifiedClass);
return $this->collectionTypeFactory->createType($fullyQualifiedObjectType, $this->collectionTypeResolver->hasIndexBy($property));
return $this->collectionTypeFactory->createType($fullyQualifiedObjectType, $this->collectionTypeResolver->hasIndexBy($property), $property);
}
}

View File

@ -3,14 +3,159 @@
declare (strict_types=1);
namespace Rector\Doctrine\TypeAnalyzer;
use PhpParser\Node\Identifier;
use PhpParser\Node\Param;
use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\Property;
use PHPStan\Type\Generic\GenericObjectType;
use PHPStan\Type\IntegerType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\StringType;
use PHPStan\Type\Type;
use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode;
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
use Rector\BetterPhpDocParser\PhpDoc\StringNode;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
use Rector\PhpParser\AstResolver;
use Rector\PhpParser\Node\Value\ValueResolver;
final class CollectionTypeFactory
{
public function createType(ObjectType $objectType, bool $withIndexBy) : GenericObjectType
/**
* @readonly
*/
private PhpDocInfoFactory $phpDocInfoFactory;
/**
* @readonly
*/
private AstResolver $astResolver;
/**
* @readonly
*/
private ValueResolver $valueResolver;
public function __construct(PhpDocInfoFactory $phpDocInfoFactory, AstResolver $astResolver, ValueResolver $valueResolver)
{
$genericTypes = $withIndexBy ? [$objectType] : [new IntegerType(), $objectType];
$this->phpDocInfoFactory = $phpDocInfoFactory;
$this->astResolver = $astResolver;
$this->valueResolver = $valueResolver;
}
/**
* @param \PhpParser\Node\Stmt\Property|\PhpParser\Node\Param $property
*/
public function createType(ObjectType $objectType, bool $withIndexBy, $property) : GenericObjectType
{
$keyType = new IntegerType();
if ($withIndexBy) {
$keyType = $this->resolveKeyType($property, $objectType->getClassName());
}
$genericTypes = [$keyType, $objectType];
return new GenericObjectType('Doctrine\\Common\\Collections\\Collection', $genericTypes);
}
/**
* @param \PhpParser\Node\Stmt\Property|\PhpParser\Node\Param $property
* @return \PHPStan\Type\IntegerType|\PHPStan\Type\StringType
*/
private function resolveKeyType($property, string $className)
{
$class = $this->astResolver->resolveClassFromName($className);
if (!$class instanceof Class_) {
return new IntegerType();
}
$phpDocInfo = $this->phpDocInfoFactory->createFromNode($property);
// key need to be initialized here
// so it can be checked in target class annotation or attribute
$key = null;
if ($phpDocInfo instanceof PhpDocInfo) {
// only on OneToMany and ManyToMany
// https://www.doctrine-project.org/projects/doctrine-orm/en/3.3/tutorials/working-with-indexed-associations.html#mapping-indexed-associations
$annotations = $phpDocInfo->findByAnnotationClass('Doctrine\\ORM\\Mapping\\OneToMany') !== [] ? $phpDocInfo->findByAnnotationClass('Doctrine\\ORM\\Mapping\\OneToMany') : $phpDocInfo->findByAnnotationClass('Doctrine\\ORM\\Mapping\\ManyToMany');
if (\count($annotations) === 1 && $annotations[0] instanceof DoctrineAnnotationTagValueNode) {
foreach ($annotations[0]->getValues() as $arrayItemNode) {
if ($arrayItemNode instanceof ArrayItemNode && $arrayItemNode->key instanceof StringNode && $arrayItemNode->key->value === 'indexBy' && $arrayItemNode->value instanceof StringNode) {
$key = $arrayItemNode->value->value;
break;
}
}
if ($key !== null) {
$type = $this->resolveKeyFromAnnotation($class, $key);
if ($type instanceof Type) {
return $type;
}
}
}
}
$attrGroups = $property->attrGroups;
foreach ($attrGroups as $attrGroup) {
foreach ($attrGroup->attrs as $attr) {
if (\in_array($attr->name->toString(), ['Doctrine\\ORM\\Mapping\\OneToMany', 'Doctrine\\ORM\\Mapping\\ManyToMany'], \true)) {
foreach ($attr->args as $arg) {
if ($arg->name instanceof Identifier && $arg->name->name === 'indexBy' && $arg->value instanceof String_) {
$key = $arg->value->value;
$type = $this->resolveKeyFromAnnotation($class, $key);
if ($type instanceof Type) {
return $type;
}
break;
}
}
}
}
}
if ($key !== null) {
return $this->resolveKeyFromAttribute($class, $key);
}
return new IntegerType();
}
/**
* @return null|\PHPStan\Type\IntegerType|\PHPStan\Type\StringType
*/
private function resolveKeyFromAnnotation(Class_ $class, string $key)
{
// get property from class
$targetProperty = $class->getProperty($key);
if (!$targetProperty instanceof Property) {
return new IntegerType();
}
$phpDocInfoTargetClass = $this->phpDocInfoFactory->createFromNode($targetProperty);
if ($phpDocInfoTargetClass instanceof PhpDocInfo) {
$columns = $phpDocInfoTargetClass->findByAnnotationClass('Doctrine\\ORM\\Mapping\\Column');
if (\count($columns) === 1 && $columns[0] instanceof DoctrineAnnotationTagValueNode) {
$type = null;
foreach ($columns[0]->getValues() as $arrayItemNode) {
if ($arrayItemNode instanceof ArrayItemNode && $arrayItemNode->key === 'type' && $arrayItemNode->value instanceof StringNode) {
$type = $arrayItemNode->value->value;
break;
}
}
return $type === null ? new IntegerType() : ($type === 'string' ? new StringType() : new IntegerType());
}
}
return null;
}
/**
* @return \PHPStan\Type\IntegerType|\PHPStan\Type\StringType
*/
private function resolveKeyFromAttribute(Class_ $class, string $key)
{
// get property from class
$targetProperty = $class->getProperty($key);
if (!$targetProperty instanceof Property) {
return new IntegerType();
}
$attrGroups = $targetProperty->attrGroups;
foreach ($attrGroups as $attrGroup) {
foreach ($attrGroup->attrs as $attr) {
if ($attr->name->toString() === 'Doctrine\\ORM\\Mapping\\Column') {
foreach ($attr->args as $arg) {
if ($arg->name instanceof Identifier && $arg->name->name === 'type') {
$type = $this->valueResolver->getValue($arg->value);
return $type === 'string' ? new StringType() : new IntegerType();
}
}
}
}
}
return new IntegerType();
}
}