rector/packages/PhpAttribute/AnnotationToAttributeMapper/ArrayItemNodeAnnotationToAttributeMapper.php
Tomas Votruba 6981c70c9a Updated Rector to commit 9ed8c21b127cdd45a28307d5fc41668f867f4ef4
9ed8c21b12 [DeadCode] Remove findFirstPrevious() usage on UselessIfCondBeforeForeachDetector (#4388)
2023-07-01 09:41:56 +00:00

84 lines
3.0 KiB
PHP

<?php
declare (strict_types=1);
namespace Rector\PhpAttribute\AnnotationToAttributeMapper;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\ArrayItem;
use PhpParser\Node\Scalar\String_;
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode;
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
use Rector\BetterPhpDocParser\PhpDoc\StringNode;
use Rector\Core\Validation\RectorAssert;
use Rector\PhpAttribute\AnnotationToAttributeMapper;
use Rector\PhpAttribute\Contract\AnnotationToAttributeMapperInterface;
use Rector\PhpAttribute\Enum\DocTagNodeState;
use RectorPrefix202307\Symfony\Contracts\Service\Attribute\Required;
use RectorPrefix202307\Webmozart\Assert\InvalidArgumentException;
/**
* @implements AnnotationToAttributeMapperInterface<ArrayItemNode>
*/
final class ArrayItemNodeAnnotationToAttributeMapper implements AnnotationToAttributeMapperInterface
{
/**
* @var \Rector\PhpAttribute\AnnotationToAttributeMapper
*/
private $annotationToAttributeMapper;
/**
* Avoid circular reference
* @required
*/
public function autowire(AnnotationToAttributeMapper $annotationToAttributeMapper) : void
{
$this->annotationToAttributeMapper = $annotationToAttributeMapper;
}
/**
* @param mixed $value
*/
public function isCandidate($value) : bool
{
return $value instanceof ArrayItemNode;
}
/**
* @param ArrayItemNode $arrayItemNode
*/
public function map($arrayItemNode) : Expr
{
$valueExpr = $this->annotationToAttributeMapper->map($arrayItemNode->value);
if ($valueExpr === DocTagNodeState::REMOVE_ARRAY) {
return new ArrayItem(new String_($valueExpr), null);
}
if ($arrayItemNode->key !== null) {
/** @var Expr $keyExpr */
$keyExpr = $this->annotationToAttributeMapper->map($arrayItemNode->key);
} else {
if ($this->hasNoParenthesesAnnotation($arrayItemNode)) {
try {
RectorAssert::className(\ltrim((string) $arrayItemNode->value, '@'));
$identifierTypeNode = new IdentifierTypeNode($arrayItemNode->value);
$arrayItemNode->value = new DoctrineAnnotationTagValueNode($identifierTypeNode);
return $this->map($arrayItemNode);
} catch (InvalidArgumentException $exception) {
}
}
$keyExpr = null;
}
// @todo how to skip natural integer keys?
return new ArrayItem($valueExpr, $keyExpr);
}
private function hasNoParenthesesAnnotation(ArrayItemNode $arrayItemNode) : bool
{
if ($arrayItemNode->value instanceof StringNode) {
return \false;
}
if (!\is_string($arrayItemNode->value)) {
return \false;
}
if (\strncmp($arrayItemNode->value, '@', \strlen('@')) !== 0) {
return \false;
}
return \substr_compare($arrayItemNode->value, ')', -\strlen(')')) !== 0;
}
}