From b912651714896989780ed8a31057ef31d9c00c7f Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 20 May 2025 21:32:35 +0700 Subject: [PATCH 1/5] [AnnotationsToAttributes] Apply to class level on @uses on AnnotationWithValueToAttributeRector --- config/sets/annotations-to-attributes.php | 2 +- .../Fixture/uses_in_test.php.inc | 2 +- .../config/configured_rule.php | 2 +- .../Class_/AnnotationWithValueToAttributeRector.php | 12 +++++++++++- src/ValueObject/AnnotationWithValueToAttribute.php | 8 +++++++- 5 files changed, 21 insertions(+), 5 deletions(-) diff --git a/config/sets/annotations-to-attributes.php b/config/sets/annotations-to-attributes.php index df44415e..a5b81221 100644 --- a/config/sets/annotations-to-attributes.php +++ b/config/sets/annotations-to-attributes.php @@ -51,7 +51,7 @@ new AnnotationWithValueToAttribute('depends', 'PHPUnit\Framework\Attributes\Depends'), new AnnotationWithValueToAttribute('group', 'PHPUnit\Framework\Attributes\Group'), - new AnnotationWithValueToAttribute('uses', 'PHPUnit\Framework\Attributes\UsesClass'), + new AnnotationWithValueToAttribute('uses', 'PHPUnit\Framework\Attributes\UsesClass', [], true), new AnnotationWithValueToAttribute('testDox', 'PHPUnit\Framework\Attributes\TestDox'), new AnnotationWithValueToAttribute('testdox', 'PHPUnit\Framework\Attributes\TestDox'), ]); diff --git a/rules-tests/AnnotationsToAttributes/Rector/Class_/AnnotationWithValueToAttributeRector/Fixture/uses_in_test.php.inc b/rules-tests/AnnotationsToAttributes/Rector/Class_/AnnotationWithValueToAttributeRector/Fixture/uses_in_test.php.inc index 38d4516d..fdae1f3f 100644 --- a/rules-tests/AnnotationsToAttributes/Rector/Class_/AnnotationWithValueToAttributeRector/Fixture/uses_in_test.php.inc +++ b/rules-tests/AnnotationsToAttributes/Rector/Class_/AnnotationWithValueToAttributeRector/Fixture/uses_in_test.php.inc @@ -22,9 +22,9 @@ namespace Rector\PHPUnit\Tests\AnnotationsToAttributes\Rector\Class_\AnnotationW use PHPUnit\Framework\TestCase; +#[\PHPUnit\Framework\Attributes\UsesClass(Foo::Bar)] final class UsesInTest extends TestCase { - #[\PHPUnit\Framework\Attributes\UsesClass(Foo::Bar)] public function run() { } diff --git a/rules-tests/AnnotationsToAttributes/Rector/Class_/AnnotationWithValueToAttributeRector/config/configured_rule.php b/rules-tests/AnnotationsToAttributes/Rector/Class_/AnnotationWithValueToAttributeRector/config/configured_rule.php index 87709c42..9f77c975 100644 --- a/rules-tests/AnnotationsToAttributes/Rector/Class_/AnnotationWithValueToAttributeRector/config/configured_rule.php +++ b/rules-tests/AnnotationsToAttributes/Rector/Class_/AnnotationWithValueToAttributeRector/config/configured_rule.php @@ -13,6 +13,6 @@ 'disabled' => false, ]), new AnnotationWithValueToAttribute('dataProvider', 'PHPUnit\Framework\Attributes\DataProvider'), - new AnnotationWithValueToAttribute('uses', 'PHPUnit\Framework\Attributes\UsesClass'), + new AnnotationWithValueToAttribute('uses', 'PHPUnit\Framework\Attributes\UsesClass', [], true), ]); }; diff --git a/rules/AnnotationsToAttributes/Rector/Class_/AnnotationWithValueToAttributeRector.php b/rules/AnnotationsToAttributes/Rector/Class_/AnnotationWithValueToAttributeRector.php index c3d070dc..b8275ed4 100644 --- a/rules/AnnotationsToAttributes/Rector/Class_/AnnotationWithValueToAttributeRector.php +++ b/rules/AnnotationsToAttributes/Rector/Class_/AnnotationWithValueToAttributeRector.php @@ -34,6 +34,8 @@ final class AnnotationWithValueToAttributeRector extends AbstractRector implemen */ private array $annotationWithValueToAttributes = []; + private ?Class_ $currentClass = null; + public function __construct( private readonly PhpDocTagRemover $phpDocTagRemover, private readonly PhpAttributeGroupFactory $phpAttributeGroupFactory, @@ -101,6 +103,10 @@ public function refactor(Node $node): ?Node return null; } + if ($node instanceof Class_) { + $this->currentClass = $node; + } + $phpDocInfo = $this->phpDocInfoFactory->createFromNode($node); if (! $phpDocInfo instanceof PhpDocInfo) { return null; @@ -127,7 +133,11 @@ public function refactor(Node $node): ?Node [$attributeValue] ); - $node->attrGroups[] = $attributeGroup; + if ($annotationWithValueToAttribute->getIsOnClassLevel()) { + $this->currentClass->attrGroups = array_merge($this->currentClass->attrGroups, [$attributeGroup]); + } else { + $node->attrGroups = array_merge($node->attrGroups, [$attributeGroup]); + } // cleanup $this->phpDocTagRemover->removeTagValueFromNode($phpDocInfo, $desiredTagValueNode); diff --git a/src/ValueObject/AnnotationWithValueToAttribute.php b/src/ValueObject/AnnotationWithValueToAttribute.php index 577434f1..0027de6e 100644 --- a/src/ValueObject/AnnotationWithValueToAttribute.php +++ b/src/ValueObject/AnnotationWithValueToAttribute.php @@ -12,7 +12,8 @@ public function __construct( private string $annotationName, private string $attributeClass, - private array $valueMap = [] + private array $valueMap = [], + private bool $isOnClassLevel = false, ) { } @@ -33,4 +34,9 @@ public function getValueMap(): array { return $this->valueMap; } + + public function getIsOnClassLevel(): bool + { + return $this->isOnClassLevel; + } } From c60c1272e0ecf00e7571cb665dadbaf8e9975fa9 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 20 May 2025 21:33:24 +0700 Subject: [PATCH 2/5] [AnnotationsToAttributes] Apply to class level on @uses on AnnotationWithValueToAttributeRector --- .../Rector/Class_/AnnotationWithValueToAttributeRector.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/AnnotationsToAttributes/Rector/Class_/AnnotationWithValueToAttributeRector.php b/rules/AnnotationsToAttributes/Rector/Class_/AnnotationWithValueToAttributeRector.php index b8275ed4..04b20ccb 100644 --- a/rules/AnnotationsToAttributes/Rector/Class_/AnnotationWithValueToAttributeRector.php +++ b/rules/AnnotationsToAttributes/Rector/Class_/AnnotationWithValueToAttributeRector.php @@ -133,7 +133,7 @@ public function refactor(Node $node): ?Node [$attributeValue] ); - if ($annotationWithValueToAttribute->getIsOnClassLevel()) { + if ($node instanceof ClassMethod && $annotationWithValueToAttribute->getIsOnClassLevel()) { $this->currentClass->attrGroups = array_merge($this->currentClass->attrGroups, [$attributeGroup]); } else { $node->attrGroups = array_merge($node->attrGroups, [$attributeGroup]); From 8888c4e16eb34ae565c4f4eb4830d514b8f4766e Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 20 May 2025 21:35:01 +0700 Subject: [PATCH 3/5] [AnnotationsToAttributes] Apply to class level on @uses on AnnotationWithValueToAttributeRector --- .../Rector/Class_/AnnotationWithValueToAttributeRector.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/AnnotationsToAttributes/Rector/Class_/AnnotationWithValueToAttributeRector.php b/rules/AnnotationsToAttributes/Rector/Class_/AnnotationWithValueToAttributeRector.php index 04b20ccb..7de9328b 100644 --- a/rules/AnnotationsToAttributes/Rector/Class_/AnnotationWithValueToAttributeRector.php +++ b/rules/AnnotationsToAttributes/Rector/Class_/AnnotationWithValueToAttributeRector.php @@ -133,7 +133,7 @@ public function refactor(Node $node): ?Node [$attributeValue] ); - if ($node instanceof ClassMethod && $annotationWithValueToAttribute->getIsOnClassLevel()) { + if ($node instanceof ClassMethod && $annotationWithValueToAttribute->getIsOnClassLevel() && $this->currentClass instanceof Class_) { $this->currentClass->attrGroups = array_merge($this->currentClass->attrGroups, [$attributeGroup]); } else { $node->attrGroups = array_merge($node->attrGroups, [$attributeGroup]); From fa33c0c54925576f916c27e513219609455930af Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 20 May 2025 21:37:15 +0700 Subject: [PATCH 4/5] Fix phpstan --- .../Rector/Class_/AnnotationWithValueToAttributeRector.php | 1 + 1 file changed, 1 insertion(+) diff --git a/rules/AnnotationsToAttributes/Rector/Class_/AnnotationWithValueToAttributeRector.php b/rules/AnnotationsToAttributes/Rector/Class_/AnnotationWithValueToAttributeRector.php index 7de9328b..422dd761 100644 --- a/rules/AnnotationsToAttributes/Rector/Class_/AnnotationWithValueToAttributeRector.php +++ b/rules/AnnotationsToAttributes/Rector/Class_/AnnotationWithValueToAttributeRector.php @@ -134,6 +134,7 @@ public function refactor(Node $node): ?Node ); if ($node instanceof ClassMethod && $annotationWithValueToAttribute->getIsOnClassLevel() && $this->currentClass instanceof Class_) { + Assert::isInstanceOf($this->currentClass, Class_::class); $this->currentClass->attrGroups = array_merge($this->currentClass->attrGroups, [$attributeGroup]); } else { $node->attrGroups = array_merge($node->attrGroups, [$attributeGroup]); From cc77a37e8a7ad55d8742884d98505358db52abcd Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 20 May 2025 21:49:29 +0700 Subject: [PATCH 5/5] skip in anonymous fixture --- .../skip_uses_in_anonymous_class.php.inc | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 rules-tests/AnnotationsToAttributes/Rector/Class_/AnnotationWithValueToAttributeRector/Fixture/skip_uses_in_anonymous_class.php.inc diff --git a/rules-tests/AnnotationsToAttributes/Rector/Class_/AnnotationWithValueToAttributeRector/Fixture/skip_uses_in_anonymous_class.php.inc b/rules-tests/AnnotationsToAttributes/Rector/Class_/AnnotationWithValueToAttributeRector/Fixture/skip_uses_in_anonymous_class.php.inc new file mode 100644 index 00000000..913f1cf9 --- /dev/null +++ b/rules-tests/AnnotationsToAttributes/Rector/Class_/AnnotationWithValueToAttributeRector/Fixture/skip_uses_in_anonymous_class.php.inc @@ -0,0 +1,20 @@ +