From f51cf515b80b3f13f48bd5aecd91f80fb585fdb9 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Wed, 11 Jun 2025 12:21:41 +0200 Subject: [PATCH] [typed-collections] Add ArrayOffsetSetToSetCollectionCallRector --- config/sets/typed-collections.php | 2 + ...OffsetSetToSetCollectionCallRectorTest.php | 28 +++++ .../Fixture/skip_non_collection.php.inc | 24 +++++ .../Fixture/skip_without_dim.php.inc | 26 +++++ .../Fixture/some_class.php.inc | 57 ++++++++++ .../config/configured_rule.php | 10 ++ ...rrayOffsetSetToSetCollectionCallRector.php | 100 ++++++++++++++++++ 7 files changed, 247 insertions(+) create mode 100644 rules-tests/TypedCollections/Rector/Assign/ArrayOffsetSetToSetCollectionCallRector/ArrayOffsetSetToSetCollectionCallRectorTest.php create mode 100644 rules-tests/TypedCollections/Rector/Assign/ArrayOffsetSetToSetCollectionCallRector/Fixture/skip_non_collection.php.inc create mode 100644 rules-tests/TypedCollections/Rector/Assign/ArrayOffsetSetToSetCollectionCallRector/Fixture/skip_without_dim.php.inc create mode 100644 rules-tests/TypedCollections/Rector/Assign/ArrayOffsetSetToSetCollectionCallRector/Fixture/some_class.php.inc create mode 100644 rules-tests/TypedCollections/Rector/Assign/ArrayOffsetSetToSetCollectionCallRector/config/configured_rule.php create mode 100644 rules/TypedCollections/Rector/Assign/ArrayOffsetSetToSetCollectionCallRector.php diff --git a/config/sets/typed-collections.php b/config/sets/typed-collections.php index 314df532..f89eb7bf 100644 --- a/config/sets/typed-collections.php +++ b/config/sets/typed-collections.php @@ -4,6 +4,7 @@ use Rector\Config\RectorConfig; use Rector\Doctrine\TypedCollections\Rector\Assign\ArrayDimFetchAssignToAddCollectionCallRector; +use Rector\Doctrine\TypedCollections\Rector\Assign\ArrayOffsetSetToSetCollectionCallRector; use Rector\Doctrine\TypedCollections\Rector\Class_\CompleteParamDocblockFromSetterToCollectionRector; use Rector\Doctrine\TypedCollections\Rector\Class_\CompletePropertyDocblockFromToManyRector; use Rector\Doctrine\TypedCollections\Rector\Class_\CompleteReturnDocblockFromToManyRector; @@ -47,6 +48,7 @@ // collection method calls ArrayDimFetchAssignToAddCollectionCallRector::class, + ArrayOffsetSetToSetCollectionCallRector::class, ArrayMapOnCollectionToArrayRector::class, ArrayMergeOnCollectionToArrayRector::class, EmptyOnCollectionToIsEmptyCallRector::class, diff --git a/rules-tests/TypedCollections/Rector/Assign/ArrayOffsetSetToSetCollectionCallRector/ArrayOffsetSetToSetCollectionCallRectorTest.php b/rules-tests/TypedCollections/Rector/Assign/ArrayOffsetSetToSetCollectionCallRector/ArrayOffsetSetToSetCollectionCallRectorTest.php new file mode 100644 index 00000000..fd4df68c --- /dev/null +++ b/rules-tests/TypedCollections/Rector/Assign/ArrayOffsetSetToSetCollectionCallRector/ArrayOffsetSetToSetCollectionCallRectorTest.php @@ -0,0 +1,28 @@ +doTestFile($filePath); + } + + public static function provideData(): Iterator + { + return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); + } + + public function provideConfigFilePath(): string + { + return __DIR__ . '/config/configured_rule.php'; + } +} diff --git a/rules-tests/TypedCollections/Rector/Assign/ArrayOffsetSetToSetCollectionCallRector/Fixture/skip_non_collection.php.inc b/rules-tests/TypedCollections/Rector/Assign/ArrayOffsetSetToSetCollectionCallRector/Fixture/skip_non_collection.php.inc new file mode 100644 index 00000000..b2ff930e --- /dev/null +++ b/rules-tests/TypedCollections/Rector/Assign/ArrayOffsetSetToSetCollectionCallRector/Fixture/skip_non_collection.php.inc @@ -0,0 +1,24 @@ + + */ + public $items; + + public function setItems() + { + $items = $this->getItems(); + $items[5] = 10; + } + + private function getItems() + { + return $this->items; + } +} diff --git a/rules-tests/TypedCollections/Rector/Assign/ArrayOffsetSetToSetCollectionCallRector/Fixture/skip_without_dim.php.inc b/rules-tests/TypedCollections/Rector/Assign/ArrayOffsetSetToSetCollectionCallRector/Fixture/skip_without_dim.php.inc new file mode 100644 index 00000000..4b282941 --- /dev/null +++ b/rules-tests/TypedCollections/Rector/Assign/ArrayOffsetSetToSetCollectionCallRector/Fixture/skip_without_dim.php.inc @@ -0,0 +1,26 @@ + + */ + public $items; + + public function setItems() + { + $items = $this->getItems(); + $items[] = 10; + } + + private function getItems(): Collection + { + return $this->items; + } +} diff --git a/rules-tests/TypedCollections/Rector/Assign/ArrayOffsetSetToSetCollectionCallRector/Fixture/some_class.php.inc b/rules-tests/TypedCollections/Rector/Assign/ArrayOffsetSetToSetCollectionCallRector/Fixture/some_class.php.inc new file mode 100644 index 00000000..ddac2e63 --- /dev/null +++ b/rules-tests/TypedCollections/Rector/Assign/ArrayOffsetSetToSetCollectionCallRector/Fixture/some_class.php.inc @@ -0,0 +1,57 @@ + + */ + public $items; + + public function setItems() + { + $items = $this->getItems(); + $items[5] = 10; + } + + private function getItems(): Collection + { + return $this->items; + } +} + +?> +----- + + */ + public $items; + + public function setItems() + { + $items = $this->getItems(); + $items->set(5, 10); + } + + private function getItems(): Collection + { + return $this->items; + } +} + +?> diff --git a/rules-tests/TypedCollections/Rector/Assign/ArrayOffsetSetToSetCollectionCallRector/config/configured_rule.php b/rules-tests/TypedCollections/Rector/Assign/ArrayOffsetSetToSetCollectionCallRector/config/configured_rule.php new file mode 100644 index 00000000..d0202cdc --- /dev/null +++ b/rules-tests/TypedCollections/Rector/Assign/ArrayOffsetSetToSetCollectionCallRector/config/configured_rule.php @@ -0,0 +1,10 @@ +rule(ArrayOffsetSetToSetCollectionCallRector::class); +}; diff --git a/rules/TypedCollections/Rector/Assign/ArrayOffsetSetToSetCollectionCallRector.php b/rules/TypedCollections/Rector/Assign/ArrayOffsetSetToSetCollectionCallRector.php new file mode 100644 index 00000000..c6e63d06 --- /dev/null +++ b/rules/TypedCollections/Rector/Assign/ArrayOffsetSetToSetCollectionCallRector.php @@ -0,0 +1,100 @@ +set() call', + [ + new CodeSample( + <<<'CODE_SAMPLE' +use Doctrine\Common\Collections\Collection; + +final class SomeClass +{ + /** + * @var Collection + */ + public $items; + + public function setItem() + { + $this->items['key'] = 'value'; + } +} +CODE_SAMPLE + , + <<<'CODE_SAMPLE' +use Doctrine\Common\Collections\Collection; + +final class SomeClass +{ + /** + * @var Collection + */ + public $items; + + public function setItem() + { + $this->items->set('key', 'value'); + } +} +CODE_SAMPLE + )] + ); + } + + public function getNodeTypes(): array + { + return [Assign::class]; + } + + /** + * @param Assign $node + */ + public function refactor(Node $node): ?MethodCall + { + if (! $node->var instanceof ArrayDimFetch) { + return null; + } + + $arrayDimFetch = $node->var; + if (! $arrayDimFetch->dim instanceof Expr) { + return null; + } + + $assignedExpr = $arrayDimFetch->var; + if (! $this->collectionTypeDetector->isCollectionType($assignedExpr)) { + return null; + } + + $args = [new Arg($arrayDimFetch->dim), new Arg($node->expr)]; + + return new MethodCall($assignedExpr, 'set', $args); + } +}