mirror of
https://github.com/rectorphp/rector.git
synced 2025-01-17 13:28:18 +01:00
Updated Rector to commit a33b200e615b9451ba091e2724ab707f39198da7
a33b200e61
[BetterPhpDocParser] Add ArrayItemNode to improve value transfer in annotation curly lists (#2786)
This commit is contained in:
parent
a6435672ab
commit
402dbe5a36
@ -11,30 +11,50 @@ final class ArrayItemNode implements PhpDocTagValueNode
|
||||
{
|
||||
use NodeAttributes;
|
||||
/**
|
||||
* @readonly
|
||||
* @var mixed
|
||||
*/
|
||||
private $value;
|
||||
public $value;
|
||||
/**
|
||||
* @var mixed
|
||||
*/
|
||||
public $key;
|
||||
/**
|
||||
* @var String_::KIND_*|null
|
||||
* @readonly
|
||||
*/
|
||||
private $kindValueQuoted = null;
|
||||
public $kindValueQuoted = null;
|
||||
/**
|
||||
* @var int|null
|
||||
*/
|
||||
public $kindKeyQuoted = null;
|
||||
/**
|
||||
* @param String_::KIND_*|null $kindValueQuoted
|
||||
* @param mixed $value
|
||||
* @param mixed $key
|
||||
*/
|
||||
public function __construct($value, ?int $kindValueQuoted = null)
|
||||
public function __construct($value, $key, ?int $kindValueQuoted = null, ?int $kindKeyQuoted = null)
|
||||
{
|
||||
$this->value = $value;
|
||||
$this->key = $key;
|
||||
$this->kindValueQuoted = $kindValueQuoted;
|
||||
$this->kindKeyQuoted = $kindKeyQuoted;
|
||||
}
|
||||
public function __toString() : string
|
||||
{
|
||||
$value = '';
|
||||
if ($this->kindKeyQuoted === String_::KIND_DOUBLE_QUOTED) {
|
||||
$value .= '"' . $this->key . '" = ';
|
||||
} elseif ($this->key !== null) {
|
||||
$value .= $this->key . '=';
|
||||
}
|
||||
// @todo depends on the context! possibly the top array is quting this stinrg already
|
||||
if ($this->kindValueQuoted === String_::KIND_DOUBLE_QUOTED) {
|
||||
$value .= '"' . $this->value . '"';
|
||||
} elseif (\is_array($this->value)) {
|
||||
foreach ($this->value as $singleValue) {
|
||||
$value .= $singleValue;
|
||||
}
|
||||
} else {
|
||||
$value .= $this->value;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ final class DoctrineAnnotationTagValueNode extends AbstractValuesAwareNode
|
||||
*/
|
||||
public $identifierTypeNode;
|
||||
/**
|
||||
* @param array<mixed, mixed> $values
|
||||
* @param ArrayItemNode[] $values
|
||||
*/
|
||||
public function __construct(IdentifierTypeNode $identifierTypeNode, ?string $originalContent = null, array $values = [], ?string $silentKey = null)
|
||||
{
|
||||
|
@ -5,6 +5,7 @@ namespace Rector\BetterPhpDocParser\PhpDocManipulator;
|
||||
|
||||
use RectorPrefix202208\Nette\Utils\Strings;
|
||||
use PhpParser\Node;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
use Rector\BetterPhpDocParser\PhpDocParser\ClassAnnotationMatcher;
|
||||
@ -41,17 +42,24 @@ final class PhpDocClassRenamer
|
||||
if (!$assertChoiceTagValueNode instanceof DoctrineAnnotationTagValueNode) {
|
||||
return;
|
||||
}
|
||||
$callback = $assertChoiceTagValueNode->getValueWithoutQuotes('callback');
|
||||
if (!$callback instanceof CurlyListNode) {
|
||||
$callbackArrayItemNode = $assertChoiceTagValueNode->getValue('callback');
|
||||
if (!$callbackArrayItemNode instanceof ArrayItemNode) {
|
||||
return;
|
||||
}
|
||||
$callbackClass = $callback->getValueWithoutQuotes(0);
|
||||
$callbackClass = $callbackArrayItemNode->value;
|
||||
// array is needed for callable
|
||||
if (!$callbackClass instanceof CurlyListNode) {
|
||||
return;
|
||||
}
|
||||
$callableCallbackArrayItems = $callbackClass->getValues();
|
||||
$classNameArrayItemNode = $callableCallbackArrayItems[0];
|
||||
foreach ($oldToNewClasses as $oldClass => $newClass) {
|
||||
if ($callbackClass !== $oldClass) {
|
||||
if ($classNameArrayItemNode->value !== $oldClass) {
|
||||
continue;
|
||||
}
|
||||
$callback->changeValue('0', $newClass);
|
||||
$assertChoiceTagValueNode->changeValue('callback', $callback);
|
||||
$classNameArrayItemNode->value = $newClass;
|
||||
// trigger reprint
|
||||
$classNameArrayItemNode->setAttribute('orig_node', null);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -75,24 +83,22 @@ final class PhpDocClassRenamer
|
||||
if (!$doctrineAnnotationTagValueNode instanceof DoctrineAnnotationTagValueNode) {
|
||||
return;
|
||||
}
|
||||
$classNameArrayItemNode = $doctrineAnnotationTagValueNode->getSilentValue();
|
||||
foreach ($oldToNewClasses as $oldClass => $newClass) {
|
||||
$className = $doctrineAnnotationTagValueNode->getSilentValue();
|
||||
if (\is_string($className)) {
|
||||
if ($className === $oldClass) {
|
||||
$doctrineAnnotationTagValueNode->changeSilentValue($newClass);
|
||||
if ($classNameArrayItemNode instanceof ArrayItemNode) {
|
||||
if ($classNameArrayItemNode->value === $oldClass) {
|
||||
$classNameArrayItemNode->value = $newClass;
|
||||
continue;
|
||||
}
|
||||
$newContent = Strings::replace($className, '#\\b' . \preg_quote($oldClass, '#') . '\\b#', $newClass);
|
||||
if ($newContent === $className) {
|
||||
continue;
|
||||
}
|
||||
$doctrineAnnotationTagValueNode->changeSilentValue($newContent);
|
||||
$classNameArrayItemNode->value = Strings::replace($classNameArrayItemNode->value, '#\\b' . \preg_quote($oldClass, '#') . '\\b#', $newClass);
|
||||
$classNameArrayItemNode->setAttribute('orig_node', null);
|
||||
}
|
||||
$currentTypeArrayItemNode = $doctrineAnnotationTagValueNode->getValue('type');
|
||||
if (!$currentTypeArrayItemNode instanceof ArrayItemNode) {
|
||||
continue;
|
||||
}
|
||||
$currentType = $doctrineAnnotationTagValueNode->getValueWithoutQuotes('type');
|
||||
if ($currentType === $oldClass) {
|
||||
$doctrineAnnotationTagValueNode->changeValue('type', $newClass);
|
||||
continue;
|
||||
if ($currentTypeArrayItemNode->value === $oldClass) {
|
||||
$currentTypeArrayItemNode->value = $newClass;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -102,17 +108,19 @@ final class PhpDocClassRenamer
|
||||
private function processDoctrineToMany(DoctrineAnnotationTagValueNode $doctrineAnnotationTagValueNode, Node $node, array $oldToNewClasses) : void
|
||||
{
|
||||
$classKey = $doctrineAnnotationTagValueNode->hasClassName('Doctrine\\ORM\\Mapping\\Embedded') ? 'class' : 'targetEntity';
|
||||
$targetEntity = $doctrineAnnotationTagValueNode->getValueWithoutQuotes($classKey);
|
||||
if ($targetEntity === null) {
|
||||
$targetEntityArrayItemNode = $doctrineAnnotationTagValueNode->getValue($classKey);
|
||||
if (!$targetEntityArrayItemNode instanceof ArrayItemNode) {
|
||||
return;
|
||||
}
|
||||
$targetEntityClass = $targetEntityArrayItemNode->value;
|
||||
// resolve to FQN
|
||||
$tagFullyQualifiedName = $this->classAnnotationMatcher->resolveTagFullyQualifiedName($targetEntity, $node);
|
||||
$tagFullyQualifiedName = $this->classAnnotationMatcher->resolveTagFullyQualifiedName($targetEntityClass, $node);
|
||||
foreach ($oldToNewClasses as $oldClass => $newClass) {
|
||||
if ($tagFullyQualifiedName !== $oldClass) {
|
||||
continue;
|
||||
}
|
||||
$doctrineAnnotationTagValueNode->changeValue($classKey, $newClass);
|
||||
$targetEntityArrayItemNode->value = $newClass;
|
||||
$targetEntityArrayItemNode->setAttribute('orig_node', null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ namespace Rector\BetterPhpDocParser\PhpDocParser;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprNode;
|
||||
use PHPStan\PhpDocParser\Lexer\Lexer;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocParser\StaticDoctrineAnnotationParser\ArrayParser;
|
||||
use Rector\BetterPhpDocParser\PhpDocParser\StaticDoctrineAnnotationParser\PlainValueParser;
|
||||
@ -33,7 +34,8 @@ final class StaticDoctrineAnnotationParser
|
||||
}
|
||||
/**
|
||||
* mimics: https://github.com/doctrine/annotations/blob/c66f06b7c83e9a2a7523351a9d5a4b55f885e574/lib/Doctrine/Common/Annotations/DocParser.php#L1024-L1041
|
||||
* @return array<mixed, mixed>
|
||||
*
|
||||
* @return ArrayItemNode[]
|
||||
*/
|
||||
public function resolveAnnotationMethodCall(BetterTokenIterator $tokenIterator) : array
|
||||
{
|
||||
@ -73,7 +75,8 @@ final class StaticDoctrineAnnotationParser
|
||||
}
|
||||
/**
|
||||
* @see https://github.com/doctrine/annotations/blob/c66f06b7c83e9a2a7523351a9d5a4b55f885e574/lib/Doctrine/Common/Annotations/DocParser.php#L1051-L1079
|
||||
* @return array<mixed>
|
||||
*
|
||||
* @return ArrayItemNode[]
|
||||
*/
|
||||
private function resolveAnnotationValues(BetterTokenIterator $tokenIterator) : array
|
||||
{
|
||||
@ -100,7 +103,7 @@ final class StaticDoctrineAnnotationParser
|
||||
$values[] = $nestedValues;
|
||||
}
|
||||
}
|
||||
return $values;
|
||||
return $this->arrayParser->createArrayFromValues($values);
|
||||
}
|
||||
/**
|
||||
* @return CurlyListNode|string|array<mixed>|ConstExprNode|DoctrineAnnotationTagValueNode
|
||||
|
@ -3,8 +3,10 @@
|
||||
declare (strict_types=1);
|
||||
namespace Rector\BetterPhpDocParser\PhpDocParser\StaticDoctrineAnnotationParser;
|
||||
|
||||
use PhpParser\Node\Scalar\String_;
|
||||
use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprIntegerNode;
|
||||
use PHPStan\PhpDocParser\Lexer\Lexer;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode;
|
||||
use Rector\BetterPhpDocParser\ValueObject\Parser\BetterTokenIterator;
|
||||
/**
|
||||
* @see \Rector\Tests\BetterPhpDocParser\PhpDocParser\StaticDoctrineAnnotationParser\ArrayParserTest
|
||||
@ -22,7 +24,8 @@ final class ArrayParser
|
||||
}
|
||||
/**
|
||||
* Mimics https://github.com/doctrine/annotations/blob/c66f06b7c83e9a2a7523351a9d5a4b55f885e574/lib/Doctrine/Common/Annotations/DocParser.php#L1305-L1352
|
||||
* @return mixed[]
|
||||
*
|
||||
* @return ArrayItemNode[]
|
||||
*/
|
||||
public function parseCurlyArray(BetterTokenIterator $tokenIterator) : array
|
||||
{
|
||||
@ -61,6 +64,29 @@ final class ArrayParser
|
||||
}
|
||||
return $this->createArrayFromValues($values);
|
||||
}
|
||||
/**
|
||||
* @param mixed[] $values
|
||||
* @return ArrayItemNode[]
|
||||
*/
|
||||
public function createArrayFromValues(array $values) : array
|
||||
{
|
||||
$arrayItemNodes = [];
|
||||
$naturalKey = 0;
|
||||
foreach ($values as $key => $value) {
|
||||
if (\is_array($value)) {
|
||||
[$nestedKey, $nestedValue] = $value;
|
||||
if ($nestedKey instanceof ConstExprIntegerNode) {
|
||||
$nestedKey = $nestedKey->value;
|
||||
}
|
||||
// curly candidate?
|
||||
$arrayItemNodes[] = $this->createArrayItemFromKeyAndValue($nestedKey, $nestedValue);
|
||||
} else {
|
||||
$arrayItemNodes[] = $this->createArrayItemFromKeyAndValue($key !== $naturalKey ? $key : null, $value);
|
||||
}
|
||||
++$naturalKey;
|
||||
}
|
||||
return $arrayItemNodes;
|
||||
}
|
||||
/**
|
||||
* Mimics https://github.com/doctrine/annotations/blob/c66f06b7c83e9a2a7523351a9d5a4b55f885e574/lib/Doctrine/Common/Annotations/DocParser.php#L1354-L1385
|
||||
* @return array<null|mixed, mixed>
|
||||
@ -103,23 +129,51 @@ final class ArrayParser
|
||||
return [$key, $this->plainValueParser->parseValue($tokenIterator)];
|
||||
}
|
||||
/**
|
||||
* @param mixed[] $values
|
||||
* @return mixed[]
|
||||
* @return String_::KIND_SINGLE_QUOTED|String_::KIND_DOUBLE_QUOTED|null
|
||||
* @param mixed $val
|
||||
*/
|
||||
private function createArrayFromValues(array $values) : array
|
||||
private function resolveQuoteKind($val) : ?int
|
||||
{
|
||||
$array = [];
|
||||
foreach ($values as $value) {
|
||||
[$key, $val] = $value;
|
||||
if ($key instanceof ConstExprIntegerNode) {
|
||||
$key = $key->value;
|
||||
}
|
||||
if ($key !== null) {
|
||||
$array[$key] = $val;
|
||||
} else {
|
||||
$array[] = $val;
|
||||
}
|
||||
if ($this->isQuotedWith($val, '"')) {
|
||||
return String_::KIND_DOUBLE_QUOTED;
|
||||
}
|
||||
return $array;
|
||||
if ($this->isQuotedWith($val, "'")) {
|
||||
return String_::KIND_SINGLE_QUOTED;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* @param mixed $key
|
||||
* @param mixed $value
|
||||
*/
|
||||
private function createArrayItemFromKeyAndValue($key, $value) : ArrayItemNode
|
||||
{
|
||||
$valueQuoteKind = $this->resolveQuoteKind($value);
|
||||
if (\is_string($value) && $valueQuoteKind === String_::KIND_DOUBLE_QUOTED) {
|
||||
// give raw value
|
||||
$value = \trim($value, '"');
|
||||
}
|
||||
$keyQuoteKind = $this->resolveQuoteKind($key);
|
||||
if (\is_string($key) && $keyQuoteKind === String_::KIND_DOUBLE_QUOTED) {
|
||||
// give raw value
|
||||
$key = \trim($key, '"');
|
||||
}
|
||||
if ($key !== null) {
|
||||
return new ArrayItemNode($value, $key, $valueQuoteKind, $keyQuoteKind);
|
||||
}
|
||||
return new ArrayItemNode($value, null, $valueQuoteKind, $keyQuoteKind);
|
||||
}
|
||||
/**
|
||||
* @param mixed $value
|
||||
*/
|
||||
private function isQuotedWith($value, string $quotes) : bool
|
||||
{
|
||||
if (!\is_string($value)) {
|
||||
return \false;
|
||||
}
|
||||
if (\strncmp($value, $quotes, \strlen($quotes)) !== 0) {
|
||||
return \false;
|
||||
}
|
||||
return \substr_compare($value, $quotes, -\strlen($quotes)) === 0;
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\ThrowsTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
|
||||
use PHPStan\PhpDocParser\Lexer\Lexer;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
use Rector\BetterPhpDocParser\PhpDocNodeVisitor\ChangedPhpDocNodeVisitor;
|
||||
@ -194,8 +195,8 @@ final class PhpDocInfoPrinter
|
||||
return $this->standardPrintPhpDocChildNode($phpDocChildNode);
|
||||
}
|
||||
if ($phpDocChildNode->value instanceof DoctrineAnnotationTagValueNode && $shouldReprintChildNode) {
|
||||
$silentValue = $phpDocChildNode->value->getSilentValue();
|
||||
if ($silentValue === null) {
|
||||
$silentValueArrayItemNode = $phpDocChildNode->value->getSilentValue();
|
||||
if (!$silentValueArrayItemNode instanceof ArrayItemNode) {
|
||||
$printedNode = (string) $phpDocChildNode;
|
||||
// remove extra space between tags
|
||||
$printedNode = Strings::replace($printedNode, self::TAG_AND_SPACE_REGEX, '$1(');
|
||||
|
@ -3,26 +3,20 @@
|
||||
declare (strict_types=1);
|
||||
namespace Rector\BetterPhpDocParser\ValueObject\PhpDoc\DoctrineAnnotation;
|
||||
|
||||
use RectorPrefix202208\Nette\Utils\Strings;
|
||||
use PHPStan\PhpDocParser\Ast\Node;
|
||||
use PHPStan\PhpDocParser\Ast\NodeAttributes;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocAttributeKey;
|
||||
use Rector\Core\Util\StringUtils;
|
||||
abstract class AbstractValuesAwareNode implements PhpDocTagValueNode
|
||||
{
|
||||
use NodeAttributes;
|
||||
/**
|
||||
* @var string
|
||||
* @see https://regex101.com/r/H6JjOG/3
|
||||
*/
|
||||
private const UNQUOTED_VALUE_REGEX = '#^("|\')(?<content>.*?)("|\')$#';
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $hasChanged = \false;
|
||||
/**
|
||||
* @var array<(string | int), mixed>
|
||||
* @var ArrayItemNode[]
|
||||
*/
|
||||
public $values = [];
|
||||
/**
|
||||
@ -34,7 +28,7 @@ abstract class AbstractValuesAwareNode implements PhpDocTagValueNode
|
||||
*/
|
||||
protected $silentKey;
|
||||
/**
|
||||
* @param array<string|int, mixed> $values Must be public so node traverser can go through them
|
||||
* @param ArrayItemNode[] $values Must be public so node traverser can go through them
|
||||
*/
|
||||
public function __construct(array $values = [], ?string $originalContent = null, ?string $silentKey = null)
|
||||
{
|
||||
@ -42,144 +36,68 @@ abstract class AbstractValuesAwareNode implements PhpDocTagValueNode
|
||||
$this->originalContent = $originalContent;
|
||||
$this->silentKey = $silentKey;
|
||||
}
|
||||
public function removeValue(string $key) : void
|
||||
public function removeValue(string $desiredKey) : void
|
||||
{
|
||||
$quotedKey = '"' . $key . '"';
|
||||
// isset?
|
||||
if (!isset($this->values[$key]) && !isset($this->values[$quotedKey])) {
|
||||
return;
|
||||
foreach ($this->values as $key => $value) {
|
||||
if ($value->key !== $desiredKey) {
|
||||
continue;
|
||||
}
|
||||
unset($this->values[$key]);
|
||||
// invoke reprint
|
||||
$this->setAttribute(PhpDocAttributeKey::ORIG_NODE, null);
|
||||
}
|
||||
unset($this->values[$key]);
|
||||
unset($this->values[$quotedKey]);
|
||||
// invoke reprint
|
||||
$this->setAttribute(PhpDocAttributeKey::ORIG_NODE, null);
|
||||
}
|
||||
/**
|
||||
* @return mixed[]
|
||||
* @return ArrayItemNode[]
|
||||
*/
|
||||
public function getValues() : array
|
||||
{
|
||||
return $this->values;
|
||||
}
|
||||
/**
|
||||
* @return mixed|Node|null
|
||||
* @param string|int $key
|
||||
* @return ArrayItemNode[]
|
||||
*/
|
||||
public function getValue($key)
|
||||
public function getValuesWithSilentKey() : array
|
||||
{
|
||||
// to allow false as default
|
||||
if (!\array_key_exists($key, $this->values)) {
|
||||
return null;
|
||||
if ($this->silentKey === null) {
|
||||
return $this->values;
|
||||
}
|
||||
return $this->values[$key];
|
||||
}
|
||||
/**
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function changeValue(string $key, $value) : void
|
||||
{
|
||||
// is quoted?
|
||||
if (isset($this->values[$key]) && \is_string($this->values[$key]) && StringUtils::isMatch($this->values[$key], self::UNQUOTED_VALUE_REGEX)) {
|
||||
$value = '"' . $value . '"';
|
||||
}
|
||||
$this->values[$key] = $value;
|
||||
// invoke reprint
|
||||
$this->setAttribute(PhpDocAttributeKey::ORIG_NODE, null);
|
||||
}
|
||||
/**
|
||||
* @return mixed|null
|
||||
* @param string|int $key
|
||||
*/
|
||||
public function getValueWithoutQuotes($key)
|
||||
{
|
||||
$value = $this->getValue($key);
|
||||
if ($value === null) {
|
||||
return null;
|
||||
}
|
||||
return $this->removeQuotes($value);
|
||||
}
|
||||
/**
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function changeSilentValue($value) : void
|
||||
{
|
||||
// is quoted?
|
||||
if (StringUtils::isMatch($this->values[0], self::UNQUOTED_VALUE_REGEX)) {
|
||||
$value = '"' . $value . '"';
|
||||
}
|
||||
$this->values[0] = $value;
|
||||
$this->hasChanged = \true;
|
||||
// invoke reprint
|
||||
$this->setAttribute(PhpDocAttributeKey::ORIG_NODE, null);
|
||||
}
|
||||
/**
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function getSilentValue()
|
||||
{
|
||||
$value = $this->values[0] ?? null;
|
||||
if ($value === null) {
|
||||
return null;
|
||||
}
|
||||
return $this->removeQuotes($value);
|
||||
}
|
||||
/**
|
||||
* Useful for attributes
|
||||
* @return array<int|string, mixed>
|
||||
*/
|
||||
public function getValuesWithExplicitSilentAndWithoutQuotes() : array
|
||||
{
|
||||
$explicitKeysValues = [];
|
||||
foreach (\array_keys($this->values) as $key) {
|
||||
$valueWithoutQuotes = $this->getValueWithoutQuotes($key);
|
||||
if (\is_int($key) && $this->silentKey !== null) {
|
||||
$explicitKeysValues[$this->silentKey] = $valueWithoutQuotes;
|
||||
} else {
|
||||
// to keep constant keys strings if quoted
|
||||
if (\is_string($key) && \strpos($key, '::') === \false) {
|
||||
$key = $this->removeQuotes($key);
|
||||
}
|
||||
$explicitKeysValues[$key] = $valueWithoutQuotes;
|
||||
// to keep original values untouched, unless not changed
|
||||
$silentKeyAwareValues = $this->values;
|
||||
foreach ($silentKeyAwareValues as $silentKeyAwareValue) {
|
||||
if ($silentKeyAwareValue->key === null) {
|
||||
$silentKeyAwareValue->key = $this->silentKey;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $explicitKeysValues;
|
||||
return $silentKeyAwareValues;
|
||||
}
|
||||
/**
|
||||
* @return mixed|Node|null|ArrayItemNode
|
||||
* @param string|int $desiredKey
|
||||
*/
|
||||
public function getValue($desiredKey)
|
||||
{
|
||||
foreach ($this->values as $value) {
|
||||
if ($value->key === $desiredKey) {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public function getSilentValue() : ?ArrayItemNode
|
||||
{
|
||||
foreach ($this->values as $value) {
|
||||
if ($value->key === null) {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public function markAsChanged() : void
|
||||
{
|
||||
$this->hasChanged = \true;
|
||||
}
|
||||
/**
|
||||
* @param mixed|string $value
|
||||
* @return mixed|string
|
||||
*/
|
||||
protected function removeQuotes($value)
|
||||
{
|
||||
if (\is_array($value)) {
|
||||
return $this->removeQuotesFromArray($value);
|
||||
}
|
||||
if (!\is_string($value)) {
|
||||
return $value;
|
||||
}
|
||||
$matches = Strings::match($value, self::UNQUOTED_VALUE_REGEX);
|
||||
if ($matches === null) {
|
||||
return $value;
|
||||
}
|
||||
return $matches['content'];
|
||||
}
|
||||
/**
|
||||
* @param mixed[] $values
|
||||
* @return array<int|string, mixed>
|
||||
*/
|
||||
protected function removeQuotesFromArray(array $values) : array
|
||||
{
|
||||
$unquotedArray = [];
|
||||
foreach ($values as $key => $value) {
|
||||
$unquotedKey = $this->removeQuotes($key);
|
||||
$unquotedValue = $this->removeQuotes($value);
|
||||
$unquotedArray[$unquotedKey] = $unquotedValue;
|
||||
}
|
||||
return $unquotedArray;
|
||||
}
|
||||
/**
|
||||
* @param mixed[] $values
|
||||
*/
|
||||
|
@ -3,29 +3,30 @@
|
||||
declare (strict_types=1);
|
||||
namespace Rector\BetterPhpDocParser\ValueObject\PhpDoc\DoctrineAnnotation;
|
||||
|
||||
use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode;
|
||||
use Stringable;
|
||||
use RectorPrefix202208\Webmozart\Assert\Assert;
|
||||
final class CurlyListNode extends \Rector\BetterPhpDocParser\ValueObject\PhpDoc\DoctrineAnnotation\AbstractValuesAwareNode
|
||||
{
|
||||
/**
|
||||
* @var ArrayItemNode[]
|
||||
* @readonly
|
||||
*/
|
||||
private $arrayItemNodes = [];
|
||||
/**
|
||||
* @param ArrayItemNode[] $arrayItemNodes
|
||||
*/
|
||||
public function __construct(array $arrayItemNodes = [])
|
||||
{
|
||||
$this->arrayItemNodes = $arrayItemNodes;
|
||||
Assert::allIsInstanceOf($this->arrayItemNodes, ArrayItemNode::class);
|
||||
parent::__construct($this->arrayItemNodes);
|
||||
}
|
||||
public function __toString() : string
|
||||
{
|
||||
// possibly list items
|
||||
return $this->implode($this->values);
|
||||
}
|
||||
/**
|
||||
* @param mixed $value
|
||||
*/
|
||||
private function stringifyValue($value) : string
|
||||
{
|
||||
if ($value === \false) {
|
||||
return 'false';
|
||||
}
|
||||
if ($value === \true) {
|
||||
return 'true';
|
||||
}
|
||||
if (\is_array($value)) {
|
||||
return $this->implode($value);
|
||||
}
|
||||
return (string) $value;
|
||||
}
|
||||
/**
|
||||
* @param mixed[] $array
|
||||
*/
|
||||
@ -36,9 +37,9 @@ final class CurlyListNode extends \Rector\BetterPhpDocParser\ValueObject\PhpDoc\
|
||||
$lastItemKey = \key($array);
|
||||
foreach ($array as $key => $value) {
|
||||
if (\is_int($key)) {
|
||||
$itemContents .= $this->stringifyValue($value);
|
||||
$itemContents .= (string) $value;
|
||||
} else {
|
||||
$itemContents .= $key . '=' . $this->stringifyValue($value);
|
||||
$itemContents .= $key . '=' . $value;
|
||||
}
|
||||
if ($lastItemKey !== $key) {
|
||||
$itemContents .= ', ';
|
||||
|
@ -5,6 +5,7 @@ namespace Rector\PhpAttribute;
|
||||
|
||||
use PhpParser\BuilderHelpers;
|
||||
use PhpParser\Node\Expr;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
|
||||
use Rector\PhpAttribute\Contract\AnnotationToAttributeMapperInterface;
|
||||
use Rector\PhpAttribute\Enum\DocTagNodeState;
|
||||
@ -26,7 +27,7 @@ final class AnnotationToAttributeMapper
|
||||
$this->annotationToAttributeMappers = $annotationToAttributeMappers;
|
||||
}
|
||||
/**
|
||||
* @return \PhpParser\Node\Expr|string
|
||||
* @return Expr|DocTagNodeState::REMOVE_ARRAY
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function map($value)
|
||||
@ -43,6 +44,9 @@ final class AnnotationToAttributeMapper
|
||||
if ($value instanceof DoctrineAnnotationTagValueNode) {
|
||||
return DocTagNodeState::REMOVE_ARRAY;
|
||||
}
|
||||
if ($value instanceof ArrayItemNode) {
|
||||
return BuilderHelpers::normalizeValue((string) $value);
|
||||
}
|
||||
// fallback
|
||||
return BuilderHelpers::normalizeValue($value);
|
||||
}
|
||||
|
@ -47,17 +47,20 @@ final class ArrayAnnotationToAttributeMapper implements AnnotationToAttributeMap
|
||||
if ($valueExpr === DocTagNodeState::REMOVE_ARRAY) {
|
||||
continue;
|
||||
}
|
||||
Assert::isInstanceOf($valueExpr, Expr::class);
|
||||
// remove value
|
||||
if ($this->isRemoveArrayPlaceholder($singleValue)) {
|
||||
continue;
|
||||
}
|
||||
$keyExpr = null;
|
||||
if (!\is_int($key)) {
|
||||
$keyExpr = $this->annotationToAttributeMapper->map($key);
|
||||
Assert::isInstanceOf($keyExpr, Expr::class);
|
||||
if ($valueExpr instanceof ArrayItem) {
|
||||
$arrayItems[] = $valueExpr;
|
||||
} else {
|
||||
$keyExpr = null;
|
||||
if (!\is_int($key)) {
|
||||
$keyExpr = $this->annotationToAttributeMapper->map($key);
|
||||
Assert::isInstanceOf($keyExpr, Expr::class);
|
||||
}
|
||||
$arrayItems[] = new ArrayItem($valueExpr, $keyExpr);
|
||||
}
|
||||
$arrayItems[] = new ArrayItem($valueExpr, $keyExpr);
|
||||
}
|
||||
return new Array_($arrayItems);
|
||||
}
|
||||
|
@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace Rector\PhpAttribute\AnnotationToAttributeMapper;
|
||||
|
||||
use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Expr\ArrayItem;
|
||||
use PhpParser\Node\Scalar\String_;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode;
|
||||
use Rector\PhpAttribute\AnnotationToAttributeMapper;
|
||||
use Rector\PhpAttribute\Contract\AnnotationToAttributeMapperInterface;
|
||||
use RectorPrefix202208\Symfony\Contracts\Service\Attribute\Required;
|
||||
/**
|
||||
* @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 ($arrayItemNode->key !== null) {
|
||||
switch ($arrayItemNode->kindKeyQuoted) {
|
||||
case String_::KIND_SINGLE_QUOTED:
|
||||
$keyValue = "'" . $arrayItemNode->key . "'";
|
||||
break;
|
||||
case String_::KIND_DOUBLE_QUOTED:
|
||||
$keyValue = '"' . $arrayItemNode->key . '"';
|
||||
break;
|
||||
default:
|
||||
$keyValue = $arrayItemNode->key;
|
||||
break;
|
||||
}
|
||||
/** @var Expr $keyExpr */
|
||||
$keyExpr = $this->annotationToAttributeMapper->map($keyValue);
|
||||
} else {
|
||||
$keyExpr = null;
|
||||
}
|
||||
// @todo how to skip natural integer keys?
|
||||
return new ArrayItem($valueExpr, $keyExpr);
|
||||
}
|
||||
}
|
@ -43,7 +43,7 @@ final class CurlyListNodeAnnotationToAttributeMapper implements AnnotationToAttr
|
||||
public function map($value) : \PhpParser\Node\Expr
|
||||
{
|
||||
$arrayItems = [];
|
||||
$valuesWithExplicitSilent = $value->getValuesWithExplicitSilentAndWithoutQuotes();
|
||||
$valuesWithExplicitSilent = $value->getValues();
|
||||
$loop = -1;
|
||||
foreach ($valuesWithExplicitSilent as $key => $singleValue) {
|
||||
$valueExpr = $this->annotationToAttributeMapper->map($singleValue);
|
||||
@ -51,7 +51,6 @@ final class CurlyListNodeAnnotationToAttributeMapper implements AnnotationToAttr
|
||||
if ($valueExpr === DocTagNodeState::REMOVE_ARRAY) {
|
||||
continue;
|
||||
}
|
||||
Assert::isInstanceOf($valueExpr, Expr::class);
|
||||
if (!\is_int($key)) {
|
||||
$keyExpr = $this->annotationToAttributeMapper->map($key);
|
||||
Assert::isInstanceOf($keyExpr, Expr::class);
|
||||
|
@ -64,7 +64,7 @@ final class DoctrineAnnotationAnnotationToAttributeMapper implements AnnotationT
|
||||
$annotationShortName = $this->resolveAnnotationName($value);
|
||||
$values = $value->getValues();
|
||||
if ($values !== []) {
|
||||
$argValues = $this->annotationToAttributeMapper->map($value->getValuesWithExplicitSilentAndWithoutQuotes());
|
||||
$argValues = $this->annotationToAttributeMapper->map($value->getValues());
|
||||
if ($argValues instanceof Array_) {
|
||||
// create named args
|
||||
$args = $this->attributeArrayNameInliner->inlineArrayToArgs($argValues);
|
||||
|
@ -7,6 +7,7 @@ use PhpParser\Node\Arg;
|
||||
use PhpParser\Node\Expr\Array_;
|
||||
use PhpParser\Node\Expr\ArrayItem;
|
||||
use PhpParser\Node\Identifier;
|
||||
use PhpParser\Node\Scalar\LNumber;
|
||||
use PhpParser\Node\Scalar\String_;
|
||||
use Rector\Core\Exception\NotImplementedYetException;
|
||||
use RectorPrefix202208\Webmozart\Assert\Assert;
|
||||
@ -55,7 +56,9 @@ final class AttributeArrayNameInliner
|
||||
// matching top root array key
|
||||
if ($arg->value instanceof ArrayItem) {
|
||||
$arrayItem = $arg->value;
|
||||
if ($arrayItem->key instanceof String_) {
|
||||
if ($arrayItem->key instanceof LNumber) {
|
||||
$newArgs[] = new Arg($arrayItem->value);
|
||||
} elseif ($arrayItem->key instanceof String_) {
|
||||
$arrayItemString = $arrayItem->key;
|
||||
$newArgs[] = new Arg($arrayItem->value, \false, \false, [], new Identifier($arrayItemString->value));
|
||||
} elseif ($arrayItem->key === null) {
|
||||
|
@ -9,6 +9,7 @@ use PhpParser\Node\AttributeGroup;
|
||||
use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Name\FullyQualified;
|
||||
use PhpParser\Node\Stmt\Use_;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
|
||||
use Rector\Php80\ValueObject\AnnotationToAttribute;
|
||||
use Rector\PhpAttribute\AnnotationToAttributeMapper;
|
||||
@ -77,7 +78,7 @@ final class PhpAttributeGroupFactory
|
||||
*/
|
||||
public function create(DoctrineAnnotationTagValueNode $doctrineAnnotationTagValueNode, AnnotationToAttribute $annotationToAttribute, array $uses) : AttributeGroup
|
||||
{
|
||||
$values = $doctrineAnnotationTagValueNode->getValuesWithExplicitSilentAndWithoutQuotes();
|
||||
$values = $doctrineAnnotationTagValueNode->getValuesWithSilentKey();
|
||||
$args = $this->createArgsFromItems($values, $annotationToAttribute->getAttributeClass());
|
||||
$args = $this->attributeArrayNameInliner->inlineArrayToArgs($args);
|
||||
$attributeName = $this->attributeNameFactory->create($annotationToAttribute, $doctrineAnnotationTagValueNode, $uses);
|
||||
@ -85,14 +86,15 @@ final class PhpAttributeGroupFactory
|
||||
return new AttributeGroup([$attribute]);
|
||||
}
|
||||
/**
|
||||
* @param mixed[] $items
|
||||
* @param ArrayItemNode[] $items
|
||||
* @return Arg[]
|
||||
*/
|
||||
public function createArgsFromItems(array $items, string $attributeClass) : array
|
||||
{
|
||||
/** @var Expr[]|Expr\Array_ $items */
|
||||
$items = $this->annotationToAttributeMapper->map($items);
|
||||
$items = $this->exprParameterReflectionTypeCorrector->correctItemsByAttributeClass($items, $attributeClass);
|
||||
return $this->namedArgsFactory->createFromValues($items);
|
||||
/** @var Expr[]|Expr\Array_ $mappedItems */
|
||||
$mappedItems = $this->annotationToAttributeMapper->map($items);
|
||||
$mappedItems = $this->exprParameterReflectionTypeCorrector->correctItemsByAttributeClass($mappedItems, $attributeClass);
|
||||
// the key here should contain the named argument
|
||||
return $this->namedArgsFactory->createFromValues($mappedItems);
|
||||
}
|
||||
}
|
||||
|
@ -11,8 +11,10 @@ use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Name;
|
||||
use PhpParser\Node\Name\FullyQualified;
|
||||
use PhpParser\Node\Stmt\Use_;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDoc\DoctrineAnnotation\CurlyListNode;
|
||||
use Rector\Core\Exception\ShouldNotHappenException;
|
||||
use Rector\Php80\ValueObject\NestedAnnotationToAttribute;
|
||||
use Rector\PhpAttribute\AnnotationToAttributeMapper;
|
||||
use Rector\PhpAttribute\AttributeArrayNameInliner;
|
||||
@ -62,7 +64,8 @@ final class PhpNestedAttributeGroupFactory
|
||||
*/
|
||||
public function create(DoctrineAnnotationTagValueNode $doctrineAnnotationTagValueNode, NestedAnnotationToAttribute $nestedAnnotationToAttribute, array $uses) : AttributeGroup
|
||||
{
|
||||
$values = $doctrineAnnotationTagValueNode->getValuesWithExplicitSilentAndWithoutQuotes();
|
||||
$values = $doctrineAnnotationTagValueNode->getValues();
|
||||
$values = $this->removeItems($values, $nestedAnnotationToAttribute);
|
||||
$args = $this->createArgsFromItems($values, $nestedAnnotationToAttribute);
|
||||
$args = $this->attributeArrayNameInliner->inlineArrayToArgs($args);
|
||||
$attributeName = $this->attributeNameFactory->create($nestedAnnotationToAttribute, $doctrineAnnotationTagValueNode, $uses);
|
||||
@ -75,40 +78,46 @@ final class PhpNestedAttributeGroupFactory
|
||||
public function createNested(DoctrineAnnotationTagValueNode $doctrineAnnotationTagValueNode, NestedAnnotationToAttribute $nestedAnnotationToAttribute) : array
|
||||
{
|
||||
$attributeGroups = [];
|
||||
$values = $doctrineAnnotationTagValueNode->getValuesWithExplicitSilentAndWithoutQuotes();
|
||||
foreach ($nestedAnnotationToAttribute->getAnnotationPropertiesToAttributeClasses() as $itemName => $nestedAttributeClass) {
|
||||
$nestedValues = $values[$itemName] ?? null;
|
||||
if ($nestedValues === null) {
|
||||
if ($nestedAnnotationToAttribute->hasExplicitParameters()) {
|
||||
return $this->createFromExplicitProperties($nestedAnnotationToAttribute, $doctrineAnnotationTagValueNode);
|
||||
}
|
||||
$nestedAttributeClass = $nestedAnnotationToAttribute->getAnnotationPropertiesToAttributeClasses()[0];
|
||||
foreach ($doctrineAnnotationTagValueNode->values as $arrayItemNode) {
|
||||
$nestedDoctrineAnnotationTagValueNode = $arrayItemNode->value;
|
||||
if (!$nestedDoctrineAnnotationTagValueNode instanceof CurlyListNode) {
|
||||
continue;
|
||||
}
|
||||
if ($nestedValues instanceof CurlyListNode) {
|
||||
foreach ($nestedValues->getValues() as $nestedDoctrineAnnotationTagValueNode) {
|
||||
/** @var DoctrineAnnotationTagValueNode $nestedDoctrineAnnotationTagValueNode */
|
||||
$args = $this->createArgsFromItems($nestedDoctrineAnnotationTagValueNode->getValuesWithExplicitSilentAndWithoutQuotes(), $nestedAnnotationToAttribute);
|
||||
$args = $this->attributeArrayNameInliner->inlineArrayToArgs($args);
|
||||
$originalIdentifier = $nestedDoctrineAnnotationTagValueNode->identifierTypeNode->name;
|
||||
$attributeName = $this->resolveAliasedAttributeName($originalIdentifier, $nestedAttributeClass);
|
||||
$attribute = new Attribute($attributeName, $args);
|
||||
$attributeGroups[] = new AttributeGroup([$attribute]);
|
||||
foreach ($nestedDoctrineAnnotationTagValueNode->values as $nestedArrayItemNode) {
|
||||
if (!$nestedArrayItemNode->value instanceof DoctrineAnnotationTagValueNode) {
|
||||
continue;
|
||||
}
|
||||
$attributeArgs = $this->createAttributeArgs($nestedArrayItemNode->value, $nestedAnnotationToAttribute);
|
||||
$originalIdentifier = $doctrineAnnotationTagValueNode->identifierTypeNode->name;
|
||||
$attributeName = $this->resolveAliasedAttributeName($originalIdentifier, $nestedAttributeClass);
|
||||
$attribute = new Attribute($attributeName, $attributeArgs);
|
||||
$attributeGroups[] = new AttributeGroup([$attribute]);
|
||||
}
|
||||
}
|
||||
return $attributeGroups;
|
||||
}
|
||||
/**
|
||||
* @param mixed[] $items
|
||||
* @return Arg[]
|
||||
*/
|
||||
private function createArgsFromItems(array $items, NestedAnnotationToAttribute $nestedAnnotationToAttribute) : array
|
||||
public function createAttributeArgs(DoctrineAnnotationTagValueNode $nestedDoctrineAnnotationTagValueNode, NestedAnnotationToAttribute $nestedAnnotationToAttribute) : array
|
||||
{
|
||||
// remove nested items
|
||||
foreach (\array_keys($nestedAnnotationToAttribute->getAnnotationPropertiesToAttributeClasses()) as $itemName) {
|
||||
unset($items[$itemName]);
|
||||
}
|
||||
/** @var Expr[]|Expr\Array_ $items */
|
||||
$items = $this->annotationToAttributeMapper->map($items);
|
||||
$items = $this->exprParameterReflectionTypeCorrector->correctItemsByAttributeClass($items, $nestedAnnotationToAttribute->getTag());
|
||||
return $this->namedArgsFactory->createFromValues($items);
|
||||
$args = $this->createArgsFromItems($nestedDoctrineAnnotationTagValueNode->getValues(), $nestedAnnotationToAttribute);
|
||||
return $this->attributeArrayNameInliner->inlineArrayToArgs($args);
|
||||
}
|
||||
/**
|
||||
* @param ArrayItemNode[] $arrayItemNodes
|
||||
* @return Arg[]
|
||||
*/
|
||||
private function createArgsFromItems(array $arrayItemNodes, NestedAnnotationToAttribute $nestedAnnotationToAttribute) : array
|
||||
{
|
||||
/** @var Expr[]|Expr\Array_ $arrayItemNodes */
|
||||
$arrayItemNodes = $this->annotationToAttributeMapper->map($arrayItemNodes);
|
||||
$arrayItemNodes = $this->exprParameterReflectionTypeCorrector->correctItemsByAttributeClass($arrayItemNodes, $nestedAnnotationToAttribute->getTag());
|
||||
return $this->namedArgsFactory->createFromValues($arrayItemNodes);
|
||||
}
|
||||
/**
|
||||
* @todo improve this hardcoded approach later
|
||||
@ -129,4 +138,48 @@ final class PhpNestedAttributeGroupFactory
|
||||
}
|
||||
return new FullyQualified($nestedAttributeClass);
|
||||
}
|
||||
/**
|
||||
* @param ArrayItemNode[] $arrayItemNodes
|
||||
* @return ArrayItemNode[]
|
||||
*/
|
||||
private function removeItems(array $arrayItemNodes, NestedAnnotationToAttribute $nestedAnnotationToAttribute) : array
|
||||
{
|
||||
foreach (\array_keys($nestedAnnotationToAttribute->getAnnotationPropertiesToAttributeClasses()) as $itemToRemoveName) {
|
||||
foreach ($arrayItemNodes as $key => $arrayItemNode) {
|
||||
if ($arrayItemNode->key !== $itemToRemoveName) {
|
||||
continue;
|
||||
}
|
||||
unset($arrayItemNodes[$key]);
|
||||
}
|
||||
}
|
||||
return $arrayItemNodes;
|
||||
}
|
||||
/**
|
||||
* @return AttributeGroup[]
|
||||
*/
|
||||
private function createFromExplicitProperties(NestedAnnotationToAttribute $nestedAnnotationToAttribute, DoctrineAnnotationTagValueNode $doctrineAnnotationTagValueNode) : array
|
||||
{
|
||||
$attributeGroups = [];
|
||||
foreach ($nestedAnnotationToAttribute->getAnnotationPropertiesToAttributeClasses() as $itemName => $nestedAttributeClass) {
|
||||
$nestedArrayItemNode = $doctrineAnnotationTagValueNode->getValue($itemName);
|
||||
if (!$nestedArrayItemNode instanceof ArrayItemNode) {
|
||||
continue;
|
||||
}
|
||||
if (!$nestedArrayItemNode->value instanceof CurlyListNode) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
foreach ($nestedArrayItemNode->value->getValues() as $arrayItemNode) {
|
||||
$nestedDoctrineAnnotationTagValueNode = $arrayItemNode->value;
|
||||
if (!$nestedDoctrineAnnotationTagValueNode instanceof DoctrineAnnotationTagValueNode) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
$attributeArgs = $this->createAttributeArgs($nestedDoctrineAnnotationTagValueNode, $nestedAnnotationToAttribute);
|
||||
$originalIdentifier = $nestedDoctrineAnnotationTagValueNode->identifierTypeNode->name;
|
||||
$attributeName = $this->resolveAliasedAttributeName($originalIdentifier, $nestedAttributeClass);
|
||||
$attribute = new Attribute($attributeName, $attributeArgs);
|
||||
$attributeGroups[] = new AttributeGroup([$attribute]);
|
||||
}
|
||||
}
|
||||
return $attributeGroups;
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ declare (strict_types=1);
|
||||
namespace Rector\Php80\NodeAnalyzer;
|
||||
|
||||
use PhpParser\Node\Expr\ClassConstFetch;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode;
|
||||
use Rector\Core\PhpParser\Node\NodeFactory;
|
||||
final class AnnotationTargetResolver
|
||||
{
|
||||
@ -30,17 +31,19 @@ final class AnnotationTargetResolver
|
||||
$this->nodeFactory = $nodeFactory;
|
||||
}
|
||||
/**
|
||||
* @param array<int|string, mixed> $targetValues
|
||||
* @param ArrayItemNode[] $targetValues
|
||||
* @return ClassConstFetch[]
|
||||
*/
|
||||
public function resolveFlagClassConstFetches(array $targetValues) : array
|
||||
{
|
||||
$classConstFetches = [];
|
||||
foreach (self::TARGET_TO_CONSTANT_MAP as $target => $constant) {
|
||||
if (!\in_array($target, $targetValues, \true)) {
|
||||
continue;
|
||||
foreach ($targetValues as $targetValue) {
|
||||
foreach (self::TARGET_TO_CONSTANT_MAP as $target => $constant) {
|
||||
if ($target !== $targetValue->value) {
|
||||
continue;
|
||||
}
|
||||
$classConstFetches[] = $this->nodeFactory->createClassConstFetch('Attribute', $constant);
|
||||
}
|
||||
$classConstFetches[] = $this->nodeFactory->createClassConstFetch('Attribute', $constant);
|
||||
}
|
||||
return $classConstFetches;
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PhpParser\Node\Stmt\Function_;
|
||||
use PhpParser\Node\Stmt\Property;
|
||||
use PhpParser\Node\Stmt\Use_;
|
||||
use PHPStan\PhpDocParser\Ast\Node as DocNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\GenericTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
|
||||
@ -27,7 +28,6 @@ use Rector\Php80\NodeManipulator\AttributeGroupNamedArgumentManipulator;
|
||||
use Rector\Php80\ValueObject\AnnotationToAttribute;
|
||||
use Rector\Php80\ValueObject\DoctrineTagAndAnnotationToAttribute;
|
||||
use Rector\PhpAttribute\NodeFactory\PhpAttributeGroupFactory;
|
||||
//use Rector\PhpAttribute\UnwrapableAnnotationAnalyzer;
|
||||
use Rector\VersionBonding\Contract\MinPhpVersionInterface;
|
||||
use RectorPrefix202208\Symplify\Astral\PhpDocParser\PhpDocNodeTraverser;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample;
|
||||
@ -122,7 +122,7 @@ CODE_SAMPLE
|
||||
return null;
|
||||
}
|
||||
$uses = $this->useImportsResolver->resolveBareUsesForNode($node);
|
||||
// 1. generic tags
|
||||
// 1. bare tags without annotation class, e.g. "@inject"
|
||||
$genericAttributeGroups = $this->processGenericTags($phpDocInfo);
|
||||
// 2. Doctrine annotation classes
|
||||
$annotationAttributeGroups = $this->processDoctrineAnnotationClasses($phpDocInfo, $uses);
|
||||
@ -179,7 +179,7 @@ CODE_SAMPLE
|
||||
return $attributeGroups;
|
||||
}
|
||||
/**
|
||||
* @param Node\Stmt\Use_[] $uses
|
||||
* @param Use_[] $uses
|
||||
* @return AttributeGroup[]
|
||||
*/
|
||||
private function processDoctrineAnnotationClasses(PhpDocInfo $phpDocInfo, array $uses) : array
|
||||
|
@ -8,6 +8,7 @@ use PhpParser\Node\Arg;
|
||||
use PhpParser\Node\AttributeGroup;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PHPStan\Type\MixedType;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTagRemover;
|
||||
@ -177,12 +178,8 @@ CODE_SAMPLE
|
||||
if ($this->shouldRemoveAnnotations) {
|
||||
$this->phpDocTagRemover->removeTagValueFromNode($phpDocInfo, $targetDoctrineAnnotationTagValueNode);
|
||||
}
|
||||
$targets = $targetDoctrineAnnotationTagValueNode->getSilentValue();
|
||||
if ($targets instanceof CurlyListNode) {
|
||||
$targetValues = $targets->getValuesWithExplicitSilentAndWithoutQuotes();
|
||||
} elseif (\is_string($targets)) {
|
||||
$targetValues = [$targets];
|
||||
} else {
|
||||
$targetValues = $this->resolveTargetValues($targetDoctrineAnnotationTagValueNode);
|
||||
if ($targetValues === []) {
|
||||
return;
|
||||
}
|
||||
$flagClassConstFetches = $this->annotationTargetResolver->resolveFlagClassConstFetches($targetValues);
|
||||
@ -200,4 +197,18 @@ CODE_SAMPLE
|
||||
// has attribute? skip it
|
||||
return $this->phpAttributeAnalyzer->hasPhpAttribute($class, AttributeName::ATTRIBUTE);
|
||||
}
|
||||
/**
|
||||
* @return ArrayItemNode[]
|
||||
*/
|
||||
private function resolveTargetValues(DoctrineAnnotationTagValueNode $targetDoctrineAnnotationTagValueNode) : array
|
||||
{
|
||||
$silentTargetsArrayItemNode = $targetDoctrineAnnotationTagValueNode->getSilentValue();
|
||||
if ($silentTargetsArrayItemNode instanceof ArrayItemNode) {
|
||||
if ($silentTargetsArrayItemNode->value instanceof CurlyListNode) {
|
||||
return $silentTargetsArrayItemNode->value->getValues();
|
||||
}
|
||||
return [$silentTargetsArrayItemNode];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ namespace Rector\Php80\ValueObject;
|
||||
|
||||
use Rector\Core\Validation\RectorAssert;
|
||||
use Rector\Php80\Contract\ValueObject\AnnotationToAttributeInterface;
|
||||
use RectorPrefix202208\Webmozart\Assert\Assert;
|
||||
final class NestedAnnotationToAttribute implements AnnotationToAttributeInterface
|
||||
{
|
||||
/**
|
||||
@ -31,6 +32,7 @@ final class NestedAnnotationToAttribute implements AnnotationToAttributeInterfac
|
||||
$this->annotationPropertiesToAttributeClasses = $annotationPropertiesToAttributeClasses;
|
||||
$this->removeOriginal = $removeOriginal;
|
||||
RectorAssert::className($tag);
|
||||
Assert::allString($annotationPropertiesToAttributeClasses);
|
||||
}
|
||||
public function getTag() : string
|
||||
{
|
||||
@ -51,4 +53,13 @@ final class NestedAnnotationToAttribute implements AnnotationToAttributeInterfac
|
||||
{
|
||||
return $this->removeOriginal;
|
||||
}
|
||||
public function hasExplicitParameters() : bool
|
||||
{
|
||||
foreach (\array_keys($this->annotationPropertiesToAttributeClasses) as $itemName) {
|
||||
if (\is_string($itemName)) {
|
||||
return \true;
|
||||
}
|
||||
}
|
||||
return \false;
|
||||
}
|
||||
}
|
||||
|
@ -17,12 +17,12 @@ final class VersionResolver
|
||||
* @api
|
||||
* @var string
|
||||
*/
|
||||
public const PACKAGE_VERSION = '6f530a1deff42a44f008e7f35c70501fd2635bae';
|
||||
public const PACKAGE_VERSION = 'a33b200e615b9451ba091e2724ab707f39198da7';
|
||||
/**
|
||||
* @api
|
||||
* @var string
|
||||
*/
|
||||
public const RELEASE_DATE = '2022-08-20 20:54:46';
|
||||
public const RELEASE_DATE = '2022-08-20 22:44:59';
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
|
2
vendor/autoload.php
vendored
2
vendor/autoload.php
vendored
@ -9,4 +9,4 @@ if (PHP_VERSION_ID < 50600) {
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInit88ac621afd5b114466a1fd611b35d804::getLoader();
|
||||
return ComposerAutoloaderInitbf3b0c550a047519dae38bd8e43006f2::getLoader();
|
||||
|
4
vendor/composer/autoload_classmap.php
vendored
4
vendor/composer/autoload_classmap.php
vendored
@ -1735,6 +1735,7 @@ return array(
|
||||
'Rector\\Doctrine\\NodeFactory\\ParamFactory' => $vendorDir . '/rector/rector-doctrine/src/NodeFactory/ParamFactory.php',
|
||||
'Rector\\Doctrine\\NodeFactory\\RepositoryAssignFactory' => $vendorDir . '/rector/rector-doctrine/src/NodeFactory/RepositoryAssignFactory.php',
|
||||
'Rector\\Doctrine\\NodeFactory\\RepositoryNodeFactory' => $vendorDir . '/rector/rector-doctrine/src/NodeFactory/RepositoryNodeFactory.php',
|
||||
'Rector\\Doctrine\\NodeFactory\\SluggableClassMethodFactory' => $vendorDir . '/rector/rector-doctrine/src/NodeFactory/SluggableClassMethodFactory.php',
|
||||
'Rector\\Doctrine\\NodeFactory\\TranslationClassNodeFactory' => $vendorDir . '/rector/rector-doctrine/src/NodeFactory/TranslationClassNodeFactory.php',
|
||||
'Rector\\Doctrine\\NodeFactory\\ValueAssignFactory' => $vendorDir . '/rector/rector-doctrine/src/NodeFactory/ValueAssignFactory.php',
|
||||
'Rector\\Doctrine\\NodeManipulator\\ColumnPropertyTypeResolver' => $vendorDir . '/rector/rector-doctrine/src/NodeManipulator/ColumnPropertyTypeResolver.php',
|
||||
@ -2424,6 +2425,7 @@ return array(
|
||||
'Rector\\Php82\\Rector\\Class_\\ReadOnlyClassRector' => $baseDir . '/rules/Php82/Rector/Class_/ReadOnlyClassRector.php',
|
||||
'Rector\\PhpAttribute\\AnnotationToAttributeMapper' => $baseDir . '/packages/PhpAttribute/AnnotationToAttributeMapper.php',
|
||||
'Rector\\PhpAttribute\\AnnotationToAttributeMapper\\ArrayAnnotationToAttributeMapper' => $baseDir . '/packages/PhpAttribute/AnnotationToAttributeMapper/ArrayAnnotationToAttributeMapper.php',
|
||||
'Rector\\PhpAttribute\\AnnotationToAttributeMapper\\ArrayItemNodeAnnotationToAttributeMapper' => $baseDir . '/packages/PhpAttribute/AnnotationToAttributeMapper/ArrayItemNodeAnnotationToAttributeMapper.php',
|
||||
'Rector\\PhpAttribute\\AnnotationToAttributeMapper\\ClassConstFetchAnnotationToAttributeMapper' => $baseDir . '/packages/PhpAttribute/AnnotationToAttributeMapper/ClassConstFetchAnnotationToAttributeMapper.php',
|
||||
'Rector\\PhpAttribute\\AnnotationToAttributeMapper\\ConstExprNodeAnnotationToAttributeMapper' => $baseDir . '/packages/PhpAttribute/AnnotationToAttributeMapper/ConstExprNodeAnnotationToAttributeMapper.php',
|
||||
'Rector\\PhpAttribute\\AnnotationToAttributeMapper\\CurlyListNodeAnnotationToAttributeMapper' => $baseDir . '/packages/PhpAttribute/AnnotationToAttributeMapper/CurlyListNodeAnnotationToAttributeMapper.php',
|
||||
@ -2638,7 +2640,6 @@ return array(
|
||||
'Rector\\Symfony\\NodeFactory\\Annotations\\DoctrineAnnotationFromNewFactory' => $vendorDir . '/rector/rector-symfony/src/NodeFactory/Annotations/DoctrineAnnotationFromNewFactory.php',
|
||||
'Rector\\Symfony\\NodeFactory\\Annotations\\DoctrineAnnotationKeyToValuesResolver' => $vendorDir . '/rector/rector-symfony/src/NodeFactory/Annotations/DoctrineAnnotationKeyToValuesResolver.php',
|
||||
'Rector\\Symfony\\NodeFactory\\Annotations\\StringValueQuoteWrapper' => $vendorDir . '/rector/rector-symfony/src/NodeFactory/Annotations/StringValueQuoteWrapper.php',
|
||||
'Rector\\Symfony\\NodeFactory\\Annotations\\ValueQuoteWrapper' => $vendorDir . '/rector/rector-symfony/src/NodeFactory/Annotations/ValueQuoteWrapper.php',
|
||||
'Rector\\Symfony\\NodeFactory\\ArrayFromCompactFactory' => $vendorDir . '/rector/rector-symfony/src/NodeFactory/ArrayFromCompactFactory.php',
|
||||
'Rector\\Symfony\\NodeFactory\\BareLogoutClassMethodFactory' => $vendorDir . '/rector/rector-symfony/src/NodeFactory/BareLogoutClassMethodFactory.php',
|
||||
'Rector\\Symfony\\NodeFactory\\EventReferenceFactory' => $vendorDir . '/rector/rector-symfony/src/NodeFactory/EventReferenceFactory.php',
|
||||
@ -2723,6 +2724,7 @@ return array(
|
||||
'Rector\\Symfony\\Rector\\StaticCall\\BinaryFileResponseCreateToNewInstanceRector' => $vendorDir . '/rector/rector-symfony/src/Rector/StaticCall/BinaryFileResponseCreateToNewInstanceRector.php',
|
||||
'Rector\\Symfony\\Rector\\StaticCall\\ParseFileRector' => $vendorDir . '/rector/rector-symfony/src/Rector/StaticCall/ParseFileRector.php',
|
||||
'Rector\\Symfony\\Rector\\StaticCall\\ProcessBuilderInstanceRector' => $vendorDir . '/rector/rector-symfony/src/Rector/StaticCall/ProcessBuilderInstanceRector.php',
|
||||
'Rector\\Symfony\\Rector\\StaticPropertyFetch\\KernelTestCaseContainerPropertyDeprecationRector' => $vendorDir . '/rector/rector-symfony/src/Rector/StaticPropertyFetch/KernelTestCaseContainerPropertyDeprecationRector.php',
|
||||
'Rector\\Symfony\\Set\\JMSSetList' => $vendorDir . '/rector/rector-symfony/src/Set/JMSSetList.php',
|
||||
'Rector\\Symfony\\Set\\SensiolabsSetList' => $vendorDir . '/rector/rector-symfony/src/Set/SensiolabsSetList.php',
|
||||
'Rector\\Symfony\\Set\\SwiftmailerSetList' => $vendorDir . '/rector/rector-symfony/src/Set/SwiftmailerSetList.php',
|
||||
|
14
vendor/composer/autoload_real.php
vendored
14
vendor/composer/autoload_real.php
vendored
@ -2,7 +2,7 @@
|
||||
|
||||
// autoload_real.php @generated by Composer
|
||||
|
||||
class ComposerAutoloaderInit88ac621afd5b114466a1fd611b35d804
|
||||
class ComposerAutoloaderInitbf3b0c550a047519dae38bd8e43006f2
|
||||
{
|
||||
private static $loader;
|
||||
|
||||
@ -22,19 +22,19 @@ class ComposerAutoloaderInit88ac621afd5b114466a1fd611b35d804
|
||||
return self::$loader;
|
||||
}
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInit88ac621afd5b114466a1fd611b35d804', 'loadClassLoader'), true, true);
|
||||
spl_autoload_register(array('ComposerAutoloaderInitbf3b0c550a047519dae38bd8e43006f2', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInit88ac621afd5b114466a1fd611b35d804', 'loadClassLoader'));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInitbf3b0c550a047519dae38bd8e43006f2', 'loadClassLoader'));
|
||||
|
||||
require __DIR__ . '/autoload_static.php';
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInit88ac621afd5b114466a1fd611b35d804::getInitializer($loader));
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInitbf3b0c550a047519dae38bd8e43006f2::getInitializer($loader));
|
||||
|
||||
$loader->setClassMapAuthoritative(true);
|
||||
$loader->register(true);
|
||||
|
||||
$includeFiles = \Composer\Autoload\ComposerStaticInit88ac621afd5b114466a1fd611b35d804::$files;
|
||||
$includeFiles = \Composer\Autoload\ComposerStaticInitbf3b0c550a047519dae38bd8e43006f2::$files;
|
||||
foreach ($includeFiles as $fileIdentifier => $file) {
|
||||
composerRequire88ac621afd5b114466a1fd611b35d804($fileIdentifier, $file);
|
||||
composerRequirebf3b0c550a047519dae38bd8e43006f2($fileIdentifier, $file);
|
||||
}
|
||||
|
||||
return $loader;
|
||||
@ -46,7 +46,7 @@ class ComposerAutoloaderInit88ac621afd5b114466a1fd611b35d804
|
||||
* @param string $file
|
||||
* @return void
|
||||
*/
|
||||
function composerRequire88ac621afd5b114466a1fd611b35d804($fileIdentifier, $file)
|
||||
function composerRequirebf3b0c550a047519dae38bd8e43006f2($fileIdentifier, $file)
|
||||
{
|
||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||
|
12
vendor/composer/autoload_static.php
vendored
12
vendor/composer/autoload_static.php
vendored
@ -4,7 +4,7 @@
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
class ComposerStaticInit88ac621afd5b114466a1fd611b35d804
|
||||
class ComposerStaticInitbf3b0c550a047519dae38bd8e43006f2
|
||||
{
|
||||
public static $files = array (
|
||||
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
|
||||
@ -2032,6 +2032,7 @@ class ComposerStaticInit88ac621afd5b114466a1fd611b35d804
|
||||
'Rector\\Doctrine\\NodeFactory\\ParamFactory' => __DIR__ . '/..' . '/rector/rector-doctrine/src/NodeFactory/ParamFactory.php',
|
||||
'Rector\\Doctrine\\NodeFactory\\RepositoryAssignFactory' => __DIR__ . '/..' . '/rector/rector-doctrine/src/NodeFactory/RepositoryAssignFactory.php',
|
||||
'Rector\\Doctrine\\NodeFactory\\RepositoryNodeFactory' => __DIR__ . '/..' . '/rector/rector-doctrine/src/NodeFactory/RepositoryNodeFactory.php',
|
||||
'Rector\\Doctrine\\NodeFactory\\SluggableClassMethodFactory' => __DIR__ . '/..' . '/rector/rector-doctrine/src/NodeFactory/SluggableClassMethodFactory.php',
|
||||
'Rector\\Doctrine\\NodeFactory\\TranslationClassNodeFactory' => __DIR__ . '/..' . '/rector/rector-doctrine/src/NodeFactory/TranslationClassNodeFactory.php',
|
||||
'Rector\\Doctrine\\NodeFactory\\ValueAssignFactory' => __DIR__ . '/..' . '/rector/rector-doctrine/src/NodeFactory/ValueAssignFactory.php',
|
||||
'Rector\\Doctrine\\NodeManipulator\\ColumnPropertyTypeResolver' => __DIR__ . '/..' . '/rector/rector-doctrine/src/NodeManipulator/ColumnPropertyTypeResolver.php',
|
||||
@ -2721,6 +2722,7 @@ class ComposerStaticInit88ac621afd5b114466a1fd611b35d804
|
||||
'Rector\\Php82\\Rector\\Class_\\ReadOnlyClassRector' => __DIR__ . '/../..' . '/rules/Php82/Rector/Class_/ReadOnlyClassRector.php',
|
||||
'Rector\\PhpAttribute\\AnnotationToAttributeMapper' => __DIR__ . '/../..' . '/packages/PhpAttribute/AnnotationToAttributeMapper.php',
|
||||
'Rector\\PhpAttribute\\AnnotationToAttributeMapper\\ArrayAnnotationToAttributeMapper' => __DIR__ . '/../..' . '/packages/PhpAttribute/AnnotationToAttributeMapper/ArrayAnnotationToAttributeMapper.php',
|
||||
'Rector\\PhpAttribute\\AnnotationToAttributeMapper\\ArrayItemNodeAnnotationToAttributeMapper' => __DIR__ . '/../..' . '/packages/PhpAttribute/AnnotationToAttributeMapper/ArrayItemNodeAnnotationToAttributeMapper.php',
|
||||
'Rector\\PhpAttribute\\AnnotationToAttributeMapper\\ClassConstFetchAnnotationToAttributeMapper' => __DIR__ . '/../..' . '/packages/PhpAttribute/AnnotationToAttributeMapper/ClassConstFetchAnnotationToAttributeMapper.php',
|
||||
'Rector\\PhpAttribute\\AnnotationToAttributeMapper\\ConstExprNodeAnnotationToAttributeMapper' => __DIR__ . '/../..' . '/packages/PhpAttribute/AnnotationToAttributeMapper/ConstExprNodeAnnotationToAttributeMapper.php',
|
||||
'Rector\\PhpAttribute\\AnnotationToAttributeMapper\\CurlyListNodeAnnotationToAttributeMapper' => __DIR__ . '/../..' . '/packages/PhpAttribute/AnnotationToAttributeMapper/CurlyListNodeAnnotationToAttributeMapper.php',
|
||||
@ -2935,7 +2937,6 @@ class ComposerStaticInit88ac621afd5b114466a1fd611b35d804
|
||||
'Rector\\Symfony\\NodeFactory\\Annotations\\DoctrineAnnotationFromNewFactory' => __DIR__ . '/..' . '/rector/rector-symfony/src/NodeFactory/Annotations/DoctrineAnnotationFromNewFactory.php',
|
||||
'Rector\\Symfony\\NodeFactory\\Annotations\\DoctrineAnnotationKeyToValuesResolver' => __DIR__ . '/..' . '/rector/rector-symfony/src/NodeFactory/Annotations/DoctrineAnnotationKeyToValuesResolver.php',
|
||||
'Rector\\Symfony\\NodeFactory\\Annotations\\StringValueQuoteWrapper' => __DIR__ . '/..' . '/rector/rector-symfony/src/NodeFactory/Annotations/StringValueQuoteWrapper.php',
|
||||
'Rector\\Symfony\\NodeFactory\\Annotations\\ValueQuoteWrapper' => __DIR__ . '/..' . '/rector/rector-symfony/src/NodeFactory/Annotations/ValueQuoteWrapper.php',
|
||||
'Rector\\Symfony\\NodeFactory\\ArrayFromCompactFactory' => __DIR__ . '/..' . '/rector/rector-symfony/src/NodeFactory/ArrayFromCompactFactory.php',
|
||||
'Rector\\Symfony\\NodeFactory\\BareLogoutClassMethodFactory' => __DIR__ . '/..' . '/rector/rector-symfony/src/NodeFactory/BareLogoutClassMethodFactory.php',
|
||||
'Rector\\Symfony\\NodeFactory\\EventReferenceFactory' => __DIR__ . '/..' . '/rector/rector-symfony/src/NodeFactory/EventReferenceFactory.php',
|
||||
@ -3020,6 +3021,7 @@ class ComposerStaticInit88ac621afd5b114466a1fd611b35d804
|
||||
'Rector\\Symfony\\Rector\\StaticCall\\BinaryFileResponseCreateToNewInstanceRector' => __DIR__ . '/..' . '/rector/rector-symfony/src/Rector/StaticCall/BinaryFileResponseCreateToNewInstanceRector.php',
|
||||
'Rector\\Symfony\\Rector\\StaticCall\\ParseFileRector' => __DIR__ . '/..' . '/rector/rector-symfony/src/Rector/StaticCall/ParseFileRector.php',
|
||||
'Rector\\Symfony\\Rector\\StaticCall\\ProcessBuilderInstanceRector' => __DIR__ . '/..' . '/rector/rector-symfony/src/Rector/StaticCall/ProcessBuilderInstanceRector.php',
|
||||
'Rector\\Symfony\\Rector\\StaticPropertyFetch\\KernelTestCaseContainerPropertyDeprecationRector' => __DIR__ . '/..' . '/rector/rector-symfony/src/Rector/StaticPropertyFetch/KernelTestCaseContainerPropertyDeprecationRector.php',
|
||||
'Rector\\Symfony\\Set\\JMSSetList' => __DIR__ . '/..' . '/rector/rector-symfony/src/Set/JMSSetList.php',
|
||||
'Rector\\Symfony\\Set\\SensiolabsSetList' => __DIR__ . '/..' . '/rector/rector-symfony/src/Set/SensiolabsSetList.php',
|
||||
'Rector\\Symfony\\Set\\SwiftmailerSetList' => __DIR__ . '/..' . '/rector/rector-symfony/src/Set/SwiftmailerSetList.php',
|
||||
@ -3254,9 +3256,9 @@ class ComposerStaticInit88ac621afd5b114466a1fd611b35d804
|
||||
public static function getInitializer(ClassLoader $loader)
|
||||
{
|
||||
return \Closure::bind(function () use ($loader) {
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInit88ac621afd5b114466a1fd611b35d804::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInit88ac621afd5b114466a1fd611b35d804::$prefixDirsPsr4;
|
||||
$loader->classMap = ComposerStaticInit88ac621afd5b114466a1fd611b35d804::$classMap;
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInitbf3b0c550a047519dae38bd8e43006f2::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInitbf3b0c550a047519dae38bd8e43006f2::$prefixDirsPsr4;
|
||||
$loader->classMap = ComposerStaticInitbf3b0c550a047519dae38bd8e43006f2::$classMap;
|
||||
|
||||
}, null, ClassLoader::class);
|
||||
}
|
||||
|
32
vendor/composer/installed.json
vendored
32
vendor/composer/installed.json
vendored
@ -1852,12 +1852,12 @@
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https:\/\/github.com\/rectorphp\/rector-doctrine.git",
|
||||
"reference": "c63e2882d4d61abacdc760561cddcd6ee394d777"
|
||||
"reference": "e1dba76992666c6fc9da35c3832ba56a6e1b28ec"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-doctrine\/zipball\/c63e2882d4d61abacdc760561cddcd6ee394d777",
|
||||
"reference": "c63e2882d4d61abacdc760561cddcd6ee394d777",
|
||||
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-doctrine\/zipball\/e1dba76992666c6fc9da35c3832ba56a6e1b28ec",
|
||||
"reference": "e1dba76992666c6fc9da35c3832ba56a6e1b28ec",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1882,7 +1882,7 @@
|
||||
"symplify\/rule-doc-generator": "^11.0",
|
||||
"symplify\/vendor-patches": "^11.0"
|
||||
},
|
||||
"time": "2022-08-18T19:37:47+00:00",
|
||||
"time": "2022-08-20T20:00:45+00:00",
|
||||
"default-branch": true,
|
||||
"type": "rector-extension",
|
||||
"extra": {
|
||||
@ -2267,12 +2267,12 @@
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https:\/\/github.com\/rectorphp\/rector-symfony.git",
|
||||
"reference": "20ac2a40e499d7933596f7c9c56d6ac0ab9df95d"
|
||||
"reference": "b689a4e48af872b4d0dcd3945a3ebf6262efdb5e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-symfony\/zipball\/20ac2a40e499d7933596f7c9c56d6ac0ab9df95d",
|
||||
"reference": "20ac2a40e499d7933596f7c9c56d6ac0ab9df95d",
|
||||
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-symfony\/zipball\/b689a4e48af872b4d0dcd3945a3ebf6262efdb5e",
|
||||
"reference": "b689a4e48af872b4d0dcd3945a3ebf6262efdb5e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2289,19 +2289,19 @@
|
||||
"phpstan\/phpstan-strict-rules": "^1.3",
|
||||
"phpstan\/phpstan-webmozart-assert": "^1.2",
|
||||
"phpunit\/phpunit": "^9.5",
|
||||
"rector\/phpstan-rules": "^0.5.8",
|
||||
"rector\/rector-src": "dev-main",
|
||||
"rector\/phpstan-rules": "^0.5.16",
|
||||
"rector\/rector-src": "dev-main#b216950",
|
||||
"symfony\/routing": "^6.1",
|
||||
"symfony\/security-core": "^6.1",
|
||||
"symfony\/security-http": "^6.1",
|
||||
"symplify\/easy-ci": "^11.0",
|
||||
"symplify\/easy-coding-standard": "^11.0",
|
||||
"symplify\/phpstan-extensions": "^11.0",
|
||||
"symplify\/phpstan-rules": "^11.0",
|
||||
"symplify\/rule-doc-generator": "^11.0",
|
||||
"symplify\/vendor-patches": "^11.0"
|
||||
"symplify\/easy-ci": "^11.1",
|
||||
"symplify\/easy-coding-standard": "^11.1",
|
||||
"symplify\/phpstan-extensions": "^11.1",
|
||||
"symplify\/phpstan-rules": "^11.1",
|
||||
"symplify\/rule-doc-generator": "^11.1",
|
||||
"symplify\/vendor-patches": "^11.1"
|
||||
},
|
||||
"time": "2022-08-19T12:50:54+00:00",
|
||||
"time": "2022-08-20T20:19:06+00:00",
|
||||
"default-branch": true,
|
||||
"type": "rector-extension",
|
||||
"extra": {
|
||||
|
2
vendor/composer/installed.php
vendored
2
vendor/composer/installed.php
vendored
File diff suppressed because one or more lines are too long
@ -9,7 +9,7 @@ namespace Rector\RectorInstaller;
|
||||
*/
|
||||
final class GeneratedConfig
|
||||
{
|
||||
public const EXTENSIONS = array('rector/rector-cakephp' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-cakephp', 'relative_install_path' => '../../rector-cakephp', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main c2ec06c'), 'rector/rector-doctrine' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-doctrine', 'relative_install_path' => '../../rector-doctrine', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main c63e288'), 'rector/rector-downgrade-php' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-downgrade-php', 'relative_install_path' => '../../rector-downgrade-php', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main efc7ddf'), 'rector/rector-generator' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-generator', 'relative_install_path' => '../../rector-generator', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 38440b9'), 'rector/rector-laravel' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-laravel', 'relative_install_path' => '../../rector-laravel', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 20edb95'), 'rector/rector-phpoffice' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-phpoffice', 'relative_install_path' => '../../rector-phpoffice', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 3638a66'), 'rector/rector-phpunit' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-phpunit', 'relative_install_path' => '../../rector-phpunit', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 0e0e399'), 'rector/rector-symfony' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-symfony', 'relative_install_path' => '../../rector-symfony', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 20ac2a4'));
|
||||
public const EXTENSIONS = array('rector/rector-cakephp' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-cakephp', 'relative_install_path' => '../../rector-cakephp', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main c2ec06c'), 'rector/rector-doctrine' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-doctrine', 'relative_install_path' => '../../rector-doctrine', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main e1dba76'), 'rector/rector-downgrade-php' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-downgrade-php', 'relative_install_path' => '../../rector-downgrade-php', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main efc7ddf'), 'rector/rector-generator' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-generator', 'relative_install_path' => '../../rector-generator', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 38440b9'), 'rector/rector-laravel' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-laravel', 'relative_install_path' => '../../rector-laravel', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 20edb95'), 'rector/rector-phpoffice' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-phpoffice', 'relative_install_path' => '../../rector-phpoffice', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 3638a66'), 'rector/rector-phpunit' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-phpunit', 'relative_install_path' => '../../rector-phpunit', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 0e0e399'), 'rector/rector-symfony' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-symfony', 'relative_install_path' => '../../rector-symfony', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main b689a4e'));
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
2
vendor/rector/rector-doctrine/rector.php
vendored
2
vendor/rector/rector-doctrine/rector.php
vendored
@ -17,6 +17,6 @@ return static function (RectorConfig $rectorConfig) : void {
|
||||
'*/Source/*',
|
||||
'*/Fixture/*',
|
||||
]);
|
||||
$rectorConfig->sets([LevelSetList::UP_TO_PHP_81, SetList::DEAD_CODE, SetList::CODE_QUALITY, SetList::NAMING]);
|
||||
$rectorConfig->sets([LevelSetList::UP_TO_PHP_81, SetList::DEAD_CODE, SetList::CODE_QUALITY, SetList::NAMING, SetList::TYPE_DECLARATION, SetList::TYPE_DECLARATION_STRICT, SetList::PRIVATIZATION]);
|
||||
$rectorConfig->ruleWithConfiguration(StringClassNameToClassConstantRector::class, ['Doctrine\\*', 'Gedmo\\*', 'Knp\\*', 'DateTime', 'DateTimeInterface']);
|
||||
};
|
||||
|
@ -3,9 +3,11 @@
|
||||
declare (strict_types=1);
|
||||
namespace Rector\Doctrine\NodeFactory;
|
||||
|
||||
use PhpParser\Node\Scalar\String_;
|
||||
use PhpParser\Node\Stmt\Property;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\SpacelessPhpDocTagNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
|
||||
@ -43,8 +45,8 @@ final class EntityIdNodeFactory
|
||||
// add @ORM\Id
|
||||
$phpDocTagNodes = [];
|
||||
$phpDocTagNodes[] = new SpacelessPhpDocTagNode('@ORM\\Id', new DoctrineAnnotationTagValueNode(new IdentifierTypeNode('Doctrine\\ORM\\Mapping\\Id'), null, []));
|
||||
$phpDocTagNodes[] = new SpacelessPhpDocTagNode('@ORM\\Column', new DoctrineAnnotationTagValueNode(new IdentifierTypeNode('Doctrine\\ORM\\Mapping\\Column'), null, ['type' => '"integer"']));
|
||||
$phpDocTagNodes[] = new SpacelessPhpDocTagNode('@ORM\\GeneratedValue', new DoctrineAnnotationTagValueNode(new IdentifierTypeNode('Doctrine\\ORM\\Mapping\\GeneratedValue'), null, ['strategy' => '"AUTO"']));
|
||||
$phpDocTagNodes[] = new SpacelessPhpDocTagNode('@ORM\\Column', new DoctrineAnnotationTagValueNode(new IdentifierTypeNode('Doctrine\\ORM\\Mapping\\Column'), null, [new ArrayItemNode('integer', 'type', String_::KIND_DOUBLE_QUOTED)]));
|
||||
$phpDocTagNodes[] = new SpacelessPhpDocTagNode('@ORM\\GeneratedValue', new DoctrineAnnotationTagValueNode(new IdentifierTypeNode('Doctrine\\ORM\\Mapping\\GeneratedValue'), null, [new ArrayItemNode('AUTO', 'strategy', String_::KIND_DOUBLE_QUOTED)]));
|
||||
foreach ($phpDocTagNodes as $phpDocTagNode) {
|
||||
$phpDocInfo->addPhpDocTagNode($phpDocTagNode);
|
||||
}
|
||||
|
55
vendor/rector/rector-doctrine/src/NodeFactory/SluggableClassMethodFactory.php
vendored
Normal file
55
vendor/rector/rector-doctrine/src/NodeFactory/SluggableClassMethodFactory.php
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace Rector\Doctrine\NodeFactory;
|
||||
|
||||
use PhpParser\Builder\Method;
|
||||
use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Identifier;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PhpParser\Node\Stmt\Return_;
|
||||
use PHPStan\Type\ArrayType;
|
||||
use PHPStan\Type\MixedType;
|
||||
use PHPStan\Type\StringType;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
|
||||
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger;
|
||||
use Rector\PhpAttribute\AnnotationToAttributeMapper;
|
||||
final class SluggableClassMethodFactory
|
||||
{
|
||||
/**
|
||||
* @readonly
|
||||
* @var \Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory
|
||||
*/
|
||||
private $phpDocInfoFactory;
|
||||
/**
|
||||
* @readonly
|
||||
* @var \Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger
|
||||
*/
|
||||
private $phpDocTypeChanger;
|
||||
/**
|
||||
* @readonly
|
||||
* @var \Rector\PhpAttribute\AnnotationToAttributeMapper
|
||||
*/
|
||||
private $annotationToAttributeMapper;
|
||||
public function __construct(PhpDocInfoFactory $phpDocInfoFactory, PhpDocTypeChanger $phpDocTypeChanger, AnnotationToAttributeMapper $annotationToAttributeMapper)
|
||||
{
|
||||
$this->phpDocInfoFactory = $phpDocInfoFactory;
|
||||
$this->phpDocTypeChanger = $phpDocTypeChanger;
|
||||
$this->annotationToAttributeMapper = $annotationToAttributeMapper;
|
||||
}
|
||||
public function createGetSluggableFields(ArrayItemNode $arrayItemNode) : ClassMethod
|
||||
{
|
||||
$builderClassMethod = new Method('getSluggableFields');
|
||||
$builderClassMethod->makePublic();
|
||||
$builderClassMethod->setReturnType(new Identifier('array'));
|
||||
/** @var Expr $slugFieldsExprs */
|
||||
$slugFieldsExprs = $this->annotationToAttributeMapper->map($arrayItemNode->value);
|
||||
$builderClassMethod->addStmt(new Return_($slugFieldsExprs));
|
||||
$classMethod = $builderClassMethod->getNode();
|
||||
$returnArrayType = new ArrayType(new MixedType(), new StringType());
|
||||
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($classMethod);
|
||||
$this->phpDocTypeChanger->changeReturnType($phpDocInfo, $returnArrayType);
|
||||
return $classMethod;
|
||||
}
|
||||
}
|
@ -13,6 +13,7 @@ use PHPStan\Type\NullType;
|
||||
use PHPStan\Type\ObjectType;
|
||||
use PHPStan\Type\StringType;
|
||||
use PHPStan\Type\Type;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
|
||||
@ -111,11 +112,14 @@ final class ColumnPropertyTypeResolver
|
||||
if (!$doctrineAnnotationTagValueNode instanceof DoctrineAnnotationTagValueNode) {
|
||||
return null;
|
||||
}
|
||||
$type = $doctrineAnnotationTagValueNode->getValueWithoutQuotes('type');
|
||||
if (!\is_string($type)) {
|
||||
$typeArrayItemNode = $doctrineAnnotationTagValueNode->getValue('type');
|
||||
if (!$typeArrayItemNode instanceof ArrayItemNode) {
|
||||
return new MixedType();
|
||||
}
|
||||
return $this->createPHPStanTypeFromDoctrineStringType($type, $isNullable);
|
||||
if (!\is_string($typeArrayItemNode->value)) {
|
||||
return null;
|
||||
}
|
||||
return $this->createPHPStanTypeFromDoctrineStringType($typeArrayItemNode->value, $isNullable);
|
||||
}
|
||||
/**
|
||||
* @return \PHPStan\Type\MixedType|\PHPStan\Type\Type
|
||||
|
@ -6,6 +6,7 @@ namespace Rector\Doctrine\NodeManipulator;
|
||||
use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprFalseNode;
|
||||
use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprIntegerNode;
|
||||
use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprTrueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
final class DoctrineItemDefaultValueManipulator
|
||||
@ -27,10 +28,11 @@ final class DoctrineItemDefaultValueManipulator
|
||||
*/
|
||||
private function hasItemWithDefaultValue(DoctrineAnnotationTagValueNode $doctrineAnnotationTagValueNode, string $itemKey, $defaultValue) : bool
|
||||
{
|
||||
$currentValue = $doctrineAnnotationTagValueNode->getValueWithoutQuotes($itemKey);
|
||||
if ($currentValue === null) {
|
||||
$currentValueArrayItemNode = $doctrineAnnotationTagValueNode->getValue($itemKey);
|
||||
if (!$currentValueArrayItemNode instanceof ArrayItemNode) {
|
||||
return \false;
|
||||
}
|
||||
$currentValue = $currentValueArrayItemNode->value;
|
||||
if ($defaultValue === \false) {
|
||||
return $currentValue instanceof ConstExprFalseNode;
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ namespace Rector\Doctrine\NodeManipulator;
|
||||
use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Stmt\Property;
|
||||
use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprTrueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
|
||||
@ -56,7 +57,10 @@ final class NullabilityColumnPropertyTypeResolver
|
||||
if (!$doctrineAnnotationTagValueNode instanceof DoctrineAnnotationTagValueNode) {
|
||||
return \true;
|
||||
}
|
||||
$nullableValue = $doctrineAnnotationTagValueNode->getValue('nullable');
|
||||
return $nullableValue === null || $nullableValue instanceof ConstExprTrueNode;
|
||||
$nullableValueArrayItemNode = $doctrineAnnotationTagValueNode->getValue('nullable');
|
||||
if (!$nullableValueArrayItemNode instanceof ArrayItemNode) {
|
||||
return \true;
|
||||
}
|
||||
return $nullableValueArrayItemNode->value instanceof ConstExprTrueNode;
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Stmt\Property;
|
||||
use PHPStan\Type\Generic\GenericObjectType;
|
||||
use PHPStan\Type\Type;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
|
||||
use Rector\Core\PhpParser\Node\Value\ValueResolver;
|
||||
@ -65,11 +66,14 @@ final class ToManyRelationPropertyTypeResolver
|
||||
}
|
||||
private function processToManyRelation(Property $property, DoctrineAnnotationTagValueNode $doctrineAnnotationTagValueNode) : ?\PHPStan\Type\Type
|
||||
{
|
||||
$targetEntity = $doctrineAnnotationTagValueNode->getValueWithoutQuotes('targetEntity');
|
||||
if (!\is_string($targetEntity)) {
|
||||
$targetEntityArrayItemNode = $doctrineAnnotationTagValueNode->getValue('targetEntity');
|
||||
if (!$targetEntityArrayItemNode instanceof ArrayItemNode) {
|
||||
return null;
|
||||
}
|
||||
return $this->resolveTypeFromTargetEntity($targetEntity, $property);
|
||||
if (!\is_string($targetEntityArrayItemNode->value)) {
|
||||
return null;
|
||||
}
|
||||
return $this->resolveTypeFromTargetEntity($targetEntityArrayItemNode->value, $property);
|
||||
}
|
||||
/**
|
||||
* @param \PhpParser\Node\Expr|string $targetEntity
|
||||
|
@ -11,6 +11,7 @@ use PHPStan\Type\MixedType;
|
||||
use PHPStan\Type\NullType;
|
||||
use PHPStan\Type\Type;
|
||||
use PHPStan\Type\TypeCombinator;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
|
||||
@ -79,15 +80,19 @@ final class ToOneRelationPropertyTypeResolver
|
||||
}
|
||||
private function processToOneRelation(Property $property, DoctrineAnnotationTagValueNode $toOneDoctrineAnnotationTagValueNode, ?DoctrineAnnotationTagValueNode $joinDoctrineAnnotationTagValueNode) : Type
|
||||
{
|
||||
$targetEntity = $toOneDoctrineAnnotationTagValueNode->getValueWithoutQuotes('targetEntity');
|
||||
if (!\is_string($targetEntity)) {
|
||||
$targetEntity = $toOneDoctrineAnnotationTagValueNode->getValue('targetEntity');
|
||||
if (!$targetEntity instanceof ArrayItemNode) {
|
||||
return new MixedType();
|
||||
}
|
||||
if (\substr_compare($targetEntity, '::class', -\strlen('::class')) === 0) {
|
||||
$targetEntity = Strings::before($targetEntity, '::class');
|
||||
$targetEntityClass = $targetEntity->value;
|
||||
if (!\is_string($targetEntityClass)) {
|
||||
return new MixedType();
|
||||
}
|
||||
if (\substr_compare($targetEntityClass, '::class', -\strlen('::class')) === 0) {
|
||||
$targetEntityClass = Strings::before($targetEntityClass, '::class');
|
||||
}
|
||||
// resolve to FQN
|
||||
$tagFullyQualifiedName = $this->classAnnotationMatcher->resolveTagFullyQualifiedName($targetEntity, $property);
|
||||
$tagFullyQualifiedName = $this->classAnnotationMatcher->resolveTagFullyQualifiedName($targetEntityClass, $property);
|
||||
if ($tagFullyQualifiedName === null) {
|
||||
return new MixedType();
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ namespace Rector\Doctrine\PhpDocParser;
|
||||
|
||||
use PhpParser\Node\Stmt\Property;
|
||||
use Rector\BetterPhpDocParser\PhpDocParser\ClassAnnotationMatcher;
|
||||
class DoctrineClassAnnotationMatcher
|
||||
final class DoctrineClassAnnotationMatcher
|
||||
{
|
||||
/**
|
||||
* @readonly
|
||||
|
@ -93,7 +93,7 @@ CODE_SAMPLE
|
||||
$classPhpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($class);
|
||||
$hasLoggableAnnotation = \false;
|
||||
$phpDocNodeTraverser = new PhpDocNodeTraverser();
|
||||
$phpDocNodeTraverser->traverseWithCallable($classPhpDocInfo->getPhpDocNode(), '', function ($node) use(&$hasLoggableAnnotation) {
|
||||
$phpDocNodeTraverser->traverseWithCallable($classPhpDocInfo->getPhpDocNode(), '', function ($node) use(&$hasLoggableAnnotation) : ?int {
|
||||
if (!$node instanceof SpacelessPhpDocTagNode) {
|
||||
return null;
|
||||
}
|
||||
@ -122,7 +122,7 @@ CODE_SAMPLE
|
||||
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($property);
|
||||
$hasChanged = \false;
|
||||
$phpDocNodeTraverser = new PhpDocNodeTraverser();
|
||||
$phpDocNodeTraverser->traverseWithCallable($phpDocInfo->getPhpDocNode(), '', function ($node) use($phpDocInfo, &$hasChanged) {
|
||||
$phpDocNodeTraverser->traverseWithCallable($phpDocInfo->getPhpDocNode(), '', function ($node) use($phpDocInfo, &$hasChanged) : ?int {
|
||||
if (!$node instanceof SpacelessPhpDocTagNode) {
|
||||
return null;
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ use PhpParser\Node;
|
||||
use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\Property;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDoc\DoctrineAnnotation\CurlyListNode;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
@ -116,8 +117,11 @@ CODE_SAMPLE
|
||||
if (!$doctrineAnnotationTagValueNode instanceof DoctrineAnnotationTagValueNode) {
|
||||
return;
|
||||
}
|
||||
$type = $doctrineAnnotationTagValueNode->getValueWithoutQuotes('type');
|
||||
if ($type !== 'datetime') {
|
||||
$typeArrayItemNode = $doctrineAnnotationTagValueNode->getValue('type');
|
||||
if (!$typeArrayItemNode instanceof ArrayItemNode) {
|
||||
return;
|
||||
}
|
||||
if ($typeArrayItemNode->value !== 'datetime') {
|
||||
return;
|
||||
}
|
||||
$node = $this->constructorAssignPropertyAnalyzer->resolveConstructorAssign($property);
|
||||
@ -127,11 +131,14 @@ CODE_SAMPLE
|
||||
}
|
||||
$this->hasChanged = \true;
|
||||
// 1. remove default options from database level
|
||||
$options = $doctrineAnnotationTagValueNode->getValue('options');
|
||||
if ($options instanceof CurlyListNode) {
|
||||
$options->removeValue('default');
|
||||
$optionsArrayItemNode = $doctrineAnnotationTagValueNode->getValue('options');
|
||||
if ($optionsArrayItemNode instanceof ArrayItemNode) {
|
||||
if (!$optionsArrayItemNode->value instanceof CurlyListNode) {
|
||||
return;
|
||||
}
|
||||
$optionsArrayItemNode->value->removeValue('default');
|
||||
// if empty, remove it completely
|
||||
if ($options->getValues() === []) {
|
||||
if ($optionsArrayItemNode->value->getValues() === []) {
|
||||
$doctrineAnnotationTagValueNode->removeValue('options');
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ namespace Rector\Doctrine\Rector\Class_;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
@ -56,11 +57,10 @@ CODE_SAMPLE
|
||||
return null;
|
||||
}
|
||||
$repositoryClass = $doctrineAnnotationTagValueNode->getValue('repositoryClass');
|
||||
if (!\is_string($repositoryClass)) {
|
||||
if (!$repositoryClass instanceof ArrayItemNode) {
|
||||
return null;
|
||||
}
|
||||
$doctrineAnnotationTagValueNode->removeValue('repositoryClass');
|
||||
$phpDocInfo->markAsChanged();
|
||||
return $node;
|
||||
}
|
||||
}
|
||||
|
@ -4,19 +4,14 @@ declare (strict_types=1);
|
||||
namespace Rector\Doctrine\Rector\Class_;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Identifier;
|
||||
use PhpParser\Node\Name\FullyQualified;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\Return_;
|
||||
use PHPStan\Type\ArrayType;
|
||||
use PHPStan\Type\MixedType;
|
||||
use PHPStan\Type\StringType;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDoc\DoctrineAnnotation\CurlyListNode;
|
||||
use Rector\Core\Exception\ShouldNotHappenException;
|
||||
use Rector\Core\NodeManipulator\ClassInsertManipulator;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Doctrine\NodeFactory\SluggableClassMethodFactory;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
/**
|
||||
@ -34,13 +29,13 @@ final class SluggableBehaviorRector extends AbstractRector
|
||||
private $classInsertManipulator;
|
||||
/**
|
||||
* @readonly
|
||||
* @var \Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger
|
||||
* @var \Rector\Doctrine\NodeFactory\SluggableClassMethodFactory
|
||||
*/
|
||||
private $phpDocTypeChanger;
|
||||
public function __construct(ClassInsertManipulator $classInsertManipulator, PhpDocTypeChanger $phpDocTypeChanger)
|
||||
private $sluggableClassMethodFactory;
|
||||
public function __construct(ClassInsertManipulator $classInsertManipulator, SluggableClassMethodFactory $sluggableClassMethodFactory)
|
||||
{
|
||||
$this->classInsertManipulator = $classInsertManipulator;
|
||||
$this->phpDocTypeChanger = $phpDocTypeChanger;
|
||||
$this->sluggableClassMethodFactory = $sluggableClassMethodFactory;
|
||||
}
|
||||
public function getRuleDefinition() : RuleDefinition
|
||||
{
|
||||
@ -124,23 +119,11 @@ CODE_SAMPLE
|
||||
}
|
||||
$this->classInsertManipulator->addAsFirstTrait($node, 'Knp\\DoctrineBehaviors\\Model\\Sluggable\\SluggableTrait');
|
||||
$node->implements[] = new FullyQualified('Knp\\DoctrineBehaviors\\Contract\\Entity\\SluggableInterface');
|
||||
if (!\is_array($slugFields)) {
|
||||
throw new ShouldNotHappenException();
|
||||
if (!$slugFields instanceof ArrayItemNode) {
|
||||
return null;
|
||||
}
|
||||
$this->addGetSluggableFieldsClassMethod($node, $slugFields);
|
||||
$getSluggableClassMethod = $this->sluggableClassMethodFactory->createGetSluggableFields($slugFields);
|
||||
$this->classInsertManipulator->addAsFirstMethod($node, $getSluggableClassMethod);
|
||||
return $node;
|
||||
}
|
||||
/**
|
||||
* @param string[] $slugFields
|
||||
*/
|
||||
private function addGetSluggableFieldsClassMethod(Class_ $class, array $slugFields) : void
|
||||
{
|
||||
$classMethod = $this->nodeFactory->createPublicMethod('getSluggableFields');
|
||||
$classMethod->returnType = new Identifier('array');
|
||||
$classMethod->stmts[] = new Return_($this->nodeFactory->createArray($slugFields));
|
||||
$returnType = new ArrayType(new MixedType(), new StringType());
|
||||
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($classMethod);
|
||||
$this->phpDocTypeChanger->changeReturnType($phpDocInfo, $returnType);
|
||||
$this->classInsertManipulator->addAsFirstMethod($class, $classMethod);
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ namespace Rector\Doctrine\Rector\Class_;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Name\FullyQualified;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTagRemover;
|
||||
use Rector\Core\NodeManipulator\ClassInsertManipulator;
|
||||
@ -89,11 +90,14 @@ CODE_SAMPLE
|
||||
if (!$doctrineAnnotationTagValueNode instanceof DoctrineAnnotationTagValueNode) {
|
||||
return null;
|
||||
}
|
||||
$fieldName = $doctrineAnnotationTagValueNode->getValueWithoutQuotes('fieldName');
|
||||
if (!\is_string($fieldName)) {
|
||||
$fieldNameArrayItemNode = $doctrineAnnotationTagValueNode->getValue('fieldName');
|
||||
if (!$fieldNameArrayItemNode instanceof ArrayItemNode) {
|
||||
return null;
|
||||
}
|
||||
$this->removePropertyAndClassMethods($node, $fieldName);
|
||||
if (!\is_string($fieldNameArrayItemNode->value)) {
|
||||
return null;
|
||||
}
|
||||
$this->removePropertyAndClassMethods($node, $fieldNameArrayItemNode->value);
|
||||
$this->classInsertManipulator->addAsFirstTrait($node, 'Knp\\DoctrineBehaviors\\Model\\SoftDeletable\\SoftDeletableTrait');
|
||||
$node->implements[] = new FullyQualified('Knp\\DoctrineBehaviors\\Contract\\Entity\\SoftDeletableInterface');
|
||||
$this->phpDocTagRemover->removeTagValueFromNode($phpDocInfo, $doctrineAnnotationTagValueNode);
|
||||
|
@ -10,6 +10,7 @@ use PHPStan\Type\BooleanType;
|
||||
use PHPStan\Type\FloatType;
|
||||
use PHPStan\Type\IntegerType;
|
||||
use PHPStan\Type\StringType;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockClassRenamer;
|
||||
@ -83,8 +84,11 @@ CODE_SAMPLE
|
||||
if (!$doctrineAnnotationTagValueNode instanceof DoctrineAnnotationTagValueNode) {
|
||||
return null;
|
||||
}
|
||||
$type = $doctrineAnnotationTagValueNode->getValueWithoutQuotes('type');
|
||||
if ($type !== 'bigint') {
|
||||
$typeArrayItemNode = $doctrineAnnotationTagValueNode->getValue('type');
|
||||
if (!$typeArrayItemNode instanceof ArrayItemNode) {
|
||||
return null;
|
||||
}
|
||||
if ($typeArrayItemNode->value !== 'bigint') {
|
||||
return null;
|
||||
}
|
||||
$varTagValueNode = $phpDocInfo->getVarTagValueNode();
|
||||
|
@ -11,6 +11,7 @@ use PhpParser\Node\Scalar\LNumber;
|
||||
use PhpParser\Node\Scalar\String_;
|
||||
use PhpParser\Node\Stmt\Property;
|
||||
use PhpParser\Node\Stmt\PropertyProperty;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
|
||||
use Rector\Core\Exception\NotImplementedYetException;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
@ -75,11 +76,18 @@ CODE_SAMPLE
|
||||
if (!$defaultValue instanceof Expr) {
|
||||
return null;
|
||||
}
|
||||
$type = $doctrineAnnotationTagValueNode->getValueWithoutQuotes('type');
|
||||
if (\in_array($type, ['bool', 'boolean'], \true)) {
|
||||
$typeArrayItemNode = $doctrineAnnotationTagValueNode->getValue('type');
|
||||
if (!$typeArrayItemNode instanceof ArrayItemNode) {
|
||||
return null;
|
||||
}
|
||||
$typeValue = $typeArrayItemNode->value;
|
||||
if (!\is_string($typeValue)) {
|
||||
return null;
|
||||
}
|
||||
if (\in_array($typeValue, ['bool', 'boolean'], \true)) {
|
||||
return $this->refactorToBoolType($onlyProperty, $node);
|
||||
}
|
||||
if (\in_array($type, ['int', 'integer', 'bigint', 'smallint'], \true)) {
|
||||
if (\in_array($typeValue, ['int', 'integer', 'bigint', 'smallint'], \true)) {
|
||||
return $this->refactorToIntType($onlyProperty, $node);
|
||||
}
|
||||
return null;
|
||||
|
@ -12,6 +12,7 @@ use PhpParser\Node;
|
||||
use PhpParser\Node\Attribute;
|
||||
use PhpParser\Node\Identifier;
|
||||
use PhpParser\Node\Stmt\Property;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
@ -24,7 +25,13 @@ use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
*/
|
||||
final class DoctrineTargetEntityStringToClassConstantRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private const ATTRIBUTE_NAME__TARGET_ENTITY = 'targetEntity';
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private const ATTRIBUTE_NAME__CLASS = 'class';
|
||||
/**
|
||||
* @var array<class-string<OneToMany|ManyToOne|OneToOne|ManyToMany|Embedded>, string>
|
||||
@ -73,6 +80,9 @@ final class SomeClass
|
||||
CODE_SAMPLE
|
||||
)]);
|
||||
}
|
||||
/**
|
||||
* @return array<class-string<Node>>
|
||||
*/
|
||||
public function getNodeTypes() : array
|
||||
{
|
||||
return [Property::class];
|
||||
@ -83,7 +93,7 @@ CODE_SAMPLE
|
||||
public function refactor(Node $node) : ?Node
|
||||
{
|
||||
$phpDocInfo = $this->phpDocInfoFactory->createFromNode($node);
|
||||
if ($phpDocInfo !== null) {
|
||||
if ($phpDocInfo instanceof PhpDocInfo) {
|
||||
$property = $this->changeTypeInAnnotationTypes($node, $phpDocInfo);
|
||||
$annotationDetected = $property !== null || $phpDocInfo->hasChanged();
|
||||
if ($annotationDetected) {
|
||||
@ -137,9 +147,12 @@ CODE_SAMPLE
|
||||
private function processDoctrineToMany(DoctrineAnnotationTagValueNode $doctrineAnnotationTagValueNode, Property $property) : ?Property
|
||||
{
|
||||
$key = $doctrineAnnotationTagValueNode->hasClassName('Doctrine\\ORM\\Mapping\\Embedded') ? self::ATTRIBUTE_NAME__CLASS : self::ATTRIBUTE_NAME__TARGET_ENTITY;
|
||||
/** @var ?string $targetEntity */
|
||||
$targetEntity = $doctrineAnnotationTagValueNode->getValueWithoutQuotes($key);
|
||||
if ($targetEntity === null) {
|
||||
$targetEntityArrayItemNode = $doctrineAnnotationTagValueNode->getValue($key);
|
||||
if (!$targetEntityArrayItemNode instanceof ArrayItemNode) {
|
||||
return null;
|
||||
}
|
||||
$targetEntity = $targetEntityArrayItemNode->value;
|
||||
if (!\is_string($targetEntity)) {
|
||||
return null;
|
||||
}
|
||||
// resolve to FQN
|
||||
@ -150,8 +163,14 @@ CODE_SAMPLE
|
||||
if ($tagFullyQualifiedName === $targetEntity) {
|
||||
return null;
|
||||
}
|
||||
$doctrineAnnotationTagValueNode->removeValue($key);
|
||||
$doctrineAnnotationTagValueNode->values[$key] = '\\' . \ltrim($tagFullyQualifiedName, '\\') . '::class';
|
||||
$currentArrayItemNode = $doctrineAnnotationTagValueNode->getValue($key);
|
||||
if (!$currentArrayItemNode instanceof ArrayItemNode) {
|
||||
return null;
|
||||
}
|
||||
// no quotes needed, it's a constants
|
||||
$currentArrayItemNode->kindValueQuoted = null;
|
||||
$currentArrayItemNode->value = '\\' . \ltrim($tagFullyQualifiedName, '\\') . '::class';
|
||||
$currentArrayItemNode->setAttribute('orig_node', null);
|
||||
return $property;
|
||||
}
|
||||
/**
|
||||
|
@ -9,9 +9,9 @@ use PHPStan\PhpDocParser\Ast\Type\ArrayTypeNode;
|
||||
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
|
||||
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
|
||||
use PHPStan\PhpDocParser\Ast\Type\UnionTypeNode;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
|
||||
use Rector\Core\Exception\ShouldNotHappenException;
|
||||
use Rector\Doctrine\PhpDoc\ShortClassExpander;
|
||||
use Rector\StaticTypeMapper\Naming\NameScopeFactory;
|
||||
use Rector\StaticTypeMapper\ValueObject\Type\FullyQualifiedObjectType;
|
||||
@ -62,11 +62,14 @@ final class CollectionTypeResolver
|
||||
if (!$doctrineAnnotationTagValueNode instanceof DoctrineAnnotationTagValueNode) {
|
||||
return null;
|
||||
}
|
||||
$targetEntity = $doctrineAnnotationTagValueNode->getValueWithoutQuotes('targetEntity');
|
||||
if (!\is_string($targetEntity)) {
|
||||
throw new ShouldNotHappenException();
|
||||
$targetEntityArrayItemNode = $doctrineAnnotationTagValueNode->getValue('targetEntity');
|
||||
if (!$targetEntityArrayItemNode instanceof ArrayItemNode) {
|
||||
return null;
|
||||
}
|
||||
$fullyQualifiedTargetEntity = $this->shortClassExpander->resolveFqnTargetEntity($targetEntity, $property);
|
||||
if (!\is_string($targetEntityArrayItemNode->value)) {
|
||||
return null;
|
||||
}
|
||||
$fullyQualifiedTargetEntity = $this->shortClassExpander->resolveFqnTargetEntity($targetEntityArrayItemNode->value, $property);
|
||||
return new FullyQualifiedObjectType($fullyQualifiedTargetEntity);
|
||||
}
|
||||
}
|
||||
|
16
vendor/rector/rector-symfony/composer.json
vendored
16
vendor/rector/rector-symfony/composer.json
vendored
@ -14,17 +14,17 @@
|
||||
"phpstan\/phpstan-strict-rules": "^1.3",
|
||||
"phpstan\/phpstan-webmozart-assert": "^1.2",
|
||||
"phpunit\/phpunit": "^9.5",
|
||||
"rector\/phpstan-rules": "^0.5.8",
|
||||
"rector\/rector-src": "dev-main",
|
||||
"rector\/phpstan-rules": "^0.5.16",
|
||||
"rector\/rector-src": "dev-main#b216950",
|
||||
"symfony\/routing": "^6.1",
|
||||
"symfony\/security-core": "^6.1",
|
||||
"symfony\/security-http": "^6.1",
|
||||
"symplify\/easy-ci": "^11.0",
|
||||
"symplify\/easy-coding-standard": "^11.0",
|
||||
"symplify\/phpstan-extensions": "^11.0",
|
||||
"symplify\/phpstan-rules": "^11.0",
|
||||
"symplify\/rule-doc-generator": "^11.0",
|
||||
"symplify\/vendor-patches": "^11.0"
|
||||
"symplify\/easy-ci": "^11.1",
|
||||
"symplify\/easy-coding-standard": "^11.1",
|
||||
"symplify\/phpstan-extensions": "^11.1",
|
||||
"symplify\/phpstan-rules": "^11.1",
|
||||
"symplify\/rule-doc-generator": "^11.1",
|
||||
"symplify\/vendor-patches": "^11.1"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
@ -10,6 +10,7 @@ use Rector\Renaming\Rector\MethodCall\RenameMethodRector;
|
||||
use Rector\Renaming\Rector\Name\RenameClassRector;
|
||||
use Rector\Renaming\ValueObject\MethodCallRename;
|
||||
use Rector\Renaming\ValueObject\RenameClassConstFetch;
|
||||
use Rector\Symfony\Rector\StaticPropertyFetch\KernelTestCaseContainerPropertyDeprecationRector;
|
||||
use Rector\Symfony\Set\SymfonySetList;
|
||||
use Rector\TypeDeclaration\Rector\ClassMethod\AddReturnTypeDeclarationRector;
|
||||
use Rector\TypeDeclaration\ValueObject\AddReturnTypeDeclaration;
|
||||
@ -48,4 +49,5 @@ return static function (RectorConfig $rectorConfig) : void {
|
||||
// @see https://github.com/symfony/symfony/pull/40536
|
||||
new RenameClassConstFetch('Symfony\\Component\\HttpKernel\\HttpKernelInterface', 'MASTER_REQUEST', 'MAIN_REQUEST'),
|
||||
]);
|
||||
$rectorConfig->rule(KernelTestCaseContainerPropertyDeprecationRector::class);
|
||||
};
|
||||
|
@ -9,4 +9,8 @@ final class SymfonyAnnotation
|
||||
* @var string
|
||||
*/
|
||||
public const ROUTE = 'Symfony\\Component\\Routing\\Annotation\\Route';
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const SENSIO_METHOD = 'Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\Method';
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ use PhpParser\Node\Scalar\String_;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PHPStan\Type\IntegerType;
|
||||
use PHPStan\Type\Type;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDoc\DoctrineAnnotation\CurlyListNode;
|
||||
use Rector\Doctrine\NodeAnalyzer\AttrinationFinder;
|
||||
@ -75,14 +76,22 @@ final class RouteRequiredParamNameToTypesResolver
|
||||
{
|
||||
$paramsToRegexes = [];
|
||||
$requirementsValue = $doctrineAnnotationTagValueNode->getValue('requirements');
|
||||
if (!$requirementsValue instanceof CurlyListNode) {
|
||||
if (!$requirementsValue instanceof ArrayItemNode) {
|
||||
return [];
|
||||
}
|
||||
foreach ($requirementsValue->getValuesWithExplicitSilentAndWithoutQuotes() as $paramName => $paramRegex) {
|
||||
if (!\is_string($paramName)) {
|
||||
if (!$requirementsValue->value instanceof CurlyListNode) {
|
||||
return [];
|
||||
}
|
||||
foreach ($requirementsValue->value->getValuesWithSilentKey() as $nestedArrayItemNode) {
|
||||
if (!\is_string($nestedArrayItemNode->value)) {
|
||||
continue;
|
||||
}
|
||||
$paramsToRegexes[$paramName] = (string) $paramRegex;
|
||||
if (!\is_string($nestedArrayItemNode->key)) {
|
||||
continue;
|
||||
}
|
||||
$paramName = $nestedArrayItemNode->key;
|
||||
$paramRegex = $nestedArrayItemNode->value;
|
||||
$paramsToRegexes[$paramName] = $paramRegex;
|
||||
}
|
||||
return $paramsToRegexes;
|
||||
}
|
||||
|
@ -25,4 +25,12 @@ final class SymfonyTestCaseAnalyzer
|
||||
}
|
||||
return $classReflection->isSubclassOf('Symfony\\Bundle\\FrameworkBundle\\Test\\WebTestCase');
|
||||
}
|
||||
public function isInKernelTestCase(Node $node) : bool
|
||||
{
|
||||
$classReflection = $this->reflectionResolver->resolveClassReflection($node);
|
||||
if (!$classReflection instanceof ClassReflection) {
|
||||
return \false;
|
||||
}
|
||||
return $classReflection->isSubclassOf('Symfony\\Bundle\\FrameworkBundle\\Test\\KernelTestCase');
|
||||
}
|
||||
}
|
||||
|
@ -3,9 +3,18 @@
|
||||
declare (strict_types=1);
|
||||
namespace Rector\Symfony\NodeFactory\Annotations;
|
||||
|
||||
use Rector\BetterPhpDocParser\PhpDocParser\StaticDoctrineAnnotationParser\ArrayParser;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDoc\DoctrineAnnotation\CurlyListNode;
|
||||
final class StringValueQuoteWrapper
|
||||
{
|
||||
/**
|
||||
* @var \Rector\BetterPhpDocParser\PhpDocParser\StaticDoctrineAnnotationParser\ArrayParser
|
||||
*/
|
||||
private $arrayParser;
|
||||
public function __construct(ArrayParser $arrayParser)
|
||||
{
|
||||
$this->arrayParser = $arrayParser;
|
||||
}
|
||||
/**
|
||||
* @return mixed|CurlyListNode|string
|
||||
* @param mixed $value
|
||||
@ -34,6 +43,7 @@ final class StringValueQuoteWrapper
|
||||
$value[$nestedKey] = '"' . $nestedValue . '"';
|
||||
}
|
||||
}
|
||||
return new CurlyListNode($value);
|
||||
$arrayItemNodes = $this->arrayParser->createArrayFromValues($value);
|
||||
return new CurlyListNode($arrayItemNodes);
|
||||
}
|
||||
}
|
||||
|
@ -1,49 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace Rector\Symfony\NodeFactory\Annotations;
|
||||
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDoc\DoctrineAnnotation\CurlyListNode;
|
||||
final class ValueQuoteWrapper
|
||||
{
|
||||
/**
|
||||
* @return mixed|CurlyListNode|string
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function wrap($value)
|
||||
{
|
||||
if (\is_string($value)) {
|
||||
return '"' . $value . '"';
|
||||
}
|
||||
if (\is_array($value)) {
|
||||
return $this->wrapArray($value);
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
/**
|
||||
* @param mixed[] $value
|
||||
*/
|
||||
private function wrapArray(array $value) : CurlyListNode
|
||||
{
|
||||
$wrappedValue = [];
|
||||
foreach ($value as $nestedKey => $nestedValue) {
|
||||
switch (\true) {
|
||||
case \is_numeric($nestedKey):
|
||||
$key = $nestedKey;
|
||||
break;
|
||||
default:
|
||||
$key = '"' . $nestedKey . '"';
|
||||
break;
|
||||
}
|
||||
switch (\true) {
|
||||
case \is_string($nestedValue):
|
||||
$wrappedValue[$key] = '"' . $nestedValue . '"';
|
||||
break;
|
||||
default:
|
||||
$wrappedValue[$key] = $nestedValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return new CurlyListNode($wrappedValue);
|
||||
}
|
||||
}
|
@ -14,6 +14,7 @@ use PhpParser\Node\Scalar\String_;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PhpParser\Node\Stmt\Return_;
|
||||
use PHPStan\Type\ArrayType;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDoc\DoctrineAnnotation\CurlyListNode;
|
||||
use Rector\Core\PhpParser\Node\NodeFactory;
|
||||
@ -83,12 +84,13 @@ final class ThisRenderFactory
|
||||
}
|
||||
private function resolveParametersExpr(?Return_ $return, DoctrineAnnotationTagValueNode $templateDoctrineAnnotationTagValueNode) : ?Expr
|
||||
{
|
||||
$vars = $templateDoctrineAnnotationTagValueNode->getValue('vars');
|
||||
if ($vars instanceof CurlyListNode) {
|
||||
$vars = $vars->getValuesWithExplicitSilentAndWithoutQuotes();
|
||||
$vars = [];
|
||||
$varsArrayItemNode = $templateDoctrineAnnotationTagValueNode->getValue('vars');
|
||||
if ($varsArrayItemNode instanceof ArrayItemNode && $varsArrayItemNode->value instanceof CurlyListNode) {
|
||||
$vars = $varsArrayItemNode->value->getValues();
|
||||
}
|
||||
if (\is_array($vars) && $vars !== []) {
|
||||
return $this->createArrayFromVars($vars);
|
||||
if ($vars !== []) {
|
||||
return $this->createArrayFromArrayItemNodes($vars);
|
||||
}
|
||||
if ($return === null) {
|
||||
return null;
|
||||
@ -106,13 +108,13 @@ final class ThisRenderFactory
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* @param string[] $vars
|
||||
* @param ArrayItemNode[] $arrayItemNodes
|
||||
*/
|
||||
private function createArrayFromVars(array $vars) : Array_
|
||||
private function createArrayFromArrayItemNodes(array $arrayItemNodes) : Array_
|
||||
{
|
||||
$arrayItems = [];
|
||||
foreach ($vars as $var) {
|
||||
$arrayItems[] = new ArrayItem(new Variable($var), new String_($var));
|
||||
foreach ($arrayItemNodes as $arrayItemNode) {
|
||||
$arrayItems[] = new ArrayItem(new Variable($arrayItemNode->value), new String_($arrayItemNode->value));
|
||||
}
|
||||
return new Array_($arrayItems);
|
||||
}
|
||||
@ -127,12 +129,12 @@ final class ThisRenderFactory
|
||||
private function resolveTemplate(DoctrineAnnotationTagValueNode $doctrineAnnotationTagValueNode) : ?string
|
||||
{
|
||||
$templateParameter = $doctrineAnnotationTagValueNode->getValue('template');
|
||||
if (\is_string($templateParameter)) {
|
||||
return $templateParameter;
|
||||
if ($templateParameter instanceof ArrayItemNode && \is_string($templateParameter->value)) {
|
||||
return $templateParameter->value;
|
||||
}
|
||||
$silentValue = $doctrineAnnotationTagValueNode->getSilentValue();
|
||||
if (\is_string($silentValue)) {
|
||||
return $silentValue;
|
||||
$arrayItemNode = $doctrineAnnotationTagValueNode->getSilentValue();
|
||||
if ($arrayItemNode instanceof ArrayItemNode && \is_string($arrayItemNode->value)) {
|
||||
return $arrayItemNode->value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -4,15 +4,17 @@ declare (strict_types=1);
|
||||
namespace Rector\Symfony\PhpDocNode;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
|
||||
use Rector\Symfony\Enum\SymfonyAnnotation;
|
||||
final class SymfonyRouteTagValueNodeFactory
|
||||
{
|
||||
/**
|
||||
* @param array<string, mixed> $items
|
||||
* @param ArrayItemNode[] $arrayItemNodes
|
||||
*/
|
||||
public function createFromItems(array $items) : DoctrineAnnotationTagValueNode
|
||||
public function createFromItems(array $arrayItemNodes) : DoctrineAnnotationTagValueNode
|
||||
{
|
||||
return new DoctrineAnnotationTagValueNode(new IdentifierTypeNode(SymfonyAnnotation::ROUTE), null, $items, 'path');
|
||||
$identifierTypeNode = new IdentifierTypeNode(SymfonyAnnotation::ROUTE);
|
||||
return new DoctrineAnnotationTagValueNode($identifierTypeNode, null, $arrayItemNodes, 'path');
|
||||
}
|
||||
}
|
||||
|
@ -4,13 +4,15 @@ declare (strict_types=1);
|
||||
namespace Rector\Symfony\Rector\ClassMethod;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Scalar\String_;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocParser\StaticDoctrineAnnotationParser\ArrayParser;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDoc\DoctrineAnnotation\CurlyListNode;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Symfony\Contract\Bridge\Symfony\Routing\SymfonyRoutesProviderInterface;
|
||||
use Rector\Symfony\Enum\SymfonyAnnotation;
|
||||
use Rector\Symfony\NodeFactory\Annotations\ValueQuoteWrapper;
|
||||
use Rector\Symfony\PhpDocNode\SymfonyRouteTagValueNodeFactory;
|
||||
use Rector\Symfony\ValueObject\SymfonyRouteMetadata;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
@ -32,14 +34,14 @@ final class AddRouteAnnotationRector extends AbstractRector
|
||||
private $symfonyRouteTagValueNodeFactory;
|
||||
/**
|
||||
* @readonly
|
||||
* @var \Rector\Symfony\NodeFactory\Annotations\ValueQuoteWrapper
|
||||
* @var \Rector\BetterPhpDocParser\PhpDocParser\StaticDoctrineAnnotationParser\ArrayParser
|
||||
*/
|
||||
private $valueQuoteWrapper;
|
||||
public function __construct(SymfonyRoutesProviderInterface $symfonyRoutesProvider, SymfonyRouteTagValueNodeFactory $symfonyRouteTagValueNodeFactory, ValueQuoteWrapper $valueQuoteWrapper)
|
||||
private $arrayParser;
|
||||
public function __construct(SymfonyRoutesProviderInterface $symfonyRoutesProvider, SymfonyRouteTagValueNodeFactory $symfonyRouteTagValueNodeFactory, ArrayParser $arrayParser)
|
||||
{
|
||||
$this->symfonyRoutesProvider = $symfonyRoutesProvider;
|
||||
$this->symfonyRouteTagValueNodeFactory = $symfonyRouteTagValueNodeFactory;
|
||||
$this->valueQuoteWrapper = $valueQuoteWrapper;
|
||||
$this->arrayParser = $arrayParser;
|
||||
}
|
||||
public function getNodeTypes() : array
|
||||
{
|
||||
@ -115,35 +117,42 @@ CODE_SAMPLE
|
||||
return $className . '::' . $methodName;
|
||||
}
|
||||
/**
|
||||
* @return array{path: string, name: string, defaults?: CurlyListNode, host?: string, methods?: CurlyListNode, condition?: string, options?: CurlyListNode}
|
||||
* @return ArrayItemNode[]
|
||||
*/
|
||||
private function createRouteItems(SymfonyRouteMetadata $symfonyRouteMetadata) : array
|
||||
{
|
||||
$items = ['path' => $this->valueQuoteWrapper->wrap($symfonyRouteMetadata->getPath()), 'name' => $this->valueQuoteWrapper->wrap($symfonyRouteMetadata->getName())];
|
||||
$arrayItemNodes = [];
|
||||
$arrayItemNodes[] = new ArrayItemNode($symfonyRouteMetadata->getPath(), 'path', String_::KIND_DOUBLE_QUOTED);
|
||||
$arrayItemNodes[] = new ArrayItemNode($symfonyRouteMetadata->getName(), 'name', String_::KIND_DOUBLE_QUOTED);
|
||||
$defaultsWithoutController = $symfonyRouteMetadata->getDefaultsWithoutController();
|
||||
if ($defaultsWithoutController !== []) {
|
||||
$items['defaults'] = $this->valueQuoteWrapper->wrap($defaultsWithoutController);
|
||||
$defaultsWithoutControllerCurlyList = $this->createCurlyQuoted($defaultsWithoutController);
|
||||
$arrayItemNodes[] = new ArrayItemNode($defaultsWithoutControllerCurlyList, 'defaults');
|
||||
}
|
||||
if ($symfonyRouteMetadata->getHost() !== '') {
|
||||
$items['host'] = $this->valueQuoteWrapper->wrap($symfonyRouteMetadata->getHost());
|
||||
$arrayItemNodes[] = new ArrayItemNode($symfonyRouteMetadata->getHost(), 'host');
|
||||
}
|
||||
if ($symfonyRouteMetadata->getSchemes() !== []) {
|
||||
$items['schemes'] = $this->valueQuoteWrapper->wrap($symfonyRouteMetadata->getSchemes());
|
||||
$schemesArrayItemNodes = $this->createCurlyQuoted($symfonyRouteMetadata->getSchemes());
|
||||
$arrayItemNodes[] = new ArrayItemNode($schemesArrayItemNodes, 'schemes');
|
||||
}
|
||||
if ($symfonyRouteMetadata->getMethods() !== []) {
|
||||
$items['methods'] = $this->valueQuoteWrapper->wrap($symfonyRouteMetadata->getMethods());
|
||||
$methodsCurlyList = $this->createCurlyQuoted($symfonyRouteMetadata->getMethods());
|
||||
$arrayItemNodes[] = new ArrayItemNode($methodsCurlyList, 'methods');
|
||||
}
|
||||
if ($symfonyRouteMetadata->getCondition() !== '') {
|
||||
$items['condition'] = $this->valueQuoteWrapper->wrap($symfonyRouteMetadata->getCondition());
|
||||
$arrayItemNodes[] = new ArrayItemNode($symfonyRouteMetadata->getCondition(), 'condition', String_::KIND_DOUBLE_QUOTED);
|
||||
}
|
||||
if ($symfonyRouteMetadata->getRequirements() !== []) {
|
||||
$items['requirements'] = $this->valueQuoteWrapper->wrap($symfonyRouteMetadata->getRequirements());
|
||||
$requriementsCurlyList = $this->createCurlyQuoted($symfonyRouteMetadata->getRequirements());
|
||||
$arrayItemNodes[] = new ArrayItemNode($requriementsCurlyList, 'requirements');
|
||||
}
|
||||
$optionsWithoutDefaultCompilerClass = $symfonyRouteMetadata->getOptionsWithoutDefaultCompilerClass();
|
||||
if ($optionsWithoutDefaultCompilerClass !== []) {
|
||||
$items['options'] = $this->valueQuoteWrapper->wrap($optionsWithoutDefaultCompilerClass);
|
||||
$optionsCurlyQuoted = $this->createCurlyQuoted($optionsWithoutDefaultCompilerClass);
|
||||
$arrayItemNodes[] = new ArrayItemNode($optionsCurlyQuoted, 'options');
|
||||
}
|
||||
return $items;
|
||||
return $arrayItemNodes;
|
||||
}
|
||||
private function matchSymfonyRouteMetadataByControllerReference(string $controllerReference) : ?SymfonyRouteMetadata
|
||||
{
|
||||
@ -154,4 +163,21 @@ CODE_SAMPLE
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* @param mixed[] $values
|
||||
*/
|
||||
private function createCurlyQuoted(array $values) : CurlyListNode
|
||||
{
|
||||
$methodsArrayItems = $this->arrayParser->createArrayFromValues($values);
|
||||
$curlyListNode = new CurlyListNode($methodsArrayItems);
|
||||
foreach ($curlyListNode->values as $nestedMethodsArrayItem) {
|
||||
if (!\is_numeric($nestedMethodsArrayItem->value)) {
|
||||
$nestedMethodsArrayItem->kindValueQuoted = String_::KIND_DOUBLE_QUOTED;
|
||||
}
|
||||
if (\is_string($nestedMethodsArrayItem->key)) {
|
||||
$nestedMethodsArrayItem->kindKeyQuoted = String_::KIND_DOUBLE_QUOTED;
|
||||
}
|
||||
}
|
||||
return $curlyListNode;
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ namespace Rector\Symfony\Rector\ClassMethod;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Stmt\ClassLike;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTagRemover;
|
||||
use Rector\BetterPhpDocParser\Printer\PhpDocInfoPrinter;
|
||||
@ -89,7 +90,7 @@ CODE_SAMPLE
|
||||
return null;
|
||||
}
|
||||
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node);
|
||||
$sensioDoctrineAnnotationTagValueNode = $phpDocInfo->getByAnnotationClass('Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\Method');
|
||||
$sensioDoctrineAnnotationTagValueNode = $phpDocInfo->getByAnnotationClass(SymfonyAnnotation::SENSIO_METHOD);
|
||||
if (!$sensioDoctrineAnnotationTagValueNode instanceof DoctrineAnnotationTagValueNode) {
|
||||
return null;
|
||||
}
|
||||
@ -97,11 +98,16 @@ CODE_SAMPLE
|
||||
if (!$symfonyDoctrineAnnotationTagValueNode instanceof DoctrineAnnotationTagValueNode) {
|
||||
return null;
|
||||
}
|
||||
$methods = $this->resolveMethods($sensioDoctrineAnnotationTagValueNode);
|
||||
if ($methods === null) {
|
||||
$sensioMethods = $this->resolveMethods($sensioDoctrineAnnotationTagValueNode);
|
||||
if ($sensioMethods === null) {
|
||||
return null;
|
||||
}
|
||||
$symfonyDoctrineAnnotationTagValueNode->changeValue('methods', $methods);
|
||||
$symfonyMethodsArrayItemNode = $symfonyDoctrineAnnotationTagValueNode->getValue('methods');
|
||||
// value is already filled, do not enter anythign
|
||||
if ($symfonyMethodsArrayItemNode instanceof ArrayItemNode) {
|
||||
return null;
|
||||
}
|
||||
$symfonyDoctrineAnnotationTagValueNode->values[] = new ArrayItemNode($sensioMethods, 'methods');
|
||||
$this->phpDocTagRemover->removeTagValueFromNode($phpDocInfo, $sensioDoctrineAnnotationTagValueNode);
|
||||
$this->phpDocInfoPrinter->printFormatPreserving($phpDocInfo);
|
||||
return $node;
|
||||
@ -112,18 +118,12 @@ CODE_SAMPLE
|
||||
private function resolveMethods(DoctrineAnnotationTagValueNode $doctrineAnnotationTagValueNode)
|
||||
{
|
||||
$methodsParameter = $doctrineAnnotationTagValueNode->getValue('methods');
|
||||
if (\is_array($methodsParameter)) {
|
||||
return $methodsParameter;
|
||||
if ($methodsParameter instanceof ArrayItemNode && $methodsParameter->value instanceof CurlyListNode) {
|
||||
return $methodsParameter->value;
|
||||
}
|
||||
if ($methodsParameter instanceof CurlyListNode) {
|
||||
return $methodsParameter;
|
||||
}
|
||||
$silentValue = $doctrineAnnotationTagValueNode->getSilentValue();
|
||||
if (\is_array($silentValue)) {
|
||||
return $silentValue;
|
||||
}
|
||||
if ($silentValue instanceof CurlyListNode) {
|
||||
return $silentValue;
|
||||
$arrayItemNode = $doctrineAnnotationTagValueNode->getSilentValue();
|
||||
if ($arrayItemNode instanceof ArrayItemNode) {
|
||||
return $arrayItemNode->value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace Rector\Symfony\Rector\StaticPropertyFetch;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\StaticPropertyFetch;
|
||||
use PhpParser\Node\Name;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Symfony\NodeAnalyzer\SymfonyTestCaseAnalyzer;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
/**
|
||||
* @see \Rector\Symfony\Tests\Rector\StaticPropertyFetch\KernelTestCaseContainerPropertyDeprecationRector\KernelTestCaseContainerPropertyDeprecationRectorTest
|
||||
*/
|
||||
class KernelTestCaseContainerPropertyDeprecationRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @readonly
|
||||
* @var \Rector\Symfony\NodeAnalyzer\SymfonyTestCaseAnalyzer
|
||||
*/
|
||||
private $symfonyTestCaseAnalyzer;
|
||||
public function __construct(SymfonyTestCaseAnalyzer $symfonyTestCaseAnalyzer)
|
||||
{
|
||||
$this->symfonyTestCaseAnalyzer = $symfonyTestCaseAnalyzer;
|
||||
}
|
||||
public function getRuleDefinition() : RuleDefinition
|
||||
{
|
||||
return new RuleDefinition('Simplify use of assertions in WebTestCase', [new CodeSample(<<<'CODE_SAMPLE'
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
|
||||
class SomeTest extends KernelTestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
$container = self::$container;
|
||||
}
|
||||
}
|
||||
CODE_SAMPLE
|
||||
, <<<'CODE_SAMPLE'
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
|
||||
class SomeTest extends KernelTestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
$container = self::getContainer();
|
||||
}
|
||||
}
|
||||
CODE_SAMPLE
|
||||
)]);
|
||||
}
|
||||
/**
|
||||
* @return array<class-string<Node>>
|
||||
*/
|
||||
public function getNodeTypes() : array
|
||||
{
|
||||
return [StaticPropertyFetch::class];
|
||||
}
|
||||
/**
|
||||
* @param StaticPropertyFetch $node
|
||||
*/
|
||||
public function refactor(Node $node) : ?Node
|
||||
{
|
||||
if (!$this->symfonyTestCaseAnalyzer->isInKernelTestCase($node)) {
|
||||
return null;
|
||||
}
|
||||
if ($this->nodeNameResolver->getName($node->name) !== 'container') {
|
||||
return null;
|
||||
}
|
||||
if (!$node->class instanceof Name || (string) $node->class !== 'self') {
|
||||
return null;
|
||||
}
|
||||
return $this->nodeFactory->createStaticCall('self', 'getContainer');
|
||||
}
|
||||
}
|
@ -8,6 +8,7 @@ use PHPStan\Reflection\ReflectionProvider;
|
||||
use PHPStan\Type\MixedType;
|
||||
use PHPStan\Type\ObjectType;
|
||||
use PHPStan\Type\Type;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
|
||||
use Rector\Core\Exception\ShouldNotHappenException;
|
||||
@ -99,13 +100,13 @@ final class JMSDITypeResolver
|
||||
}
|
||||
private function resolveServiceName(DoctrineAnnotationTagValueNode $doctrineAnnotationTagValueNode, Property $property) : string
|
||||
{
|
||||
$serviceNameParameter = $doctrineAnnotationTagValueNode->getValueWithoutQuotes('serviceName');
|
||||
if (\is_string($serviceNameParameter)) {
|
||||
return $serviceNameParameter;
|
||||
$serviceNameParameter = $doctrineAnnotationTagValueNode->getValue('serviceName');
|
||||
if ($serviceNameParameter instanceof ArrayItemNode && \is_string($serviceNameParameter->value)) {
|
||||
return $serviceNameParameter->value;
|
||||
}
|
||||
$silentValue = $doctrineAnnotationTagValueNode->getSilentValue();
|
||||
if (\is_string($silentValue)) {
|
||||
return $silentValue;
|
||||
$arrayItemNode = $doctrineAnnotationTagValueNode->getSilentValue();
|
||||
if ($arrayItemNode instanceof ArrayItemNode && \is_string($arrayItemNode->value)) {
|
||||
return $arrayItemNode->value;
|
||||
}
|
||||
return $this->nodeNameResolver->getName($property);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user