mirror of
https://github.com/rectorphp/rector.git
synced 2024-05-31 00:10:51 +00:00
[Nette 3.0] Add #[Inject] attribute (#5376)
This commit is contained in:
parent
2df4732c6c
commit
e1310abebb
|
@ -19,16 +19,10 @@ To get e.g. return type, use `PhpDocInfo` value object with useful methods:
|
|||
```php
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
|
||||
|
||||
// ...
|
||||
|
||||
/** @var PhpDocInfo|null $phpDocInfo */
|
||||
$phpDocInfo = $classMethod->getAttribute(AttributeKey::PHP_DOC_INFO);
|
||||
|
||||
// be always sure to check the PhpDocInfo exists and was set
|
||||
if ($phpDocInfo === null) {
|
||||
return null;
|
||||
}
|
||||
/** @var PhpDocInfoFactory $phpDocInfoFactory */
|
||||
$phpDocInfo = $phpDocInfoFactory->createFromNodeOrEmpty($classMethod);
|
||||
|
||||
// then use any method you like
|
||||
$returnType = $phpDocInfo->getReturnType();
|
||||
|
@ -39,16 +33,11 @@ var_dump($returnType);
|
|||
## How to Remove node?
|
||||
|
||||
```php
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTagRemover;
|
||||
|
||||
public function __construct(
|
||||
private PhpDocTagRemover $phpDocTagRemover
|
||||
) {
|
||||
}
|
||||
|
||||
/** @var PhpDocInfo $phpDocInfo */
|
||||
$this->phpDocTagRemover->removeByName($phpDocInfo, 'return');
|
||||
$phpDocInfo->removeByType(ReturnTagValueNode::class);
|
||||
```
|
||||
|
||||
## How create PhpDocInfo for a new node?
|
||||
|
@ -57,7 +46,10 @@ In case you build a new node and want to work with its doc block, you need to cr
|
|||
|
||||
```php
|
||||
// the "PhpDocInfoFactory" service is already available in children of "AbstractRector"
|
||||
$phpDocInfo = $this->phpDocInfoFactory->createEmpty($node);
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
|
||||
|
||||
/** @var PhpDocInfoFactory $phpDocInfoFactory */
|
||||
$phpDocInfo = $phpDocInfoFactory->createFromNodeOrEmpty($node);
|
||||
```
|
||||
|
||||
## How to get Param with Names and Types?
|
||||
|
|
|
@ -12,6 +12,11 @@ final class DataProviderTagValueNode implements PhpDocTagValueNode, AttributeAwa
|
|||
{
|
||||
use AttributeTrait;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const NAME = '@dataprovider';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
|
|
|
@ -4,23 +4,37 @@ declare(strict_types=1);
|
|||
|
||||
namespace Rector\AttributeAwarePhpDoc\Ast\PhpDoc;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
|
||||
use Rector\BetterPhpDocParser\Attributes\Attribute\AttributeTrait;
|
||||
use Rector\BetterPhpDocParser\Contract\PhpDocNode\AttributeAwareNodeInterface;
|
||||
use Rector\PhpAttribute\Contract\PhpAttributableTagNodeInterface;
|
||||
|
||||
final class RequiredTagValueNode implements PhpDocTagValueNode, AttributeAwareNodeInterface, PhpAttributableTagNodeInterface
|
||||
/**
|
||||
* Use by Symfony to autowire dependencies outside constructor,
|
||||
* @see https://symfony.com/doc/current/service_container/autowiring.html#autowiring-other-methods-e-g-setters-and-public-typed-properties
|
||||
*/
|
||||
final class SymfonyRequiredTagNode extends PhpDocTagNode implements PhpAttributableTagNodeInterface, AttributeAwareNodeInterface
|
||||
{
|
||||
use AttributeTrait;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const NAME = '@required';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(self::NAME, new AttributeAwareGenericTagValueNode(''));
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return '';
|
||||
return self::NAME;
|
||||
}
|
||||
|
||||
public function getShortName(): string
|
||||
{
|
||||
return 'Required';
|
||||
return self::NAME;
|
||||
}
|
||||
|
||||
public function getAttributeClassName(): string
|
|
@ -8,9 +8,9 @@ use Doctrine\Common\Annotations\AnnotationReader;
|
|||
use Doctrine\Common\Annotations\AnnotationRegistry;
|
||||
use Doctrine\Common\Annotations\DocParser;
|
||||
use Doctrine\Common\Annotations\Reader;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Nette\NetteInjectTagNode;
|
||||
use Rector\DoctrineAnnotationGenerated\ConstantPreservingAnnotationReader;
|
||||
use Rector\DoctrineAnnotationGenerated\ConstantPreservingDocParser;
|
||||
use Rector\PhpAttribute\ValueObject\TagName;
|
||||
|
||||
final class AnnotationReaderFactory
|
||||
{
|
||||
|
@ -39,7 +39,7 @@ final class AnnotationReaderFactory
|
|||
'Gedmo\Versioned',
|
||||
'Versioned',
|
||||
// nette @inject dummy annotation
|
||||
TagName::INJECT,
|
||||
NetteInjectTagNode::NAME,
|
||||
];
|
||||
|
||||
public function create(): Reader
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\BetterPhpDocParser\Contract;
|
||||
|
||||
interface GenericPhpDocNodeFactoryInterface extends PhpDocNodeFactoryInterface
|
||||
{
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getTagValueNodeClassesToAnnotationClasses(): array;
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\BetterPhpDocParser\Contract;
|
||||
|
||||
use PHPStan\PhpDocParser\Parser\PhpDocParser;
|
||||
|
||||
interface PhpDocParserAwareInterface
|
||||
{
|
||||
public function setPhpDocParser(PhpDocParser $phpDocParser): void;
|
||||
}
|
|
@ -7,7 +7,7 @@ namespace Rector\BetterPhpDocParser\Contract;
|
|||
interface SpecificPhpDocNodeFactoryInterface extends PhpDocNodeFactoryInterface
|
||||
{
|
||||
/**
|
||||
* @return string[]
|
||||
* @return class-string[]
|
||||
*/
|
||||
public function getClasses(): array;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\BetterPhpDocParser\Contract;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\Node;
|
||||
use PHPStan\PhpDocParser\Parser\TokenIterator;
|
||||
|
||||
interface StringTagMatchingPhpDocNodeFactoryInterface
|
||||
{
|
||||
public function match(string $tag): bool;
|
||||
|
||||
public function createFromTokens(TokenIterator $tokenIterator): ?Node;
|
||||
}
|
|
@ -5,6 +5,7 @@ declare(strict_types=1);
|
|||
namespace Rector\BetterPhpDocParser\PhpDocInfo;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PHPStan\PhpDocParser\Ast\Node as PhpDocNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\GenericTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\MethodTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode;
|
||||
|
@ -274,15 +275,19 @@ final class PhpDocInfo
|
|||
}
|
||||
|
||||
/**
|
||||
* @template T as \PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode
|
||||
* @template T as \PHPStan\PhpDocParser\Ast\Node
|
||||
* @param class-string<T> $type
|
||||
* @return T|null
|
||||
*/
|
||||
public function getByType(string $type): ?PhpDocTagValueNode
|
||||
public function getByType(string $type): ?PhpDocNode
|
||||
{
|
||||
$this->ensureTypeIsTagValueNode($type, __METHOD__);
|
||||
|
||||
foreach ($this->phpDocNode->children as $phpDocChildNode) {
|
||||
if (is_a($phpDocChildNode, $type, true)) {
|
||||
return $phpDocChildNode;
|
||||
}
|
||||
|
||||
if (! $phpDocChildNode instanceof PhpDocTagNode) {
|
||||
continue;
|
||||
}
|
||||
|
@ -309,6 +314,11 @@ final class PhpDocInfo
|
|||
$foundTagsValueNodes = [];
|
||||
|
||||
foreach ($this->phpDocNode->children as $phpDocChildNode) {
|
||||
if (is_a($phpDocChildNode, $type, true)) {
|
||||
$foundTagsValueNodes[] = $phpDocChildNode;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! $phpDocChildNode instanceof PhpDocTagNode) {
|
||||
continue;
|
||||
}
|
||||
|
@ -333,6 +343,11 @@ final class PhpDocInfo
|
|||
$this->ensureTypeIsTagValueNode($type, __METHOD__);
|
||||
|
||||
foreach ($this->phpDocNode->children as $key => $phpDocChildNode) {
|
||||
if (is_a($phpDocChildNode, $type, true)) {
|
||||
unset($this->phpDocNode->children[$key]);
|
||||
$this->markAsChanged();
|
||||
}
|
||||
|
||||
if (! $phpDocChildNode instanceof PhpDocTagNode) {
|
||||
continue;
|
||||
}
|
||||
|
@ -342,7 +357,6 @@ final class PhpDocInfo
|
|||
}
|
||||
|
||||
unset($this->phpDocNode->children[$key]);
|
||||
|
||||
$this->markAsChanged();
|
||||
}
|
||||
}
|
||||
|
@ -366,6 +380,9 @@ final class PhpDocInfo
|
|||
return $paramTypesByName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo remove to keep united API, just 1 usage
|
||||
*/
|
||||
public function addBareTag(string $tag): void
|
||||
{
|
||||
$tag = '@' . ltrim($tag, '@');
|
||||
|
@ -376,6 +393,10 @@ final class PhpDocInfo
|
|||
|
||||
public function addTagValueNode(PhpDocTagValueNode $phpDocTagValueNode): void
|
||||
{
|
||||
if (is_a($phpDocTagValueNode, PhpDocTagNode::class)) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
$name = $this->resolveNameForPhpDocTagValueNode($phpDocTagValueNode);
|
||||
|
||||
$attributeAwarePhpDocTagNode = new AttributeAwarePhpDocTagNode($name, $phpDocTagValueNode);
|
||||
|
@ -513,7 +534,7 @@ final class PhpDocInfo
|
|||
}
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
throw new NotImplementedException(get_class($phpDocTagValueNode));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -4,8 +4,8 @@ declare(strict_types=1);
|
|||
|
||||
namespace Rector\BetterPhpDocParser\PhpDocManipulator;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\Node;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
|
||||
final class PhpDocTagRemover
|
||||
|
@ -29,21 +29,26 @@ final class PhpDocTagRemover
|
|||
}
|
||||
}
|
||||
|
||||
public function removeTagValueFromNode(PhpDocInfo $phpDocInfo, PhpDocTagValueNode $phpDocTagValueNode): void
|
||||
public function removeTagValueFromNode(PhpDocInfo $phpDocInfo, Node $desiredNode): void
|
||||
{
|
||||
$attributeAwarePhpDocNode = $phpDocInfo->getPhpDocNode();
|
||||
|
||||
foreach ($attributeAwarePhpDocNode->children as $key => $phpDocChildNode) {
|
||||
if ($phpDocChildNode === $desiredNode) {
|
||||
unset($attributeAwarePhpDocNode->children[$key]);
|
||||
$phpDocInfo->markAsChanged();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! $phpDocChildNode instanceof PhpDocTagNode) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($phpDocChildNode->value !== $phpDocTagValueNode) {
|
||||
if ($phpDocChildNode->value !== $desiredNode) {
|
||||
continue;
|
||||
}
|
||||
|
||||
unset($attributeAwarePhpDocNode->children[$key]);
|
||||
|
||||
$phpDocInfo->markAsChanged();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\BetterPhpDocParser\PhpDocNodeFactory\Doctrine\Property_;
|
||||
|
||||
use Doctrine\ORM\Mapping\Embedded;
|
||||
use PhpParser\Node;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
|
||||
use PHPStan\PhpDocParser\Parser\TokenIterator;
|
||||
use Rector\BetterPhpDocParser\Contract\GenericPhpDocNodeFactoryInterface;
|
||||
use Rector\BetterPhpDocParser\PhpDocNodeFactory\AbstractPhpDocNodeFactory;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Doctrine\Class_\EmbeddedTagValueNode;
|
||||
|
||||
final class DoctrineEmbeddedPhpDocNodeFactory extends AbstractPhpDocNodeFactory implements GenericPhpDocNodeFactoryInterface
|
||||
{
|
||||
/**
|
||||
* @return array<string, string>
|
||||
*/
|
||||
public function getTagValueNodeClassesToAnnotationClasses(): array
|
||||
{
|
||||
return [
|
||||
EmbeddedTagValueNode::class => 'Doctrine\ORM\Mapping\Embedded',
|
||||
];
|
||||
}
|
||||
|
||||
public function createFromNodeAndTokens(
|
||||
Node $node,
|
||||
TokenIterator $tokenIterator,
|
||||
string $annotationClass
|
||||
): ?PhpDocTagValueNode {
|
||||
$annotation = $this->nodeAnnotationReader->readAnnotation($node, $annotationClass);
|
||||
if (! $annotation instanceof Embedded) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$content = $this->resolveContentFromTokenIterator($tokenIterator);
|
||||
$items = $this->annotationItemsResolver->resolve($annotation);
|
||||
$fullyQualifiedClassName = $this->resolveFqnTargetEntity($annotation->class, $node);
|
||||
|
||||
return new EmbeddedTagValueNode($items, $content, $fullyQualifiedClassName);
|
||||
}
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\BetterPhpDocParser\PhpDocNodeFactory\Doctrine\Property_;
|
||||
|
||||
use Doctrine\ORM\Mapping\ManyToMany;
|
||||
use Doctrine\ORM\Mapping\ManyToOne;
|
||||
use Doctrine\ORM\Mapping\OneToMany;
|
||||
use Doctrine\ORM\Mapping\OneToOne;
|
||||
use PhpParser\Node;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
|
||||
use PHPStan\PhpDocParser\Parser\TokenIterator;
|
||||
use Rector\BetterPhpDocParser\Contract\GenericPhpDocNodeFactoryInterface;
|
||||
use Rector\BetterPhpDocParser\PhpDocNodeFactory\AbstractPhpDocNodeFactory;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Doctrine\Property_\ManyToManyTagValueNode;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Doctrine\Property_\ManyToOneTagValueNode;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Doctrine\Property_\OneToManyTagValueNode;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Doctrine\Property_\OneToOneTagValueNode;
|
||||
|
||||
final class DoctrineTargetEntityPhpDocNodeFactory extends AbstractPhpDocNodeFactory implements GenericPhpDocNodeFactoryInterface
|
||||
{
|
||||
/**
|
||||
* @return array<string, string>
|
||||
*/
|
||||
public function getTagValueNodeClassesToAnnotationClasses(): array
|
||||
{
|
||||
return [
|
||||
OneToOneTagValueNode::class => 'Doctrine\ORM\Mapping\OneToOne',
|
||||
OneToManyTagValueNode::class => 'Doctrine\ORM\Mapping\OneToMany',
|
||||
ManyToManyTagValueNode::class => 'Doctrine\ORM\Mapping\ManyToMany',
|
||||
ManyToOneTagValueNode::class => 'Doctrine\ORM\Mapping\ManyToOne',
|
||||
];
|
||||
}
|
||||
|
||||
public function createFromNodeAndTokens(
|
||||
Node $node,
|
||||
TokenIterator $tokenIterator,
|
||||
string $annotationClass
|
||||
): ?PhpDocTagValueNode {
|
||||
/** @var OneToOne|OneToMany|ManyToMany|ManyToOne|null $annotation */
|
||||
$annotation = $this->nodeAnnotationReader->readAnnotation($node, $annotationClass);
|
||||
if ($annotation === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$tagValueNodeClassesToAnnotationClasses = $this->getTagValueNodeClassesToAnnotationClasses();
|
||||
$tagValueNodeClass = array_search($annotationClass, $tagValueNodeClassesToAnnotationClasses, true);
|
||||
|
||||
$content = $this->resolveContentFromTokenIterator($tokenIterator);
|
||||
$items = $this->annotationItemsResolver->resolve($annotation);
|
||||
$fullyQualifiedTargetEntity = $this->resolveFqnTargetEntity($annotation->targetEntity, $node);
|
||||
|
||||
return new $tagValueNodeClass($items, $content, $fullyQualifiedTargetEntity);
|
||||
}
|
||||
}
|
|
@ -4,11 +4,20 @@ declare(strict_types=1);
|
|||
|
||||
namespace Rector\BetterPhpDocParser\PhpDocNodeFactory;
|
||||
|
||||
use Doctrine\ORM\Mapping\Annotation;
|
||||
use Doctrine\ORM\Mapping\Embedded;
|
||||
use Doctrine\ORM\Mapping\ManyToMany;
|
||||
use Doctrine\ORM\Mapping\ManyToOne;
|
||||
use Doctrine\ORM\Mapping\OneToMany;
|
||||
use Doctrine\ORM\Mapping\OneToOne;
|
||||
use PhpParser\Node;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
|
||||
use PHPStan\PhpDocParser\Parser\TokenIterator;
|
||||
use Rector\BetterPhpDocParser\Contract\GenericPhpDocNodeFactoryInterface;
|
||||
use Rector\BetterPhpDocParser\Contract\Doctrine\DoctrineRelationTagValueNodeInterface;
|
||||
use Rector\BetterPhpDocParser\Contract\PhpDocNodeFactoryInterface;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\AbstractTagValueNode;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Doctrine\Class_\EmbeddableTagValueNode;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Doctrine\Class_\EmbeddedTagValueNode;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Doctrine\Class_\EntityTagValueNode;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Doctrine\Class_\InheritanceTypeTagValueNode;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Doctrine\Property_\ColumnTagValueNode;
|
||||
|
@ -16,6 +25,10 @@ use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Doctrine\Property_\CustomId
|
|||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Doctrine\Property_\GeneratedValueTagValueNode;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Doctrine\Property_\IdTagValueNode;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Doctrine\Property_\JoinColumnTagValueNode;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Doctrine\Property_\ManyToManyTagValueNode;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Doctrine\Property_\ManyToOneTagValueNode;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Doctrine\Property_\OneToManyTagValueNode;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Doctrine\Property_\OneToOneTagValueNode;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Gedmo\BlameableTagValueNode;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Gedmo\LocaleTagValueNode;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Gedmo\LoggableTagValueNode;
|
||||
|
@ -42,10 +55,10 @@ use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Symfony\Validator\Constrain
|
|||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Symfony\Validator\Constraints\AssertRangeTagValueNode;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Symfony\Validator\Constraints\AssertTypeTagValueNode;
|
||||
|
||||
final class MultiPhpDocNodeFactory extends AbstractPhpDocNodeFactory implements GenericPhpDocNodeFactoryInterface
|
||||
final class MultiPhpDocNodeFactory extends AbstractPhpDocNodeFactory implements PhpDocNodeFactoryInterface
|
||||
{
|
||||
/**
|
||||
* @return array<string, string>
|
||||
* @return array<class-string<AbstractTagValueNode>, class-string<Annotation>>
|
||||
*/
|
||||
public function getTagValueNodeClassesToAnnotationClasses(): array
|
||||
{
|
||||
|
@ -91,6 +104,15 @@ final class MultiPhpDocNodeFactory extends AbstractPhpDocNodeFactory implements
|
|||
JMSServiceValueNode::class => 'JMS\DiExtraBundle\Annotation\Service',
|
||||
SerializerTypeTagValueNode::class => 'JMS\Serializer\Annotation\Type',
|
||||
PHPDIInjectTagValueNode::class => 'DI\Annotation\Inject',
|
||||
|
||||
// Doctrine
|
||||
OneToOneTagValueNode::class => 'Doctrine\ORM\Mapping\OneToOne',
|
||||
OneToManyTagValueNode::class => 'Doctrine\ORM\Mapping\OneToMany',
|
||||
ManyToManyTagValueNode::class => 'Doctrine\ORM\Mapping\ManyToMany',
|
||||
ManyToOneTagValueNode::class => 'Doctrine\ORM\Mapping\ManyToOne',
|
||||
|
||||
// @todo cover with reflection / services to avoid forgetting registering it?
|
||||
EmbeddedTagValueNode::class => 'Doctrine\ORM\Mapping\Embedded',
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -99,17 +121,38 @@ final class MultiPhpDocNodeFactory extends AbstractPhpDocNodeFactory implements
|
|||
TokenIterator $tokenIterator,
|
||||
string $annotationClass
|
||||
): ?PhpDocTagValueNode {
|
||||
$tagValueNodeClassesToAnnotationClasses = $this->getTagValueNodeClassesToAnnotationClasses();
|
||||
$tagValueNodeClass = array_search($annotationClass, $tagValueNodeClassesToAnnotationClasses, true);
|
||||
|
||||
$annotation = $this->nodeAnnotationReader->readAnnotation($node, $annotationClass);
|
||||
if ($annotation === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$tagValueNodeClassesToAnnotationClasses = $this->getTagValueNodeClassesToAnnotationClasses();
|
||||
$tagValueNodeClass = array_search($annotationClass, $tagValueNodeClassesToAnnotationClasses, true);
|
||||
if ($tagValueNodeClass === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$items = $this->annotationItemsResolver->resolve($annotation);
|
||||
$content = $this->annotationContentResolver->resolveFromTokenIterator($tokenIterator);
|
||||
|
||||
if (is_a($tagValueNodeClass, DoctrineRelationTagValueNodeInterface::class, true)) {
|
||||
/** @var ManyToOne|OneToMany|ManyToMany|OneToOne|Embedded $annotation */
|
||||
$fullyQualifiedTargetEntity = $this->resolveEntityClass($annotation, $node);
|
||||
return new $tagValueNodeClass($items, $content, $fullyQualifiedTargetEntity);
|
||||
}
|
||||
|
||||
return new $tagValueNodeClass($items, $content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ManyToOne|OneToMany|ManyToMany|OneToOne|Embedded $annotation
|
||||
*/
|
||||
private function resolveEntityClass(object $annotation, Node $node): string
|
||||
{
|
||||
if ($annotation instanceof Embedded) {
|
||||
return $this->resolveFqnTargetEntity($annotation->class, $node);
|
||||
}
|
||||
|
||||
return $this->resolveFqnTargetEntity($annotation->targetEntity, $node);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\BetterPhpDocParser\PhpDocNodeFactory\StringMatchingPhpDocNodeFactory;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\Node;
|
||||
use PHPStan\PhpDocParser\Parser\TokenIterator;
|
||||
use Rector\BetterPhpDocParser\Contract\StringTagMatchingPhpDocNodeFactoryInterface;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Nette\NetteCrossOriginTagNode;
|
||||
|
||||
final class NetteCrossOriginPhpDocNodeFactory implements StringTagMatchingPhpDocNodeFactoryInterface
|
||||
{
|
||||
public function match(string $tag): bool
|
||||
{
|
||||
return $tag === NetteCrossOriginTagNode::NAME;
|
||||
}
|
||||
|
||||
public function createFromTokens(TokenIterator $tokenIterator): ?Node
|
||||
{
|
||||
return new NetteCrossOriginTagNode();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\BetterPhpDocParser\PhpDocNodeFactory\StringMatchingPhpDocNodeFactory;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\Node;
|
||||
use PHPStan\PhpDocParser\Parser\TokenIterator;
|
||||
use Rector\BetterPhpDocParser\Contract\StringTagMatchingPhpDocNodeFactoryInterface;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Nette\NetteInjectTagNode;
|
||||
|
||||
final class NetteInjectPhpDocNodeFactory implements StringTagMatchingPhpDocNodeFactoryInterface
|
||||
{
|
||||
public function match(string $tag): bool
|
||||
{
|
||||
return $tag === NetteInjectTagNode::NAME;
|
||||
}
|
||||
|
||||
public function createFromTokens(TokenIterator $tokenIterator): ?Node
|
||||
{
|
||||
return new NetteInjectTagNode();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\BetterPhpDocParser\PhpDocNodeFactory\StringMatchingPhpDocNodeFactory;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\Node;
|
||||
use PHPStan\PhpDocParser\Parser\TokenIterator;
|
||||
use Rector\BetterPhpDocParser\Contract\StringTagMatchingPhpDocNodeFactoryInterface;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Nette\NetteCrossOriginTagNode;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Nette\NettePersistentTagNode;
|
||||
|
||||
final class NettePersistentPhpDocNodeFactory implements StringTagMatchingPhpDocNodeFactoryInterface
|
||||
{
|
||||
public function match(string $tag): bool
|
||||
{
|
||||
return $tag === NettePersistentTagNode::NAME;
|
||||
}
|
||||
|
||||
public function createFromTokens(TokenIterator $tokenIterator): ?Node
|
||||
{
|
||||
return new NettePersistentTagNode();
|
||||
}
|
||||
}
|
|
@ -2,17 +2,20 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\BetterPhpDocParser\PhpDocNodeFactory;
|
||||
namespace Rector\BetterPhpDocParser\PhpDocNodeFactory\StringMatchingPhpDocNodeFactory;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\Node;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\InvalidTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
|
||||
use PHPStan\PhpDocParser\Parser\ParserException;
|
||||
use PHPStan\PhpDocParser\Parser\PhpDocParser;
|
||||
use PHPStan\PhpDocParser\Parser\TokenIterator;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\DataProviderTagValueNode;
|
||||
use Rector\BetterPhpDocParser\Contract\PhpDocParserAwareInterface;
|
||||
use Rector\BetterPhpDocParser\Contract\StringTagMatchingPhpDocNodeFactoryInterface;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\PHPUnit\PHPUnitDataProviderTagValueNode;
|
||||
use Symplify\PackageBuilder\Reflection\PrivatesCaller;
|
||||
|
||||
final class PHPUnitDataProviderDocNodeFactory
|
||||
final class PHPUnitDataProviderDocNodeFactory implements StringTagMatchingPhpDocNodeFactoryInterface, PhpDocParserAwareInterface
|
||||
{
|
||||
/**
|
||||
* @var PrivatesCaller
|
||||
|
@ -29,14 +32,14 @@ final class PHPUnitDataProviderDocNodeFactory
|
|||
$this->privatesCaller = $privatesCaller;
|
||||
}
|
||||
|
||||
public function createFromTokens(TokenIterator $tokenIterator): ?PhpDocTagValueNode
|
||||
public function createFromTokens(TokenIterator $tokenIterator): ?Node
|
||||
{
|
||||
try {
|
||||
$tokenIterator->pushSavePoint();
|
||||
$attributeAwareDataProviderTagValueNode = $this->parseDataProviderTagValue($tokenIterator);
|
||||
$phpUnitDataProviderTagValueNode = $this->parseDataProviderTagValue($tokenIterator);
|
||||
$tokenIterator->dropSavePoint();
|
||||
|
||||
return $attributeAwareDataProviderTagValueNode;
|
||||
return $phpUnitDataProviderTagValueNode;
|
||||
} catch (ParserException $parserException) {
|
||||
$tokenIterator->rollback();
|
||||
$description = $this->privatesCaller->callPrivateMethod(
|
||||
|
@ -45,7 +48,8 @@ final class PHPUnitDataProviderDocNodeFactory
|
|||
[$tokenIterator]
|
||||
);
|
||||
|
||||
return new InvalidTagValueNode($description, $parserException);
|
||||
$invalidTagValueNode = new InvalidTagValueNode($description, $parserException);
|
||||
return new PhpDocTagNode('', $invalidTagValueNode);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,10 +61,15 @@ final class PHPUnitDataProviderDocNodeFactory
|
|||
$this->phpDocParser = $phpDocParser;
|
||||
}
|
||||
|
||||
public function match(string $tag): bool
|
||||
{
|
||||
return strtolower($tag) === PHPUnitDataProviderTagValueNode::NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override of parent private method to allow reference: https://github.com/rectorphp/rector/pull/1735
|
||||
*/
|
||||
private function parseDataProviderTagValue(TokenIterator $tokenIterator): DataProviderTagValueNode
|
||||
private function parseDataProviderTagValue(TokenIterator $tokenIterator): PHPUnitDataProviderTagValueNode
|
||||
{
|
||||
$method = $this->privatesCaller->callPrivateMethod(
|
||||
$this->phpDocParser,
|
||||
|
@ -68,6 +77,6 @@ final class PHPUnitDataProviderDocNodeFactory
|
|||
[$tokenIterator]
|
||||
);
|
||||
|
||||
return new DataProviderTagValueNode($method);
|
||||
return new PHPUnitDataProviderTagValueNode($method);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\BetterPhpDocParser\PhpDocNodeFactory\StringMatchingPhpDocNodeFactory;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\Node;
|
||||
use PHPStan\PhpDocParser\Parser\TokenIterator;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\SymfonyRequiredTagNode;
|
||||
use Rector\BetterPhpDocParser\Contract\StringTagMatchingPhpDocNodeFactoryInterface;
|
||||
|
||||
final class SymfonyRequirePhpDocNodeFactory implements StringTagMatchingPhpDocNodeFactoryInterface
|
||||
{
|
||||
public function match(string $tag): bool
|
||||
{
|
||||
return $tag === SymfonyRequiredTagNode::NAME;
|
||||
}
|
||||
|
||||
public function createFromTokens(TokenIterator $tokenIterator): ?Node
|
||||
{
|
||||
return new SymfonyRequiredTagNode();
|
||||
}
|
||||
}
|
|
@ -15,18 +15,17 @@ use PHPStan\PhpDocParser\Parser\PhpDocParser;
|
|||
use PHPStan\PhpDocParser\Parser\TokenIterator;
|
||||
use PHPStan\PhpDocParser\Parser\TypeParser;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwarePhpDocNode;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\RequiredTagValueNode;
|
||||
use Rector\BetterPhpDocParser\Attributes\Ast\AttributeAwareNodeFactory;
|
||||
use Rector\BetterPhpDocParser\Attributes\Attribute\Attribute;
|
||||
use Rector\BetterPhpDocParser\Contract\GenericPhpDocNodeFactoryInterface;
|
||||
use Rector\BetterPhpDocParser\Contract\PhpDocNodeFactoryInterface;
|
||||
use Rector\BetterPhpDocParser\Contract\PhpDocParserAwareInterface;
|
||||
use Rector\BetterPhpDocParser\Contract\SpecificPhpDocNodeFactoryInterface;
|
||||
use Rector\BetterPhpDocParser\PhpDocNodeFactory\PHPUnitDataProviderDocNodeFactory;
|
||||
use Rector\BetterPhpDocParser\Contract\StringTagMatchingPhpDocNodeFactoryInterface;
|
||||
use Rector\BetterPhpDocParser\PhpDocNodeFactory\MultiPhpDocNodeFactory;
|
||||
use Rector\BetterPhpDocParser\Printer\MultilineSpaceFormatPreserver;
|
||||
use Rector\BetterPhpDocParser\ValueObject\StartAndEnd;
|
||||
use Rector\Core\Configuration\CurrentNodeProvider;
|
||||
use Rector\Core\Exception\ShouldNotHappenException;
|
||||
use Rector\PhpAttribute\ValueObject\TagName;
|
||||
use Symplify\PackageBuilder\Reflection\PrivatesAccessor;
|
||||
use Symplify\PackageBuilder\Reflection\PrivatesCaller;
|
||||
|
||||
|
@ -82,12 +81,13 @@ final class BetterPhpDocParser extends PhpDocParser
|
|||
private $annotationContentResolver;
|
||||
|
||||
/**
|
||||
* @var PHPUnitDataProviderDocNodeFactory
|
||||
* @var StringTagMatchingPhpDocNodeFactoryInterface[]
|
||||
*/
|
||||
private $phpUnitDataProviderDocNodeFactory;
|
||||
private $stringTagMatchingPhpDocNodeFactories = [];
|
||||
|
||||
/**
|
||||
* @param PhpDocNodeFactoryInterface[] $phpDocNodeFactories
|
||||
* @param StringTagMatchingPhpDocNodeFactoryInterface[] $stringTagMatchingPhpDocNodeFactories
|
||||
*/
|
||||
public function __construct(
|
||||
TypeParser $typeParser,
|
||||
|
@ -97,8 +97,8 @@ final class BetterPhpDocParser extends PhpDocParser
|
|||
CurrentNodeProvider $currentNodeProvider,
|
||||
ClassAnnotationMatcher $classAnnotationMatcher,
|
||||
AnnotationContentResolver $annotationContentResolver,
|
||||
PHPUnitDataProviderDocNodeFactory $phpUnitDataProviderDocNodeFactory,
|
||||
array $phpDocNodeFactories = []
|
||||
array $phpDocNodeFactories = [],
|
||||
array $stringTagMatchingPhpDocNodeFactories = []
|
||||
) {
|
||||
parent::__construct($typeParser, $constExprParser);
|
||||
|
||||
|
@ -109,9 +109,9 @@ final class BetterPhpDocParser extends PhpDocParser
|
|||
$this->currentNodeProvider = $currentNodeProvider;
|
||||
$this->classAnnotationMatcher = $classAnnotationMatcher;
|
||||
$this->annotationContentResolver = $annotationContentResolver;
|
||||
$this->phpUnitDataProviderDocNodeFactory = $phpUnitDataProviderDocNodeFactory;
|
||||
|
||||
$this->setPhpDocNodeFactories($phpDocNodeFactories);
|
||||
$this->stringTagMatchingPhpDocNodeFactories = $stringTagMatchingPhpDocNodeFactories;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -150,43 +150,41 @@ final class BetterPhpDocParser extends PhpDocParser
|
|||
{
|
||||
$tag = $this->resolveTag($tokenIterator);
|
||||
|
||||
$phpDocTagValueNode = $this->parseTagValue($tokenIterator, $tag);
|
||||
$phpDocTagNode = $this->createPhpDocTagNodeFromStringMatch($tag, $tokenIterator);
|
||||
if ($phpDocTagNode instanceof PhpDocTagNode) {
|
||||
return $phpDocTagNode;
|
||||
}
|
||||
|
||||
if ($phpDocTagNode instanceof PhpDocTagValueNode) {
|
||||
return new PhpDocTagNode($tag, $phpDocTagNode);
|
||||
}
|
||||
|
||||
$phpDocTagValueNode = $this->parseTagValue($tokenIterator, $tag);
|
||||
return new PhpDocTagNode($tag, $phpDocTagValueNode);
|
||||
}
|
||||
|
||||
public function parseTagValue(TokenIterator $tokenIterator, string $tag): PhpDocTagValueNode
|
||||
{
|
||||
// needed for reference support in params, see https://github.com/rectorphp/rector/issues/1734
|
||||
$tagValueNode = null;
|
||||
|
||||
$currentPhpNode = $this->currentNodeProvider->getNode();
|
||||
if (! $currentPhpNode instanceof \PhpParser\Node) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
$lowercasedTag = strtolower($tag);
|
||||
$tagValueNode = null;
|
||||
|
||||
if ($lowercasedTag === '@dataprovider') {
|
||||
$this->phpUnitDataProviderDocNodeFactory->setPhpDocParser($this);
|
||||
$tagValueNode = $this->phpUnitDataProviderDocNodeFactory->createFromTokens($tokenIterator);
|
||||
} elseif ($lowercasedTag === '@' . TagName::REQUIRED) {
|
||||
$tagValueNode = new RequiredTagValueNode();
|
||||
} else {
|
||||
// class-annotation
|
||||
$phpDocNodeFactory = $this->matchTagToPhpDocNodeFactory($tag);
|
||||
if ($phpDocNodeFactory !== null) {
|
||||
$fullyQualifiedAnnotationClass = $this->classAnnotationMatcher->resolveTagFullyQualifiedName(
|
||||
$tag,
|
||||
$currentPhpNode
|
||||
);
|
||||
// class-annotation
|
||||
$phpDocNodeFactory = $this->matchTagToPhpDocNodeFactory($tag);
|
||||
if ($phpDocNodeFactory !== null) {
|
||||
$fullyQualifiedAnnotationClass = $this->classAnnotationMatcher->resolveTagFullyQualifiedName(
|
||||
$tag,
|
||||
$currentPhpNode
|
||||
);
|
||||
|
||||
$tagValueNode = $phpDocNodeFactory->createFromNodeAndTokens(
|
||||
$currentPhpNode,
|
||||
$tokenIterator,
|
||||
$fullyQualifiedAnnotationClass
|
||||
);
|
||||
}
|
||||
$tagValueNode = $phpDocNodeFactory->createFromNodeAndTokens(
|
||||
$currentPhpNode,
|
||||
$tokenIterator,
|
||||
$fullyQualifiedAnnotationClass
|
||||
);
|
||||
}
|
||||
|
||||
$originalTokenIterator = clone $tokenIterator;
|
||||
|
@ -303,7 +301,7 @@ final class BetterPhpDocParser extends PhpDocParser
|
|||
return $phpDocNodeFactory->getClasses();
|
||||
}
|
||||
|
||||
if ($phpDocNodeFactory instanceof GenericPhpDocNodeFactoryInterface) {
|
||||
if ($phpDocNodeFactory instanceof MultiPhpDocNodeFactory) {
|
||||
return $phpDocNodeFactory->getTagValueNodeClassesToAnnotationClasses();
|
||||
}
|
||||
|
||||
|
@ -373,4 +371,21 @@ final class BetterPhpDocParser extends PhpDocParser
|
|||
|
||||
return $tokenEnd;
|
||||
}
|
||||
|
||||
private function createPhpDocTagNodeFromStringMatch(string $tag, TokenIterator $tokenIterator): ?Node
|
||||
{
|
||||
foreach ($this->stringTagMatchingPhpDocNodeFactories as $stringTagMatchingPhpDocNodeFactory) {
|
||||
if (! $stringTagMatchingPhpDocNodeFactory->match($tag)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($stringTagMatchingPhpDocNodeFactory instanceof PhpDocParserAwareInterface) {
|
||||
$stringTagMatchingPhpDocNodeFactory->setPhpDocParser($this);
|
||||
}
|
||||
|
||||
return $stringTagMatchingPhpDocNodeFactory->createFromTokens($tokenIterator);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ use Rector\NodeTypeResolver\Node\AttributeKey;
|
|||
final class ClassAnnotationMatcher
|
||||
{
|
||||
/**
|
||||
* @var string[]
|
||||
* @var array<string, string>
|
||||
*/
|
||||
private $fullyQualifiedNameByHash = [];
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@ use PHPStan\PhpDocParser\Ast\PhpDoc\ThrowsTagValueNode;
|
|||
use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
|
||||
use PHPStan\PhpDocParser\Lexer\Lexer;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwarePhpDocNode;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwarePhpDocTagNode;
|
||||
use Rector\BetterPhpDocParser\Attributes\Attribute\Attribute;
|
||||
use Rector\BetterPhpDocParser\Contract\PhpDocNode\AttributeAwareNodeInterface;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
|
@ -326,7 +325,6 @@ final class PhpDocInfoPrinter
|
|||
$output .= $tagSpaceSeparator;
|
||||
}
|
||||
|
||||
/** @var AttributeAwarePhpDocTagNode $phpDocTagNode */
|
||||
if ($this->hasDescription($phpDocTagNode)) {
|
||||
$quotedDescription = preg_quote($phpDocTagNode->value->description, '#');
|
||||
$pattern = Strings::replace($quotedDescription, '#[\s]+#', '\s+');
|
||||
|
@ -421,20 +419,24 @@ final class PhpDocInfoPrinter
|
|||
return '';
|
||||
}
|
||||
|
||||
private function hasDescription(AttributeAwarePhpDocTagNode $attributeAwarePhpDocTagNode): bool
|
||||
/**
|
||||
* @param AttributeAwareNodeInterface&PhpDocTagNode $phpDocTagNode
|
||||
*/
|
||||
private function hasDescription(PhpDocTagNode $phpDocTagNode): bool
|
||||
{
|
||||
$hasDescriptionWithOriginalSpaces = $attributeAwarePhpDocTagNode->getAttribute(
|
||||
$hasDescriptionWithOriginalSpaces = $phpDocTagNode->getAttribute(
|
||||
Attribute::HAS_DESCRIPTION_WITH_ORIGINAL_SPACES
|
||||
);
|
||||
|
||||
if (! $hasDescriptionWithOriginalSpaces) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! property_exists($attributeAwarePhpDocTagNode->value, 'description')) {
|
||||
if (! property_exists($phpDocTagNode->value, 'description')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (bool) $attributeAwarePhpDocTagNode->value->description;
|
||||
return (bool) $phpDocTagNode->value->description;
|
||||
}
|
||||
|
||||
private function explodeAndImplode(string $content, string $explodeChar, string $implodeChar): string
|
||||
|
|
|
@ -3,9 +3,10 @@ declare(strict_types=1);
|
|||
|
||||
namespace Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Doctrine\Class_;
|
||||
|
||||
use Rector\BetterPhpDocParser\Contract\Doctrine\DoctrineRelationTagValueNodeInterface;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Doctrine\AbstractDoctrineTagValueNode;
|
||||
|
||||
final class EmbeddedTagValueNode extends AbstractDoctrineTagValueNode
|
||||
final class EmbeddedTagValueNode extends AbstractDoctrineTagValueNode implements DoctrineRelationTagValueNodeInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
|
@ -24,18 +25,23 @@ final class EmbeddedTagValueNode extends AbstractDoctrineTagValueNode
|
|||
return '@ORM\Embedded';
|
||||
}
|
||||
|
||||
public function getClass(): string
|
||||
{
|
||||
return $this->items['class'];
|
||||
}
|
||||
|
||||
public function getFullyQualifiedClassName(): string
|
||||
{
|
||||
return $this->fullyQualifiedClassName;
|
||||
}
|
||||
|
||||
public function getColumnPrefix(): ?string
|
||||
{
|
||||
return $this->items['columnPrefix'];
|
||||
}
|
||||
|
||||
public function getTargetEntity(): ?string
|
||||
{
|
||||
return $this->items['class'];
|
||||
}
|
||||
|
||||
public function getFullyQualifiedTargetEntity(): string
|
||||
{
|
||||
return $this->fullyQualifiedClassName;
|
||||
}
|
||||
|
||||
public function changeTargetEntity(string $targetEntity): void
|
||||
{
|
||||
$this->items['class'] = $targetEntity;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ namespace Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Doctrine\Class_;
|
|||
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Doctrine\AbstractDoctrineTagValueNode;
|
||||
use Rector\PhpAttribute\Contract\PhpAttributableTagNodeInterface;
|
||||
use Rector\PhpAttribute\Printer\PhpAttributeGroupFactory;
|
||||
|
||||
final class EntityTagValueNode extends AbstractDoctrineTagValueNode implements PhpAttributableTagNodeInterface
|
||||
{
|
||||
|
@ -39,6 +40,6 @@ final class EntityTagValueNode extends AbstractDoctrineTagValueNode implements P
|
|||
|
||||
public function getAttributeClassName(): string
|
||||
{
|
||||
return 'TBA';
|
||||
return PhpAttributeGroupFactory::TO_BE_ANNOUNCED;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ namespace Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Doctrine\Property_;
|
|||
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Doctrine\AbstractDoctrineTagValueNode;
|
||||
use Rector\PhpAttribute\Contract\PhpAttributableTagNodeInterface;
|
||||
use Rector\PhpAttribute\Printer\PhpAttributeGroupFactory;
|
||||
|
||||
final class ColumnTagValueNode extends AbstractDoctrineTagValueNode implements PhpAttributableTagNodeInterface
|
||||
{
|
||||
|
@ -39,6 +40,6 @@ final class ColumnTagValueNode extends AbstractDoctrineTagValueNode implements P
|
|||
|
||||
public function getAttributeClassName(): string
|
||||
{
|
||||
return 'TBA';
|
||||
return PhpAttributeGroupFactory::TO_BE_ANNOUNCED;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ namespace Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Doctrine\Property_;
|
|||
use Rector\BetterPhpDocParser\Contract\PhpDocNode\SilentKeyNodeInterface;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Doctrine\AbstractDoctrineTagValueNode;
|
||||
use Rector\PhpAttribute\Contract\PhpAttributableTagNodeInterface;
|
||||
use Rector\PhpAttribute\Printer\PhpAttributeGroupFactory;
|
||||
|
||||
/**
|
||||
* @see \Rector\BetterPhpDocParser\Tests\PhpDocParser\TagValueNodeReprint\TagValueNodeReprintTest
|
||||
|
@ -25,6 +26,6 @@ final class GeneratedValueTagValueNode extends AbstractDoctrineTagValueNode impl
|
|||
|
||||
public function getAttributeClassName(): string
|
||||
{
|
||||
return 'TBA';
|
||||
return PhpAttributeGroupFactory::TO_BE_ANNOUNCED;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ namespace Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Doctrine\Property_;
|
|||
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Doctrine\AbstractDoctrineTagValueNode;
|
||||
use Rector\PhpAttribute\Contract\PhpAttributableTagNodeInterface;
|
||||
use Rector\PhpAttribute\Printer\PhpAttributeGroupFactory;
|
||||
|
||||
final class IdTagValueNode extends AbstractDoctrineTagValueNode implements PhpAttributableTagNodeInterface
|
||||
{
|
||||
|
@ -16,6 +17,6 @@ final class IdTagValueNode extends AbstractDoctrineTagValueNode implements PhpAt
|
|||
|
||||
public function getAttributeClassName(): string
|
||||
{
|
||||
return 'TBA';
|
||||
return PhpAttributeGroupFactory::TO_BE_ANNOUNCED;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ namespace Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Doctrine\Property_;
|
|||
use Rector\BetterPhpDocParser\Contract\PhpDocNode\TagAwareNodeInterface;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Doctrine\AbstractDoctrineTagValueNode;
|
||||
use Rector\PhpAttribute\Contract\PhpAttributableTagNodeInterface;
|
||||
use Rector\PhpAttribute\Printer\PhpAttributeGroupFactory;
|
||||
|
||||
final class JoinColumnTagValueNode extends AbstractDoctrineTagValueNode implements TagAwareNodeInterface, PhpAttributableTagNodeInterface
|
||||
{
|
||||
|
@ -54,6 +55,6 @@ final class JoinColumnTagValueNode extends AbstractDoctrineTagValueNode implemen
|
|||
|
||||
public function getAttributeClassName(): string
|
||||
{
|
||||
return 'TBA';
|
||||
return PhpAttributeGroupFactory::TO_BE_ANNOUNCED;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Doctrine\AbstractDoctrineTa
|
|||
use Rector\Core\Exception\ShouldNotHappenException;
|
||||
use Rector\PhpAttribute\Contract\ManyPhpAttributableTagNodeInterface;
|
||||
use Rector\PhpAttribute\Contract\PhpAttributableTagNodeInterface;
|
||||
use Rector\PhpAttribute\Printer\PhpAttributeGroupFactory;
|
||||
|
||||
final class JoinTableTagValueNode extends AbstractDoctrineTagValueNode implements PhpAttributableTagNodeInterface, ManyPhpAttributableTagNodeInterface
|
||||
{
|
||||
|
@ -125,7 +126,7 @@ final class JoinTableTagValueNode extends AbstractDoctrineTagValueNode implement
|
|||
|
||||
public function getAttributeClassName(): string
|
||||
{
|
||||
return 'TBA';
|
||||
return PhpAttributeGroupFactory::TO_BE_ANNOUNCED;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -9,6 +9,7 @@ use Rector\BetterPhpDocParser\Contract\Doctrine\MappedByNodeInterface;
|
|||
use Rector\BetterPhpDocParser\Contract\Doctrine\ToManyTagNodeInterface;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Doctrine\AbstractDoctrineTagValueNode;
|
||||
use Rector\PhpAttribute\Contract\PhpAttributableTagNodeInterface;
|
||||
use Rector\PhpAttribute\Printer\PhpAttributeGroupFactory;
|
||||
|
||||
final class ManyToManyTagValueNode extends AbstractDoctrineTagValueNode implements ToManyTagNodeInterface, MappedByNodeInterface, InversedByNodeInterface, PhpAttributableTagNodeInterface
|
||||
{
|
||||
|
@ -74,6 +75,6 @@ final class ManyToManyTagValueNode extends AbstractDoctrineTagValueNode implemen
|
|||
|
||||
public function getAttributeClassName(): string
|
||||
{
|
||||
return 'TBA';
|
||||
return PhpAttributeGroupFactory::TO_BE_ANNOUNCED;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Nette;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwareGenericTagValueNode;
|
||||
use Rector\BetterPhpDocParser\Attributes\Attribute\AttributeTrait;
|
||||
use Rector\BetterPhpDocParser\Contract\PhpDocNode\AttributeAwareNodeInterface;
|
||||
use Rector\PhpAttribute\Contract\PhpAttributableTagNodeInterface;
|
||||
|
||||
final class NetteCrossOriginTagNode extends PhpDocTagNode implements PhpAttributableTagNodeInterface, AttributeAwareNodeInterface
|
||||
{
|
||||
use AttributeTrait;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const NAME = '@crossOrigin';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(self::NAME, new AttributeAwareGenericTagValueNode(''));
|
||||
}
|
||||
|
||||
public function getShortName(): string
|
||||
{
|
||||
return self::NAME;
|
||||
}
|
||||
|
||||
public function getAttributeClassName(): string
|
||||
{
|
||||
return 'Nette\Application\Attributes\CrossOrigin';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function getAttributableItems(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Nette;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwareGenericTagValueNode;
|
||||
use Rector\BetterPhpDocParser\Attributes\Attribute\AttributeTrait;
|
||||
use Rector\BetterPhpDocParser\Contract\PhpDocNode\AttributeAwareNodeInterface;
|
||||
use Rector\PhpAttribute\Contract\PhpAttributableTagNodeInterface;
|
||||
|
||||
/**
|
||||
* @see \Rector\BetterPhpDocParser\PhpDocNodeFactory\StringMatchingPhpDocNodeFactory\NetteInjectPhpDocNodeFactory
|
||||
*/
|
||||
final class NetteInjectTagNode extends PhpDocTagNode implements PhpAttributableTagNodeInterface, AttributeAwareNodeInterface
|
||||
{
|
||||
use AttributeTrait;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const NAME = '@inject';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(self::NAME, new AttributeAwareGenericTagValueNode(''));
|
||||
}
|
||||
|
||||
public function getShortName(): string
|
||||
{
|
||||
return self::NAME;
|
||||
}
|
||||
|
||||
public function getAttributeClassName(): string
|
||||
{
|
||||
return 'Nette\DI\Attributes\Inject';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function getAttributableItems(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Nette;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwareGenericTagValueNode;
|
||||
use Rector\BetterPhpDocParser\Attributes\Attribute\AttributeTrait;
|
||||
use Rector\BetterPhpDocParser\Contract\PhpDocNode\AttributeAwareNodeInterface;
|
||||
use Rector\PhpAttribute\Contract\PhpAttributableTagNodeInterface;
|
||||
|
||||
/**
|
||||
* @see \Rector\BetterPhpDocParser\PhpDocNodeFactory\StringMatchingPhpDocNodeFactory\NettePersistentPhpDocNodeFactory
|
||||
*/
|
||||
final class NettePersistentTagNode extends PhpDocTagNode implements PhpAttributableTagNodeInterface, AttributeAwareNodeInterface
|
||||
{
|
||||
use AttributeTrait;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const NAME = '@persistent';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(self::NAME, new AttributeAwareGenericTagValueNode(''));
|
||||
}
|
||||
|
||||
public function getShortName(): string
|
||||
{
|
||||
return self::NAME;
|
||||
}
|
||||
|
||||
public function getAttributeClassName(): string
|
||||
{
|
||||
return 'Nette\Application\Attributes\Persistent';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function getAttributableItems(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\BetterPhpDocParser\ValueObject\PhpDocNode\PHPUnit;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
|
||||
use Rector\BetterPhpDocParser\Attributes\Attribute\AttributeTrait;
|
||||
use Rector\BetterPhpDocParser\Contract\PhpDocNode\AttributeAwareNodeInterface;
|
||||
|
||||
final class PHPUnitDataProviderTagValueNode implements PhpDocTagValueNode, AttributeAwareNodeInterface
|
||||
{
|
||||
use AttributeTrait;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const NAME = '@dataprovider';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $method;
|
||||
|
||||
public function __construct(string $method)
|
||||
{
|
||||
$this->method = $method;
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->method;
|
||||
}
|
||||
|
||||
public function getMethod(): string
|
||||
{
|
||||
return $this->method;
|
||||
}
|
||||
|
||||
public function getMethodName(): string
|
||||
{
|
||||
return trim($this->method, '()');
|
||||
}
|
||||
|
||||
public function changeMethodName(string $method): void
|
||||
{
|
||||
$this->method = $method . '()';
|
||||
}
|
||||
}
|
|
@ -35,6 +35,6 @@ final class AssertEmailTagValueNode extends AbstractTagValueNode implements Type
|
|||
|
||||
public function getAttributeClassName(): string
|
||||
{
|
||||
return 'TBA';
|
||||
return 'Symfony\Component\Validator\Constraints\Email';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,6 @@ final class AssertRangeTagValueNode extends AbstractTagValueNode implements Type
|
|||
|
||||
public function getAttributeClassName(): string
|
||||
{
|
||||
return 'TBA';
|
||||
return 'Symfony\Component\Validator\Constraints\Range';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,15 +15,15 @@ use PhpParser\Node\Stmt\Property;
|
|||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
|
||||
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTagRemover;
|
||||
use Rector\PhpAttribute\Contract\PhpAttributableTagNodeInterface;
|
||||
use Rector\PhpAttribute\Printer\PhpAttributteGroupFactory;
|
||||
use Rector\PhpAttribute\Printer\PhpAttributeGroupFactory;
|
||||
use Rector\Testing\PHPUnit\StaticPHPUnitEnvironment;
|
||||
|
||||
final class AnnotationToAttributeConverter
|
||||
{
|
||||
/**
|
||||
* @var PhpAttributteGroupFactory
|
||||
* @var PhpAttributeGroupFactory
|
||||
*/
|
||||
private $phpAttributteGroupFactory;
|
||||
private $phpAttributeGroupFactory;
|
||||
|
||||
/**
|
||||
* @var PhpDocInfoFactory
|
||||
|
@ -36,11 +36,11 @@ final class AnnotationToAttributeConverter
|
|||
private $phpDocTagRemover;
|
||||
|
||||
public function __construct(
|
||||
PhpAttributteGroupFactory $phpAttributteGroupFactory,
|
||||
PhpAttributeGroupFactory $phpAttributeGroupFactory,
|
||||
PhpDocInfoFactory $phpDocInfoFactory,
|
||||
PhpDocTagRemover $phpDocTagRemover
|
||||
) {
|
||||
$this->phpAttributteGroupFactory = $phpAttributteGroupFactory;
|
||||
$this->phpAttributeGroupFactory = $phpAttributeGroupFactory;
|
||||
$this->phpDocInfoFactory = $phpDocInfoFactory;
|
||||
$this->phpDocTagRemover = $phpDocTagRemover;
|
||||
}
|
||||
|
@ -52,8 +52,6 @@ final class AnnotationToAttributeConverter
|
|||
{
|
||||
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node);
|
||||
|
||||
$hasNewAttrGroups = false;
|
||||
|
||||
// 0. has 0 nodes, nothing to change
|
||||
/** @var PhpAttributableTagNodeInterface[] $phpAttributableTagNodes */
|
||||
$phpAttributableTagNodes = $phpDocInfo->findAllByType(PhpAttributableTagNodeInterface::class);
|
||||
|
@ -61,6 +59,8 @@ final class AnnotationToAttributeConverter
|
|||
return null;
|
||||
}
|
||||
|
||||
$hasNewAttrGroups = false;
|
||||
|
||||
// 1. keep only those, whom's attribute class exists
|
||||
$phpAttributableTagNodes = $this->filterOnlyExistingAttributes($phpAttributableTagNodes);
|
||||
if ($phpAttributableTagNodes !== []) {
|
||||
|
@ -73,7 +73,7 @@ final class AnnotationToAttributeConverter
|
|||
}
|
||||
|
||||
// 3. convert annotations to attributes
|
||||
$newAttrGroups = $this->phpAttributteGroupFactory->create($phpAttributableTagNodes);
|
||||
$newAttrGroups = $this->phpAttributeGroupFactory->create($phpAttributableTagNodes);
|
||||
$node->attrGroups = array_merge($node->attrGroups, $newAttrGroups);
|
||||
|
||||
if ($hasNewAttrGroups) {
|
||||
|
|
|
@ -4,9 +4,9 @@ declare(strict_types=1);
|
|||
|
||||
namespace Rector\PhpAttribute\Contract;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\Node;
|
||||
|
||||
interface PhpAttributableTagNodeInterface extends PhpDocTagValueNode
|
||||
interface PhpAttributableTagNodeInterface extends Node
|
||||
{
|
||||
public function getShortName(): string;
|
||||
|
||||
|
|
|
@ -14,12 +14,15 @@ use PhpParser\Node\Name\FullyQualified;
|
|||
use Rector\PhpAttribute\Contract\ManyPhpAttributableTagNodeInterface;
|
||||
use Rector\PhpAttribute\Contract\PhpAttributableTagNodeInterface;
|
||||
|
||||
final class PhpAttributteGroupFactory
|
||||
final class PhpAttributeGroupFactory
|
||||
{
|
||||
/**
|
||||
* A dummy placeholder for annotation, that we know will be converted to attributes,
|
||||
* but don't have specific attribute class yet.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public const TBA = 'TBA';
|
||||
public const TO_BE_ANNOUNCED = 'TBA';
|
||||
|
||||
/**
|
||||
* @param PhpAttributableTagNodeInterface[] $phpAttributableTagNodes
|
||||
|
@ -100,7 +103,7 @@ final class PhpAttributteGroupFactory
|
|||
|
||||
private function resolveAttributeClassName(PhpAttributableTagNodeInterface $phpAttributableTagNode): Name
|
||||
{
|
||||
if ($phpAttributableTagNode->getAttributeClassName() !== self::TBA) {
|
||||
if ($phpAttributableTagNode->getAttributeClassName() !== self::TO_BE_ANNOUNCED) {
|
||||
return new FullyQualified($phpAttributableTagNode->getAttributeClassName());
|
||||
}
|
||||
|
|
@ -6,20 +6,8 @@ namespace Rector\PhpAttribute\ValueObject;
|
|||
|
||||
final class TagName
|
||||
{
|
||||
/**
|
||||
* Use by Symfony to autowire dependencies outside constructor,
|
||||
* @see https://symfony.com/doc/current/service_container/autowiring.html#autowiring-other-methods-e-g-setters-and-public-typed-properties
|
||||
* @var string
|
||||
*/
|
||||
public const REQUIRED = 'required';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const API = 'api';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const INJECT = 'inject';
|
||||
}
|
||||
|
|
|
@ -6,9 +6,9 @@ namespace Rector\PostRector\NodeAnalyzer;
|
|||
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Nette\NetteInjectTagNode;
|
||||
use Rector\Core\ValueObject\MethodName;
|
||||
use Rector\NodeNameResolver\NodeNameResolver;
|
||||
use Rector\PhpAttribute\ValueObject\TagName;
|
||||
use ReflectionClass;
|
||||
use ReflectionMethod;
|
||||
|
||||
|
@ -47,7 +47,7 @@ final class NetteInjectDetector
|
|||
}
|
||||
|
||||
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($property);
|
||||
if ($phpDocInfo->hasByName(TagName::INJECT)) {
|
||||
if ($phpDocInfo->hasByType(NetteInjectTagNode::class)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
11
phpstan.neon
11
phpstan.neon
|
@ -523,3 +523,14 @@ parameters:
|
|||
-
|
||||
message: '#There should be no empty class#'
|
||||
path: src/Rector/AbstractRector.php
|
||||
|
||||
- '#Method Rector\\BetterPhpDocParser\\PhpDocNodeFactory\\MultiPhpDocNodeFactory\:\:getTagValueNodeClassesToAnnotationClasses\(\) should return array<class\-string<Rector\\BetterPhpDocParser\\ValueObject\\PhpDocNode\\AbstractTagValueNode\>, class\-string<Doctrine\\ORM\\Mapping\\Annotation\>\> but returns array<string, string\>#'
|
||||
-
|
||||
message: '#Use value object over return of values#'
|
||||
path: packages/better-php-doc-parser/src/PhpDocNodeFactory/MultiPhpDocNodeFactory.php
|
||||
|
||||
-
|
||||
message: '#Do not use setter on a service#'
|
||||
path: packages/better-php-doc-parser/src/PhpDocNodeFactory/NetteInjectDocNodeFactory.php
|
||||
|
||||
- '#Content of method "getFunctionLikePhpDocInfo\(\)" is duplicated with method "getFunctionLikePhpDocInfo\(\)" in "Rector\\NodeTypeResolver\\NodeTypeResolver\\ParamTypeResolver" class\. Use unique content or abstract service instead#'
|
||||
|
|
|
@ -173,8 +173,8 @@ CODE_SAMPLE
|
|||
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($callee);
|
||||
|
||||
foreach ($this->throwablesToAnnotate as $throwableToAnnotate) {
|
||||
$docComment = $this->throwsFactory->crateDocTagNodeFromClass($throwableToAnnotate);
|
||||
$phpDocInfo->addPhpDocTagNode($docComment);
|
||||
$phpDocTagNode = $this->throwsFactory->crateDocTagNodeFromClass($throwableToAnnotate);
|
||||
$phpDocInfo->addPhpDocTagNode($phpDocTagNode);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,10 +11,10 @@ use PhpParser\Node\Stmt\Class_;
|
|||
use PhpParser\Node\Stmt\ClassLike;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PhpParser\Node\Stmt\Return_;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\SymfonyRequiredTagNode;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\DeadCode\Comparator\CurrentAndParentClassMethodComparator;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\PhpAttribute\ValueObject\TagName;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
|
||||
|
@ -148,6 +148,6 @@ CODE_SAMPLE
|
|||
private function hasRequiredAnnotation(ClassMethod $classMethod): bool
|
||||
{
|
||||
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($classMethod);
|
||||
return $phpDocInfo->hasByName(TagName::REQUIRED);
|
||||
return $phpDocInfo->hasByType(SymfonyRequiredTagNode::class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,14 +88,9 @@ CODE_SAMPLE
|
|||
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node);
|
||||
|
||||
foreach ($this->annotationsToRemove as $annotationToRemove) {
|
||||
if ($phpDocInfo->hasByName($annotationToRemove)) {
|
||||
$this->phpDocTagRemover->removeByName($phpDocInfo, $annotationToRemove);
|
||||
continue;
|
||||
}
|
||||
$this->phpDocTagRemover->removeByName($phpDocInfo, $annotationToRemove);
|
||||
|
||||
if (is_a($annotationToRemove, PhpDocTagValueNode::class, true) && $phpDocInfo->hasByType(
|
||||
$annotationToRemove
|
||||
)) {
|
||||
if (is_a($annotationToRemove, PhpDocTagValueNode::class, true)) {
|
||||
$phpDocInfo->removeByType($annotationToRemove);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,10 +6,8 @@ namespace Rector\DeadDocBlock\Rector\ClassMethod;
|
|||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwareReturnTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTagRemover;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\DeadDocBlock\DeadReturnTagValueNodeAnalyzer;
|
||||
use Rector\DeadDocBlock\TagRemover\ReturnTagRemover;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
|
||||
|
@ -19,21 +17,13 @@ use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
|||
final class RemoveUselessReturnTagRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @var DeadReturnTagValueNodeAnalyzer
|
||||
* @var ReturnTagRemover
|
||||
*/
|
||||
private $deadReturnTagValueNodeAnalyzer;
|
||||
private $returnTagRemover;
|
||||
|
||||
/**
|
||||
* @var PhpDocTagRemover
|
||||
*/
|
||||
private $phpDocTagRemover;
|
||||
|
||||
public function __construct(
|
||||
DeadReturnTagValueNodeAnalyzer $deadReturnTagValueNodeAnalyzer,
|
||||
PhpDocTagRemover $phpDocTagRemover
|
||||
) {
|
||||
$this->deadReturnTagValueNodeAnalyzer = $deadReturnTagValueNodeAnalyzer;
|
||||
$this->phpDocTagRemover = $phpDocTagRemover;
|
||||
public function __construct(ReturnTagRemover $returnTagRemover)
|
||||
{
|
||||
$this->returnTagRemover = $returnTagRemover;
|
||||
}
|
||||
|
||||
public function getRuleDefinition(): RuleDefinition
|
||||
|
@ -85,18 +75,12 @@ CODE_SAMPLE
|
|||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node);
|
||||
$this->returnTagRemover->removeReturnTagIfUseless($phpDocInfo, $node);
|
||||
|
||||
$attributeAwareReturnTagValueNode = $phpDocInfo->getReturnTagValue();
|
||||
if (! $attributeAwareReturnTagValueNode instanceof AttributeAwareReturnTagValueNode) {
|
||||
return null;
|
||||
if ($phpDocInfo->hasChanged()) {
|
||||
return $node;
|
||||
}
|
||||
|
||||
if (! $this->deadReturnTagValueNodeAnalyzer->isDead($attributeAwareReturnTagValueNode, $node)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->phpDocTagRemover->removeTagValueFromNode($phpDocInfo, $attributeAwareReturnTagValueNode);
|
||||
|
||||
return $node;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,10 +5,10 @@ declare(strict_types=1);
|
|||
namespace Rector\DeadDocBlock\TagRemover;
|
||||
|
||||
use PhpParser\Node\FunctionLike;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode;
|
||||
use PHPStan\Type\Type;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwareReturnTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTagRemover;
|
||||
use Rector\DeadDocBlock\DeadReturnTagValueNodeAnalyzer;
|
||||
|
||||
final class ReturnTagRemover
|
||||
|
@ -18,17 +18,9 @@ final class ReturnTagRemover
|
|||
*/
|
||||
private $deadReturnTagValueNodeAnalyzer;
|
||||
|
||||
/**
|
||||
* @var PhpDocTagRemover
|
||||
*/
|
||||
private $phpDocTagRemover;
|
||||
|
||||
public function __construct(
|
||||
DeadReturnTagValueNodeAnalyzer $deadReturnTagValueNodeAnalyzer,
|
||||
PhpDocTagRemover $phpDocTagRemover
|
||||
) {
|
||||
public function __construct(DeadReturnTagValueNodeAnalyzer $deadReturnTagValueNodeAnalyzer)
|
||||
{
|
||||
$this->deadReturnTagValueNodeAnalyzer = $deadReturnTagValueNodeAnalyzer;
|
||||
$this->phpDocTagRemover = $phpDocTagRemover;
|
||||
}
|
||||
|
||||
public function removeReturnTagIfUseless(PhpDocInfo $phpDocInfo, FunctionLike $functionLike): void
|
||||
|
@ -47,6 +39,6 @@ final class ReturnTagRemover
|
|||
return;
|
||||
}
|
||||
|
||||
$this->phpDocTagRemover->removeTagValueFromNode($phpDocInfo, $attributeAwareReturnTagValueNode);
|
||||
$phpDocInfo->removeByType(ReturnTagValueNode::class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,13 +7,13 @@ namespace Rector\DependencyInjection\NodeFactory;
|
|||
use PhpParser\Node\Name\FullyQualified;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PHPStan\Type\ObjectType;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\SymfonyRequiredTagNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
|
||||
use Rector\CodingStyle\Naming\ClassNaming;
|
||||
use Rector\Core\PhpParser\Node\NodeFactory;
|
||||
use Rector\Core\ValueObject\FrameworkName;
|
||||
use Rector\Naming\Naming\PropertyNaming;
|
||||
use Rector\NodeTypeResolver\PHPStan\Type\TypeFactory;
|
||||
use Rector\PhpAttribute\ValueObject\TagName;
|
||||
use Symplify\Astral\ValueObject\NodeBuilder\MethodBuilder;
|
||||
use Symplify\Astral\ValueObject\NodeBuilder\ParamBuilder;
|
||||
|
||||
|
@ -87,7 +87,7 @@ final class InjectMethodFactory
|
|||
|
||||
if ($framework === FrameworkName::SYMFONY) {
|
||||
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($classMethod);
|
||||
$phpDocInfo->addBareTag(TagName::REQUIRED);
|
||||
$phpDocInfo->addPhpDocTagNode(new SymfonyRequiredTagNode());
|
||||
}
|
||||
|
||||
return $classMethod;
|
||||
|
|
|
@ -13,7 +13,6 @@ use Rector\BetterPhpDocParser\Contract\Doctrine\DoctrineRelationTagValueNodeInte
|
|||
use Rector\BetterPhpDocParser\Contract\Doctrine\ToManyTagNodeInterface;
|
||||
use Rector\BetterPhpDocParser\Contract\Doctrine\ToOneTagNodeInterface;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTagRemover;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Doctrine\Property_\JoinColumnTagValueNode;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Doctrine\Property_\OneToOneTagValueNode;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
|
@ -41,11 +40,6 @@ final class AddUuidMirrorForRelationPropertyRector extends AbstractRector
|
|||
*/
|
||||
private $uuidMigrationDataCollector;
|
||||
|
||||
/**
|
||||
* @var PhpDocTagRemover
|
||||
*/
|
||||
private $phpDocTagRemover;
|
||||
|
||||
/**
|
||||
* @var DoctrineDocBlockResolver
|
||||
*/
|
||||
|
@ -54,12 +48,10 @@ final class AddUuidMirrorForRelationPropertyRector extends AbstractRector
|
|||
public function __construct(
|
||||
PhpDocTagNodeFactory $phpDocTagNodeFactory,
|
||||
UuidMigrationDataCollector $uuidMigrationDataCollector,
|
||||
PhpDocTagRemover $phpDocTagRemover,
|
||||
DoctrineDocBlockResolver $doctrineDocBlockResolver
|
||||
) {
|
||||
$this->phpDocTagNodeFactory = $phpDocTagNodeFactory;
|
||||
$this->uuidMigrationDataCollector = $uuidMigrationDataCollector;
|
||||
$this->phpDocTagRemover = $phpDocTagRemover;
|
||||
$this->doctrineDocBlockResolver = $doctrineDocBlockResolver;
|
||||
}
|
||||
|
||||
|
@ -279,11 +271,8 @@ CODE_SAMPLE
|
|||
|
||||
private function refactorToManyPropertyPhpDocInfo(PhpDocInfo $phpDocInfo, Property $property): void
|
||||
{
|
||||
$doctrineJoinColumnTagValueNode = $phpDocInfo->getByType(JoinColumnTagValueNode::class);
|
||||
if ($doctrineJoinColumnTagValueNode !== null) {
|
||||
// replace @ORM\JoinColumn with @ORM\JoinTable
|
||||
$this->phpDocTagRemover->removeTagValueFromNode($phpDocInfo, $doctrineJoinColumnTagValueNode);
|
||||
}
|
||||
// replace @ORM\JoinColumn with @ORM\JoinTable
|
||||
$phpDocInfo->removeByType(JoinColumnTagValueNode::class);
|
||||
|
||||
$joinTableTagNode = $this->phpDocTagNodeFactory->createJoinTableTagNode($property);
|
||||
$phpDocInfo->addPhpDocTagNode($joinTableTagNode);
|
||||
|
|
|
@ -8,13 +8,12 @@ use PhpParser\Node;
|
|||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\ClassLike;
|
||||
use PhpParser\Node\Stmt\Property;
|
||||
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTagRemover;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Nette\NetteInjectTagNode;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Core\ValueObject\PhpVersionFeature;
|
||||
use Rector\FamilyTree\NodeAnalyzer\ClassChildAnalyzer;
|
||||
use Rector\FamilyTree\NodeAnalyzer\PropertyUsageAnalyzer;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\PhpAttribute\ValueObject\TagName;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
|
||||
|
@ -39,25 +38,18 @@ final class AnnotatedPropertyInjectToConstructorInjectionRector extends Abstract
|
|||
*/
|
||||
private $classChildAnalyzer;
|
||||
|
||||
/**
|
||||
* @var PhpDocTagRemover
|
||||
*/
|
||||
private $phpDocTagRemover;
|
||||
|
||||
public function __construct(
|
||||
ClassChildAnalyzer $classChildAnalyzer,
|
||||
PropertyUsageAnalyzer $propertyUsageAnalyzer,
|
||||
PhpDocTagRemover $phpDocTagRemover
|
||||
PropertyUsageAnalyzer $propertyUsageAnalyzer
|
||||
) {
|
||||
$this->propertyUsageAnalyzer = $propertyUsageAnalyzer;
|
||||
$this->classChildAnalyzer = $classChildAnalyzer;
|
||||
$this->phpDocTagRemover = $phpDocTagRemover;
|
||||
}
|
||||
|
||||
public function getRuleDefinition(): RuleDefinition
|
||||
{
|
||||
return new RuleDefinition(
|
||||
'Turns non-private properties with `@annotation` to private properties and constructor injection',
|
||||
'Turns non-private properties with `@inject` to private properties and constructor injection',
|
||||
[
|
||||
new CodeSample(
|
||||
<<<'CODE_SAMPLE'
|
||||
|
@ -102,7 +94,7 @@ CODE_SAMPLE
|
|||
}
|
||||
|
||||
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node);
|
||||
$this->phpDocTagRemover->removeByName($phpDocInfo, TagName::INJECT);
|
||||
$phpDocInfo->removeByType(NetteInjectTagNode::class);
|
||||
|
||||
if ($this->propertyUsageAnalyzer->isPropertyFetchedInChildClass($node)) {
|
||||
$this->makeProtected($node);
|
||||
|
@ -123,7 +115,7 @@ CODE_SAMPLE
|
|||
private function shouldSkipProperty(Property $property): bool
|
||||
{
|
||||
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($property);
|
||||
if (! $phpDocInfo->hasByName(TagName::INJECT)) {
|
||||
if (! $phpDocInfo->hasByType(NetteInjectTagNode::class)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,12 +8,11 @@ use PhpParser\Node;
|
|||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PhpParser\Node\Stmt\Property;
|
||||
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTagRemover;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Nette\NetteInjectTagNode;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Core\ValueObject\MethodName;
|
||||
use Rector\Core\ValueObject\PhpVersionFeature;
|
||||
use Rector\FamilyTree\NodeAnalyzer\PropertyUsageAnalyzer;
|
||||
use Rector\PhpAttribute\ValueObject\TagName;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
|
||||
|
@ -29,15 +28,9 @@ final class MoveInjectToExistingConstructorRector extends AbstractRector
|
|||
*/
|
||||
private $propertyUsageAnalyzer;
|
||||
|
||||
/**
|
||||
* @var PhpDocTagRemover
|
||||
*/
|
||||
private $phpDocTagRemover;
|
||||
|
||||
public function __construct(PropertyUsageAnalyzer $propertyUsageAnalyzer, PhpDocTagRemover $phpDocTagRemover)
|
||||
public function __construct(PropertyUsageAnalyzer $propertyUsageAnalyzer)
|
||||
{
|
||||
$this->propertyUsageAnalyzer = $propertyUsageAnalyzer;
|
||||
$this->phpDocTagRemover = $phpDocTagRemover;
|
||||
}
|
||||
|
||||
public function getRuleDefinition(): RuleDefinition
|
||||
|
@ -141,7 +134,7 @@ CODE_SAMPLE
|
|||
private function removeInjectAnnotation(Property $property): void
|
||||
{
|
||||
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($property);
|
||||
$this->phpDocTagRemover->removeByName($phpDocInfo, TagName::INJECT);
|
||||
$phpDocInfo->removeByType(NetteInjectTagNode::class);
|
||||
}
|
||||
|
||||
private function changePropertyVisibility(Property $injectProperty): void
|
||||
|
@ -160,6 +153,6 @@ CODE_SAMPLE
|
|||
}
|
||||
|
||||
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($property);
|
||||
return $phpDocInfo->hasByName(TagName::INJECT);
|
||||
return $phpDocInfo->hasByType(NetteInjectTagNode::class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ use Symfony\Component\Validator\Constraints as Assert;
|
|||
|
||||
class AssertRange
|
||||
{
|
||||
#[@Assert\Range(min: 120, max: 180, minMessage: 'You must be at least {{ limit }}cm tall to enter', maxMessage: 'You cannot be taller than {{ limit }}cm to enter')]
|
||||
#[\Symfony\Component\Validator\Constraints\Range(min: 120, max: 180, minMessage: 'You must be at least {{ limit }}cm tall to enter', maxMessage: 'You cannot be taller than {{ limit }}cm to enter')]
|
||||
protected $height;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ use Symfony\Component\Validator\Constraints as Assert;
|
|||
class EntityColumnAndAssertEmail
|
||||
{
|
||||
#[@ORM\Column(type: 'string', unique: true)]
|
||||
#[@Assert\Email(message: 'This value is not a valid email address.')]
|
||||
#[\Symfony\Component\Validator\Constraints\Email(message: 'This value is not a valid email address.')]
|
||||
public $name;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Php80\Tests\Rector\Class_\AnnotationToAttributeRector\Fixture;
|
||||
|
||||
final class NetteCrossOrigin
|
||||
{
|
||||
/**
|
||||
* @crossOrigin
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Php80\Tests\Rector\Class_\AnnotationToAttributeRector\Fixture;
|
||||
|
||||
final class NetteCrossOrigin
|
||||
{
|
||||
#[\Nette\Application\Attributes\CrossOrigin]
|
||||
public function run()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Php80\Tests\Rector\Class_\AnnotationToAttributeRector\Fixture;
|
||||
|
||||
final class NetteInject
|
||||
{
|
||||
/**
|
||||
* @inject
|
||||
* @var SomeType
|
||||
*/
|
||||
public $someDependency;
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Php80\Tests\Rector\Class_\AnnotationToAttributeRector\Fixture;
|
||||
|
||||
final class NetteInject
|
||||
{
|
||||
/**
|
||||
* @var SomeType
|
||||
*/
|
||||
#[\Nette\DI\Attributes\Inject]
|
||||
public $someDependency;
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Php80\Tests\Rector\Class_\AnnotationToAttributeRector\Fixture;
|
||||
|
||||
final class NettePersistent
|
||||
{
|
||||
/**
|
||||
* @persistent
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Php80\Tests\Rector\Class_\AnnotationToAttributeRector\Fixture;
|
||||
|
||||
final class NettePersistent
|
||||
{
|
||||
#[\Nette\Application\Attributes\Persistent]
|
||||
public function run()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -106,6 +106,7 @@ CODE_SAMPLE
|
|||
}
|
||||
|
||||
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node);
|
||||
|
||||
foreach (self::ANNOTATION_TO_METHOD as $annotationName => $methodName) {
|
||||
if (! $phpDocInfo->hasByName($annotationName)) {
|
||||
continue;
|
||||
|
|
|
@ -8,7 +8,7 @@ use Nette\Utils\Strings;
|
|||
use PhpParser\Node;
|
||||
use PhpParser\Node\Identifier;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\DataProviderTagValueNode;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\PHPUnit\PHPUnitDataProviderTagValueNode;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\PHPUnit\NodeAnalyzer\TestsNodeAnalyzer;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
|
@ -112,27 +112,23 @@ CODE_SAMPLE
|
|||
foreach ($class->getMethods() as $classMethod) {
|
||||
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($classMethod);
|
||||
|
||||
/** @var DataProviderTagValueNode[] $dataProviderTagValueNodes */
|
||||
$dataProviderTagValueNodes = $phpDocInfo->findAllByType(DataProviderTagValueNode::class);
|
||||
if ($dataProviderTagValueNodes === []) {
|
||||
/** @var PHPUnitDataProviderTagValueNode[] $phpunitDataProviderTagValueNodes */
|
||||
$phpunitDataProviderTagValueNodes = $phpDocInfo->findAllByType(PHPUnitDataProviderTagValueNode::class);
|
||||
if ($phpunitDataProviderTagValueNodes === []) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($dataProviderTagValueNodes as $dataProviderTagValueNode) {
|
||||
$oldMethodName = $dataProviderTagValueNode->getMethod();
|
||||
foreach ($phpunitDataProviderTagValueNodes as $dataProviderTagValueNode) {
|
||||
$oldMethodName = $dataProviderTagValueNode->getMethodName();
|
||||
if (! Strings::startsWith($oldMethodName, 'test')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$newMethodName = $this->createNewMethodName($oldMethodName);
|
||||
$dataProviderTagValueNode->changeMethod($newMethodName);
|
||||
|
||||
$oldMethodName = trim($oldMethodName, '()');
|
||||
$newMethodName = trim($newMethodName, '()');
|
||||
$dataProviderTagValueNode->changeMethodName($newMethodName);
|
||||
$phpDocInfo->markAsChanged();
|
||||
|
||||
$this->providerMethodNamesToNewNames[$oldMethodName] = $newMethodName;
|
||||
|
||||
$phpDocInfo->markAsChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@ use Nette\Utils\Strings;
|
|||
use PhpParser\Node;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\SymfonyRequiredTagNode;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Nette\NetteInjectTagNode;
|
||||
use Rector\Caching\Contract\Rector\ZeroCacheRectorInterface;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Doctrine\PhpDocParser\DoctrineDocBlockResolver;
|
||||
|
@ -160,7 +162,11 @@ CODE_SAMPLE
|
|||
}
|
||||
|
||||
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($classMethod);
|
||||
return $phpDocInfo->hasByNames([TagName::API, TagName::REQUIRED]);
|
||||
if ($phpDocInfo->hasByType(SymfonyRequiredTagNode::class)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $phpDocInfo->hasByName(TagName::API);
|
||||
}
|
||||
|
||||
private function shouldSkipClassLike(Class_ $class): bool
|
||||
|
@ -198,7 +204,7 @@ CODE_SAMPLE
|
|||
}
|
||||
|
||||
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($classMethod);
|
||||
return $phpDocInfo->hasByName(TagName::INJECT);
|
||||
return $phpDocInfo->hasByType(NetteInjectTagNode::class);
|
||||
}
|
||||
|
||||
private function shouldSkipClassMethod(ClassMethod $classMethod): bool
|
||||
|
|
|
@ -8,6 +8,8 @@ use PhpParser\Node;
|
|||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\ClassLike;
|
||||
use PhpParser\Node\Stmt\Property;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\SymfonyRequiredTagNode;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Nette\NetteInjectTagNode;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\PhpAttribute\ValueObject\TagName;
|
||||
|
@ -26,9 +28,9 @@ final class PrivatizeLocalPropertyToPrivatePropertyRector extends AbstractRector
|
|||
private const ANNOTATIONS_REQUIRING_PUBLIC = [
|
||||
TagName::API,
|
||||
// Symfony DI
|
||||
TagName::REQUIRED,
|
||||
SymfonyRequiredTagNode::NAME,
|
||||
// other DI
|
||||
TagName::INJECT,
|
||||
NetteInjectTagNode::NAME,
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
@ -9,7 +9,6 @@ use PhpParser\Node\Name;
|
|||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PhpParser\Node\Stmt\Use_;
|
||||
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTagRemover;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Sensio\SensioRouteTagValueNode;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Symfony\SymfonyRouteTagValueNode;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
|
@ -24,16 +23,6 @@ use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
|||
*/
|
||||
final class ReplaceSensioRouteAnnotationWithSymfonyRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @var PhpDocTagRemover
|
||||
*/
|
||||
private $phpDocTagRemover;
|
||||
|
||||
public function __construct(PhpDocTagRemover $phpDocTagRemover)
|
||||
{
|
||||
$this->phpDocTagRemover = $phpDocTagRemover;
|
||||
}
|
||||
|
||||
public function getRuleDefinition(): RuleDefinition
|
||||
{
|
||||
return new RuleDefinition(
|
||||
|
@ -99,10 +88,7 @@ CODE_SAMPLE
|
|||
return null;
|
||||
}
|
||||
|
||||
/** @var SensioRouteTagValueNode $sensioRouteTagValueNode */
|
||||
$sensioRouteTagValueNode = $phpDocInfo->getByType(SensioRouteTagValueNode::class);
|
||||
|
||||
$this->phpDocTagRemover->removeTagValueFromNode($phpDocInfo, $sensioRouteTagValueNode);
|
||||
$phpDocInfo->removeByType(SensioRouteTagValueNode::class);
|
||||
|
||||
// unset service, that is deprecated
|
||||
$items = $sensioRouteTagValueNode->getItems();
|
||||
|
|
|
@ -7,9 +7,9 @@ namespace Rector\Symfony\Rector\ClassMethod;
|
|||
use PhpParser\Node;
|
||||
use PhpParser\Node\Identifier;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\SymfonyRequiredTagNode;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\PhpAttribute\ValueObject\TagName;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
|
||||
|
@ -61,7 +61,8 @@ CODE_SAMPLE
|
|||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
if (! $this->hasTagByName($node, TagName::REQUIRED)) {
|
||||
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node);
|
||||
if (! $phpDocInfo->hasByType(SymfonyRequiredTagNode::class)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ namespace Rector\Symfony3\Rector\ClassMethod;
|
|||
use PhpParser\Node;
|
||||
use PhpParser\Node\Stmt\ClassLike;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTagRemover;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Sensio\SensioMethodTagValueNode;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Symfony\SymfonyRouteTagValueNode;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
|
@ -23,16 +22,6 @@ use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
|||
*/
|
||||
final class MergeMethodAnnotationToRouteAnnotationRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @var PhpDocTagRemover
|
||||
*/
|
||||
private $phpDocTagRemover;
|
||||
|
||||
public function __construct(PhpDocTagRemover $phpDocTagRemover)
|
||||
{
|
||||
$this->phpDocTagRemover = $phpDocTagRemover;
|
||||
}
|
||||
|
||||
public function getRuleDefinition(): RuleDefinition
|
||||
{
|
||||
return new RuleDefinition(
|
||||
|
@ -110,8 +99,7 @@ CODE_SAMPLE
|
|||
}
|
||||
|
||||
$symfonyRouteTagValueNode->changeMethods($methods);
|
||||
|
||||
$this->phpDocTagRemover->removeTagValueFromNode($phpDocInfo, $sensioMethodTagValueNode);
|
||||
$phpDocInfo->removeByType(SensioMethodTagValueNode::class);
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
|
|
@ -13,9 +13,9 @@ use PhpParser\Node\Stmt\Return_;
|
|||
use PHPStan\Type\Constant\ConstantArrayType;
|
||||
use PHPStan\Type\MixedType;
|
||||
use PHPStan\Type\Type;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\DataProviderTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\PHPUnit\PHPUnitDataProviderTagValueNode;
|
||||
use Rector\Core\Exception\ShouldNotHappenException;
|
||||
use Rector\Core\PhpParser\Node\BetterNodeFinder;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
|
@ -86,8 +86,8 @@ final class PHPUnitDataProviderParamTypeInferer implements ParamTypeInfererInter
|
|||
{
|
||||
$phpDocInfo = $this->getFunctionLikePhpDocInfo($param);
|
||||
|
||||
$attributeAwareDataProviderTagValueNode = $phpDocInfo->getByType(DataProviderTagValueNode::class);
|
||||
if (! $attributeAwareDataProviderTagValueNode instanceof DataProviderTagValueNode) {
|
||||
$phpUnitDataProviderTagValueNode = $phpDocInfo->getByType(PHPUnitDataProviderTagValueNode::class);
|
||||
if (! $phpUnitDataProviderTagValueNode instanceof PHPUnitDataProviderTagValueNode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -96,7 +96,7 @@ final class PHPUnitDataProviderParamTypeInferer implements ParamTypeInfererInter
|
|||
return null;
|
||||
}
|
||||
|
||||
return $classLike->getMethod($attributeAwareDataProviderTagValueNode->getMethodName());
|
||||
return $classLike->getMethod($phpUnitDataProviderTagValueNode->getMethodName());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -45,6 +45,7 @@ use PHPStan\Type\MixedType;
|
|||
use PHPStan\Type\Type;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
|
||||
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Nette\NetteInjectTagNode;
|
||||
use Rector\Core\Configuration\CurrentNodeProvider;
|
||||
use Rector\Core\Exception\NotImplementedException;
|
||||
use Rector\Core\Php\PhpVersionProvider;
|
||||
|
@ -52,7 +53,6 @@ use Rector\Core\ValueObject\MethodName;
|
|||
use Rector\Core\ValueObject\PhpVersionFeature;
|
||||
use Rector\NodeNameResolver\NodeNameResolver;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\PhpAttribute\ValueObject\TagName;
|
||||
use Rector\PostRector\ValueObject\PropertyMetadata;
|
||||
use Rector\StaticTypeMapper\StaticTypeMapper;
|
||||
use Symplify\Astral\ValueObject\NodeBuilder\MethodBuilder;
|
||||
|
@ -265,7 +265,7 @@ final class NodeFactory
|
|||
|
||||
// add @inject
|
||||
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($property);
|
||||
$phpDocInfo->addBareTag(TagName::INJECT);
|
||||
$phpDocInfo->addPhpDocTagNode(new NetteInjectTagNode());
|
||||
|
||||
return $property;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user