[Php80] Handle named type on JMS\AccessType on AnnotationToAttributeRector (#2141)

* Add failing test for JMS AccessType

* Configure rule for testing transform of JMS\AccessType

* Closes #2118

* [ci-review] Rector Rectify

Co-authored-by: Dominik Ritter <dritter03@googlemail.com>
Co-authored-by: GitHub Action <action@github.com>
This commit is contained in:
Abdul Malik Ikhsan 2022-04-24 05:20:46 +07:00 committed by GitHub
parent eb1090c934
commit e4858d9a60
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 131 additions and 0 deletions

View File

@ -0,0 +1,25 @@
<?php
namespace Rector\Tests\Php80\Rector\Class_\AnnotationToAttributeRector\Fixture\JMS;
use JMS\Serializer\Annotation as JMS;
/**
* @JMS\AccessType("public_method")
*/
class MyClass
{
}
?>
-----
<?php
namespace Rector\Tests\Php80\Rector\Class_\AnnotationToAttributeRector\Fixture\JMS;
use JMS\Serializer\Annotation as JMS;
#[JMS\AccessType(type: 'public_method')]
class MyClass
{
}
?>

View File

@ -0,0 +1,21 @@
<?php
namespace Rector\Tests\Php80\Rector\Class_\AnnotationToAttributeRector\Fixture\JMS;
/**
* @\JMS\Serializer\Annotation\AccessType("public_method")
*/
class MyClass2
{
}
?>
-----
<?php
namespace Rector\Tests\Php80\Rector\Class_\AnnotationToAttributeRector\Fixture\JMS;
#[\JMS\Serializer\Annotation\AccessType(type: 'public_method')]
class MyClass2
{
}
?>

View File

@ -34,6 +34,9 @@ return static function (RectorConfig $rectorConfig): void {
new AnnotationToAttribute('Symfony\Component\Validator\Constraints\All'),
new AnnotationToAttribute('Symfony\Component\Validator\Constraints\Length'),
// JMS
new AnnotationToAttribute('JMS\Serializer\Annotation\AccessType'),
// test for alias used
new AnnotationToAttribute(
'Rector\Tests\Php80\Rector\Class_\AnnotationToAttributeRector\Source\UseAlias\TestSmth'

View File

@ -0,0 +1,78 @@
<?php
declare(strict_types=1);
namespace Rector\Php80\NodeManipulator;
use PhpParser\Node\Arg;
use PhpParser\Node\Attribute;
use PhpParser\Node\AttributeGroup;
use PhpParser\Node\Expr;
use PhpParser\Node\Identifier;
use Rector\Core\NodeAnalyzer\ArgsAnalyzer;
final class AttributeGroupNamedArgumentManipulator
{
/**
* @var array<string, array<string, string|class-string<Expr>>>
*/
private const SPECIAL_CLASS_TYPES = [
'JMS\Serializer\Annotation\AccessType' => [
'common_aliased' => 'JMS\AccessType',
'value' => 'PhpParser\Node\Scalar\String_',
'name' => 'type',
],
];
public function __construct(private readonly ArgsAnalyzer $argsAnalyzer)
{
}
/**
* @param AttributeGroup[] $attributeGroups
* @return AttributeGroup[]
*/
public function processSpecialClassTypes(array $attributeGroups): array
{
foreach ($attributeGroups as $attributeGroup) {
$attrs = $attributeGroup->attrs;
foreach ($attrs as $attr) {
$attrName = ltrim($attr->name->toString(), '\\');
$this->processReplaceAttr($attr, $attrName);
}
}
return $attributeGroups;
}
private function processReplaceAttr(Attribute $attribute, string $attrName): void
{
foreach (self::SPECIAL_CLASS_TYPES as $classType => $specialClasssType) {
if ($attrName !== $classType && $attrName !== $specialClasssType['common_aliased']) {
continue;
}
$args = $attribute->args;
if (count($args) !== 1) {
continue;
}
if (! $this->argsAnalyzer->isArgInstanceInArgsPosition($args, 0)) {
continue;
}
/** @var Arg $currentArg */
$currentArg = $args[0];
if ($currentArg->name !== null) {
continue;
}
if (! $currentArg->value instanceof $specialClasssType['value']) {
continue;
}
$currentArg->name = new Identifier($specialClasssType['name']);
}
}
}

View File

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Rector\Php80\Rector\Class_;
use Doctrine\Common\Annotations\Annotation\Attributes;
use PhpParser\Node;
use PhpParser\Node\AttributeGroup;
use PhpParser\Node\Expr\ArrowFunction;
@ -23,6 +24,7 @@ use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\ValueObject\PhpVersionFeature;
use Rector\Php80\NodeFactory\AttrGroupsFactory;
use Rector\Php80\NodeManipulator\AttributeGroupNamedArgumentManipulator;
use Rector\Php80\PhpDoc\PhpDocNodeFinder;
use Rector\Php80\ValueObject\AnnotationToAttribute;
use Rector\Php80\ValueObject\DoctrineTagAndAnnotationToAttribute;
@ -54,6 +56,7 @@ final class AnnotationToAttributeRector extends AbstractRector implements Config
private readonly PhpDocNodeFinder $phpDocNodeFinder,
private readonly UnwrapableAnnotationAnalyzer $unwrapableAnnotationAnalyzer,
private readonly RemovableAnnotationAnalyzer $removableAnnotationAnalyzer,
private readonly AttributeGroupNamedArgumentManipulator $attributeGroupNamedArgumentManipulator
) {
}
@ -129,6 +132,7 @@ CODE_SAMPLE
return null;
}
$attributeGroups = $this->attributeGroupNamedArgumentManipulator->processSpecialClassTypes($attributeGroups);
$node->attrGroups = array_merge($node->attrGroups, $attributeGroups);
return $node;