Updated Rector to commit b4eb883e9110f50607ce2eed629c237b5e7e7356

b4eb883e91 [DeadCode] Skip isset() from property fetch from docblock on RemoveAlwaysTrueIfConditionRector (#5754)
This commit is contained in:
Tomas Votruba 2024-03-22 00:10:36 +00:00
parent 9811962c70
commit 11b9220a05
11 changed files with 181 additions and 30 deletions

View File

@ -1330,6 +1330,7 @@ return array(
'Rector\\Doctrine\\CodeQuality\\Enum\\ToManyMappings' => $vendorDir . '/rector/rector-doctrine/rules/CodeQuality/Enum/ToManyMappings.php',
'Rector\\Doctrine\\CodeQuality\\Helper\\NodeValueNormalizer' => $vendorDir . '/rector/rector-doctrine/rules/CodeQuality/Helper/NodeValueNormalizer.php',
'Rector\\Doctrine\\CodeQuality\\NodeFactory\\AttributeFactory' => $vendorDir . '/rector/rector-doctrine/rules/CodeQuality/NodeFactory/AttributeFactory.php',
'Rector\\Doctrine\\CodeQuality\\Rector\\Class_\\ExplicitRelationCollectionRector' => $vendorDir . '/rector/rector-doctrine/rules/CodeQuality/Rector/Class_/ExplicitRelationCollectionRector.php',
'Rector\\Doctrine\\CodeQuality\\Rector\\Class_\\InitializeDefaultEntityCollectionRector' => $vendorDir . '/rector/rector-doctrine/rules/CodeQuality/Rector/Class_/InitializeDefaultEntityCollectionRector.php',
'Rector\\Doctrine\\CodeQuality\\Rector\\Class_\\MoveCurrentDateTimeDefaultInEntityToConstructorRector' => $vendorDir . '/rector/rector-doctrine/rules/CodeQuality/Rector/Class_/MoveCurrentDateTimeDefaultInEntityToConstructorRector.php',
'Rector\\Doctrine\\CodeQuality\\Rector\\Class_\\RemoveEmptyTableAttributeRector' => $vendorDir . '/rector/rector-doctrine/rules/CodeQuality/Rector/Class_/RemoveEmptyTableAttributeRector.php',

View File

@ -1549,6 +1549,7 @@ class ComposerStaticInit67be42e0079886f0083b7116ae1de531
'Rector\\Doctrine\\CodeQuality\\Enum\\ToManyMappings' => __DIR__ . '/..' . '/rector/rector-doctrine/rules/CodeQuality/Enum/ToManyMappings.php',
'Rector\\Doctrine\\CodeQuality\\Helper\\NodeValueNormalizer' => __DIR__ . '/..' . '/rector/rector-doctrine/rules/CodeQuality/Helper/NodeValueNormalizer.php',
'Rector\\Doctrine\\CodeQuality\\NodeFactory\\AttributeFactory' => __DIR__ . '/..' . '/rector/rector-doctrine/rules/CodeQuality/NodeFactory/AttributeFactory.php',
'Rector\\Doctrine\\CodeQuality\\Rector\\Class_\\ExplicitRelationCollectionRector' => __DIR__ . '/..' . '/rector/rector-doctrine/rules/CodeQuality/Rector/Class_/ExplicitRelationCollectionRector.php',
'Rector\\Doctrine\\CodeQuality\\Rector\\Class_\\InitializeDefaultEntityCollectionRector' => __DIR__ . '/..' . '/rector/rector-doctrine/rules/CodeQuality/Rector/Class_/InitializeDefaultEntityCollectionRector.php',
'Rector\\Doctrine\\CodeQuality\\Rector\\Class_\\MoveCurrentDateTimeDefaultInEntityToConstructorRector' => __DIR__ . '/..' . '/rector/rector-doctrine/rules/CodeQuality/Rector/Class_/MoveCurrentDateTimeDefaultInEntityToConstructorRector.php',
'Rector\\Doctrine\\CodeQuality\\Rector\\Class_\\RemoveEmptyTableAttributeRector' => __DIR__ . '/..' . '/rector/rector-doctrine/rules/CodeQuality/Rector/Class_/RemoveEmptyTableAttributeRector.php',

View File

@ -1679,12 +1679,12 @@
"source": {
"type": "git",
"url": "https:\/\/github.com\/rectorphp\/rector-doctrine.git",
"reference": "a1d50bb1b3d158961293ef0828fffb1058cdb32f"
"reference": "bbc48ccb87e026a100e86d6dc2a238b1293c14cb"
},
"dist": {
"type": "zip",
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-doctrine\/zipball\/a1d50bb1b3d158961293ef0828fffb1058cdb32f",
"reference": "a1d50bb1b3d158961293ef0828fffb1058cdb32f",
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-doctrine\/zipball\/bbc48ccb87e026a100e86d6dc2a238b1293c14cb",
"reference": "bbc48ccb87e026a100e86d6dc2a238b1293c14cb",
"shasum": ""
},
"require": {
@ -1709,7 +1709,7 @@
"tomasvotruba\/unused-public": "^0.3",
"tracy\/tracy": "^2.10"
},
"time": "2024-03-07T14:21:07+00:00",
"time": "2024-03-22T00:08:11+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 a1d50bb'), '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 eadea25'), '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 6845db4'), '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 c8b6413'));
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 bbc48cc'), '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 eadea25'), '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 6845db4'), '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 c8b6413'));
private function __construct()
{
}

View File

@ -4,7 +4,7 @@ declare (strict_types=1);
namespace RectorPrefix202403;
use Rector\Config\RectorConfig;
use Rector\Doctrine\CodeQuality\Rector\Class_\InitializeDefaultEntityCollectionRector;
use Rector\Doctrine\CodeQuality\Rector\Class_\ExplicitRelationCollectionRector;
use Rector\Doctrine\CodeQuality\Rector\Class_\MoveCurrentDateTimeDefaultInEntityToConstructorRector;
use Rector\Doctrine\CodeQuality\Rector\Class_\RemoveEmptyTableAttributeRector;
use Rector\Doctrine\CodeQuality\Rector\Property\CorrectDefaultTypesOnEntityPropertyRector;
@ -12,24 +12,22 @@ use Rector\Doctrine\CodeQuality\Rector\Property\ImproveDoctrineCollectionDocType
use Rector\Doctrine\CodeQuality\Rector\Property\MakeEntityDateTimePropertyDateTimeInterfaceRector;
use Rector\Doctrine\CodeQuality\Rector\Property\OrderByKeyToClassConstRector;
use Rector\Doctrine\CodeQuality\Rector\Property\TypedPropertyFromColumnTypeRector;
use Rector\Doctrine\CodeQuality\Rector\Property\TypedPropertyFromDoctrineCollectionRector;
use Rector\Doctrine\CodeQuality\Rector\Property\TypedPropertyFromToManyRelationTypeRector;
use Rector\Doctrine\CodeQuality\Rector\Property\TypedPropertyFromToOneRelationTypeRector;
use Rector\Transform\Rector\Attribute\AttributeKeyToClassConstFetchRector;
use Rector\Transform\ValueObject\AttributeKeyToClassConstFetch;
return static function (RectorConfig $rectorConfig) : void {
$rectorConfig->rules([
InitializeDefaultEntityCollectionRector::class,
MakeEntityDateTimePropertyDateTimeInterfaceRector::class,
MoveCurrentDateTimeDefaultInEntityToConstructorRector::class,
CorrectDefaultTypesOnEntityPropertyRector::class,
ExplicitRelationCollectionRector::class,
ImproveDoctrineCollectionDocTypeInEntityRector::class,
RemoveEmptyTableAttributeRector::class,
// typed properties in entities from annotations/attributes
TypedPropertyFromColumnTypeRector::class,
TypedPropertyFromToOneRelationTypeRector::class,
TypedPropertyFromToManyRelationTypeRector::class,
TypedPropertyFromDoctrineCollectionRector::class,
OrderByKeyToClassConstRector::class,
]);
$rectorConfig->ruleWithConfiguration(AttributeKeyToClassConstFetchRector::class, [new AttributeKeyToClassConstFetch('Doctrine\\ORM\\Mapping\\Column', 'type', 'Doctrine\\DBAL\\Types\\Types', ['array' => 'ARRAY', 'ascii_string' => 'ASCII_STRING', 'bigint' => 'BIGINT', 'binary' => 'BINARY', 'blob' => 'BLOB', 'boolean' => 'BOOLEAN', 'date' => 'DATE_MUTABLE', 'date_immutable' => 'DATE_IMMUTABLE', 'dateinterval' => 'DATEINTERVAL', 'datetime' => 'DATETIME_MUTABLE', 'datetime_immutable' => 'DATETIME_IMMUTABLE', 'datetimetz' => 'DATETIMETZ_MUTABLE', 'datetimetz_immutable' => 'DATETIMETZ_IMMUTABLE', 'decimal' => 'DECIMAL', 'float' => 'FLOAT', 'guid' => 'GUID', 'integer' => 'INTEGER', 'json' => 'JSON', 'object' => 'OBJECT', 'simple_array' => 'SIMPLE_ARRAY', 'smallint' => 'SMALLINT', 'string' => 'STRING', 'text' => 'TEXT', 'time' => 'TIME_MUTABLE', 'time_immutable' => 'TIME_IMMUTABLE'])]);

View File

@ -1,4 +1,4 @@
# 18 Rules Overview
# 19 Rules Overview
## ChangeCompositeExpressionAddMultipleWithWithRector
@ -87,6 +87,35 @@ Replace EventSubscriberInterface with AsDoctrineListener attribute(s)
<br>
## ExplicitRelationCollectionRector
Use explicit collection in one-to-many relations of Doctrine entity
- class: [`Rector\Doctrine\CodeQuality\Rector\Class_\ExplicitRelationCollectionRector`](../rules/CodeQuality/Rector/Class_/ExplicitRelationCollectionRector.php)
```diff
+use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\OneToMany;
-use Doctrine\ORM\Mapping\Entity;
+use Doctrine\Common\Collections\ArrayCollection;
+use Doctrine\Common\Collections\Collection;
#[Entity]
class SomeClass
{
#[OneToMany(targetEntity: 'SomeClass')]
- private $items = [];
+ private Collection $items;
+
+ public function __construct()
+ {
+ $this->items = new ArrayCollection();
+ }
}
```
<br>
## ExtractArrayArgOnQueryBuilderSelectRector
Extract array arg on QueryBuilder select, addSelect, groupBy, addGroupBy

View File

@ -0,0 +1,126 @@
<?php
declare (strict_types=1);
namespace Rector\Doctrine\CodeQuality\Rector\Class_;
use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Stmt\Class_;
use Rector\Doctrine\NodeAnalyzer\AttrinationFinder;
use Rector\Doctrine\NodeFactory\ArrayCollectionAssignFactory;
use Rector\NodeManipulator\ClassDependencyManipulator;
use Rector\Rector\AbstractRector;
use Rector\TypeDeclaration\AlreadyAssignDetector\ConstructorAssignDetector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see \Rector\Doctrine\Tests\CodeQuality\Rector\Class_\ExplicitRelationCollectionRector\ExplicitRelationCollectionRectorTest
*
* @changelog https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/best-practices.html#initialize-collections-in-the-constructor
*/
final class ExplicitRelationCollectionRector extends AbstractRector
{
/**
* @readonly
* @var \Rector\Doctrine\NodeAnalyzer\AttrinationFinder
*/
private $attrinationFinder;
/**
* @readonly
* @var \Rector\TypeDeclaration\AlreadyAssignDetector\ConstructorAssignDetector
*/
private $constructorAssignDetector;
/**
* @readonly
* @var \Rector\Doctrine\NodeFactory\ArrayCollectionAssignFactory
*/
private $arrayCollectionAssignFactory;
/**
* @readonly
* @var \Rector\NodeManipulator\ClassDependencyManipulator
*/
private $classDependencyManipulator;
public function __construct(AttrinationFinder $attrinationFinder, ConstructorAssignDetector $constructorAssignDetector, ArrayCollectionAssignFactory $arrayCollectionAssignFactory, ClassDependencyManipulator $classDependencyManipulator)
{
$this->attrinationFinder = $attrinationFinder;
$this->constructorAssignDetector = $constructorAssignDetector;
$this->arrayCollectionAssignFactory = $arrayCollectionAssignFactory;
$this->classDependencyManipulator = $classDependencyManipulator;
}
public function getRuleDefinition() : RuleDefinition
{
return new RuleDefinition('Use explicit collection in one-to-many relations of Doctrine entity', [new CodeSample(<<<'CODE_SAMPLE'
use Doctrine\ORM\Mapping\OneToMany;
use Doctrine\ORM\Mapping\Entity;
#[Entity]
class SomeClass
{
#[OneToMany(targetEntity: 'SomeClass')]
private $items = [];
}
CODE_SAMPLE
, <<<'CODE_SAMPLE'
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\OneToMany;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
#[Entity]
class SomeClass
{
#[OneToMany(targetEntity: 'SomeClass')]
private Collection $items;
public function __construct()
{
$this->items = new ArrayCollection();
}
}
CODE_SAMPLE
)]);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes() : array
{
return [Class_::class];
}
/**
* @param Class_ $node
*/
public function refactor(Node $node) : ?Node
{
if (!$this->attrinationFinder->hasByOne($node, 'Doctrine\\ORM\\Mapping\\Entity')) {
return null;
}
$arrayCollectionAssigns = [];
foreach ($node->getProperties() as $property) {
if (!$this->attrinationFinder->hasByMany($property, ['Doctrine\\ORM\\Mapping\\OneToMany', 'Doctrine\\ORM\\Mapping\\ManyToMany'])) {
continue;
}
// make sure has collection
if (!$property->type instanceof Node) {
$property->type = new FullyQualified('Doctrine\\Common\\Collections\\Collection');
}
// make sure is null
if ($property->props[0]->default instanceof Expr) {
$property->props[0]->default = null;
}
/** @var string $propertyName */
$propertyName = $this->getName($property);
if ($this->constructorAssignDetector->isPropertyAssigned($node, $propertyName)) {
continue;
}
$arrayCollectionAssigns[] = $this->arrayCollectionAssignFactory->createFromPropertyName($propertyName);
// make sure it is initialized in constructor
}
if ($arrayCollectionAssigns === []) {
return null;
}
$this->classDependencyManipulator->addStmtsToConstructorIfNotThereYet($node, $arrayCollectionAssigns);
return $node;
}
}

View File

@ -17,6 +17,8 @@ use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
* @see https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/best-practices.html#initialize-collections-in-the-constructor
*
* @see \Rector\Doctrine\Tests\CodeQuality\Rector\Class_\InitializeDefaultEntityCollectionRector\InitializeDefaultEntityCollectionRectorTest
*
* @deprecated This rule can create incomplete assign of object to an array. Use the @see \Rector\Doctrine\CodeQuality\Rector\Class_\ExplicitRelationCollectionRector instead.
*/
final class InitializeDefaultEntityCollectionRector extends AbstractRector
{
@ -41,7 +43,7 @@ final class InitializeDefaultEntityCollectionRector extends AbstractRector
*/
private $constructorAssignDetector;
/**
* @var class-string[]
* @var string[]
*/
private const TO_MANY_ANNOTATION_CLASSES = ['Doctrine\\ORM\\Mapping\\OneToMany', 'Doctrine\\ORM\\Mapping\\ManyToMany'];
public function __construct(ClassDependencyManipulator $classDependencyManipulator, ArrayCollectionAssignFactory $arrayCollectionAssignFactory, AttrinationFinder $attrinationFinder, ConstructorAssignDetector $constructorAssignDetector)
@ -103,7 +105,13 @@ CODE_SAMPLE
if (!$this->attrinationFinder->hasByOne($node, 'Doctrine\\ORM\\Mapping\\Entity')) {
return null;
}
return $this->refactorClass($node);
$toManyPropertyNames = $this->resolveToManyPropertyNames($node);
if ($toManyPropertyNames === []) {
return null;
}
$assigns = $this->createAssignsOfArrayCollectionsForPropertyNames($toManyPropertyNames);
$this->classDependencyManipulator->addStmtsToConstructorIfNotThereYet($node, $assigns);
return $node;
}
/**
* @return string[]
@ -139,14 +147,4 @@ CODE_SAMPLE
}
return $assigns;
}
private function refactorClass(Class_ $class) : ?\PhpParser\Node\Stmt\Class_
{
$toManyPropertyNames = $this->resolveToManyPropertyNames($class);
if ($toManyPropertyNames === []) {
return null;
}
$assigns = $this->createAssignsOfArrayCollectionsForPropertyNames($toManyPropertyNames);
$this->classDependencyManipulator->addStmtsToConstructorIfNotThereYet($class, $assigns);
return $class;
}
}

View File

@ -18,6 +18,7 @@ use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see \Rector\Doctrine\Tests\CodeQuality\Rector\Property\TypedPropertyFromDoctrineCollectionRector\TypedPropertyFromDoctrineCollectionRectorTest
* @deprecated Use more complete \Rector\Doctrine\CodeQuality\Rector\Class_\ExplicitRelationCollectionRector instead
*/
final class TypedPropertyFromDoctrineCollectionRector extends AbstractRector implements MinPhpVersionInterface
{

View File

@ -32,8 +32,6 @@ final class AttrinationFinder
$this->attributeFinder = $attributeFinder;
}
/**
* @api
* @param class-string $name
* @param \PhpParser\Node\Stmt\Property|\PhpParser\Node\Stmt\Class_|\PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Param $node
* @return \Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode|\PhpParser\Node\Attribute|null
*/
@ -46,7 +44,6 @@ final class AttrinationFinder
return $this->attributeFinder->findAttributeByClass($node, $name);
}
/**
* @param class-string $name
* @param \PhpParser\Node\Stmt\Property|\PhpParser\Node\Stmt\Class_|\PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Param $node
*/
public function hasByOne($node, string $name) : bool
@ -59,15 +56,15 @@ final class AttrinationFinder
return $attribute instanceof Attribute;
}
/**
* @param class-string[] $names
* @param string[] $classNames
*/
public function hasByMany(Property $property, array $names) : bool
public function hasByMany(Property $property, array $classNames) : bool
{
$phpDocInfo = $this->phpDocInfoFactory->createFromNode($property);
if ($phpDocInfo instanceof PhpDocInfo && $phpDocInfo->hasByAnnotationClasses($names)) {
if ($phpDocInfo instanceof PhpDocInfo && $phpDocInfo->hasByAnnotationClasses($classNames)) {
return \true;
}
$attribute = $this->attributeFinder->findAttributeByClasses($property, $names);
$attribute = $this->attributeFinder->findAttributeByClasses($property, $classNames);
return $attribute instanceof Attribute;
}
}