mirror of
https://github.com/rectorphp/rector.git
synced 2024-07-22 17:30:23 +00:00
commit
a9cda5f938
@ -15,6 +15,7 @@ use Rector\BetterPhpDocParser\Attributes\Ast\PhpDoc\AttributeAwarePhpDocNode;
|
||||
use Rector\BetterPhpDocParser\Attributes\Ast\PhpDoc\AttributeAwareReturnTagValueNode;
|
||||
use Rector\BetterPhpDocParser\Attributes\Ast\PhpDoc\AttributeAwareVarTagValueNode;
|
||||
use Rector\BetterPhpDocParser\Attributes\Contract\Ast\AttributeAwareNodeInterface;
|
||||
use Rector\Exception\ShouldNotHappenException;
|
||||
use Rector\NodeTypeResolver\StaticTypeMapper;
|
||||
|
||||
/**
|
||||
@ -189,6 +190,8 @@ final class PhpDocInfo
|
||||
|
||||
public function getByType(string $type): ?PhpDocTagValueNode
|
||||
{
|
||||
$this->ensureTypeIsTagValueNode($type, __METHOD__);
|
||||
|
||||
foreach ($this->phpDocNode->children as $phpDocChildNode) {
|
||||
if ($phpDocChildNode instanceof PhpDocTagNode) {
|
||||
if (is_a($phpDocChildNode->value, $type, true)) {
|
||||
@ -213,4 +216,18 @@ final class PhpDocInfo
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function ensureTypeIsTagValueNode(string $type, string $location): void
|
||||
{
|
||||
if (is_a($type, PhpDocTagValueNode::class, true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new ShouldNotHappenException(sprintf(
|
||||
'Type "%s" passed to "%s()" method must be child of "%s"',
|
||||
$type,
|
||||
$location,
|
||||
PhpDocTagValueNode::class
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -3,10 +3,10 @@
|
||||
namespace Rector\DeadCode\Doctrine;
|
||||
|
||||
use Doctrine\ORM\Mapping\Entity;
|
||||
use Doctrine\ORM\Mapping\InheritanceType;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\Property;
|
||||
use Rector\DoctrinePhpDocParser\Ast\PhpDoc\Class_\EntityTagValueNode;
|
||||
use Rector\DoctrinePhpDocParser\Ast\PhpDoc\Class_\InheritanceTypeTagValueNode;
|
||||
use Rector\DoctrinePhpDocParser\Contract\Ast\PhpDoc\DoctrineRelationTagValueNodeInterface;
|
||||
use Rector\DoctrinePhpDocParser\Contract\Ast\PhpDoc\InversedByNodeInterface;
|
||||
use Rector\DoctrinePhpDocParser\Contract\Ast\PhpDoc\MappedByNodeInterface;
|
||||
@ -71,7 +71,7 @@ final class DoctrineEntityManipulator
|
||||
}
|
||||
|
||||
// is parent entity
|
||||
if ($this->docBlockManipulator->hasTag($class, InheritanceType::class)) {
|
||||
if ($this->docBlockManipulator->hasTag($class, InheritanceTypeTagValueNode::class)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,9 @@
|
||||
|
||||
namespace Rector\DoctrinePhpDocParser\Contract\Ast\PhpDoc;
|
||||
|
||||
interface DoctrineRelationTagValueNodeInterface
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
|
||||
|
||||
interface DoctrineRelationTagValueNodeInterface extends PhpDocTagValueNode
|
||||
{
|
||||
public function getTargetEntity(): ?string;
|
||||
|
||||
|
@ -109,6 +109,11 @@ final class DocBlockManipulator
|
||||
return true;
|
||||
}
|
||||
|
||||
// allow only class nodes further
|
||||
if (! class_exists($name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// advanced check, e.g. for "Namespaced\Annotations\DI"
|
||||
$phpDocInfo = $this->createPhpDocInfoFromNode($node);
|
||||
|
||||
|
@ -57,7 +57,9 @@ final class PropertyTypeDeclarationRector extends AbstractRector
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($this->docBlockManipulator->hasTag($node, '@var')) {
|
||||
// is already set
|
||||
$currentVarType = $this->docBlockManipulator->getVarType($node);
|
||||
if (! $currentVarType instanceof MixedType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@ use PHPStan\Type\UnionType;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockManipulator;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\RectorDefinition\ConfiguredCodeSample;
|
||||
use Rector\RectorDefinition\CodeSample;
|
||||
use Rector\RectorDefinition\RectorDefinition;
|
||||
|
||||
/**
|
||||
@ -26,17 +26,16 @@ final class AnnotatedPropertyInjectToConstructorInjectionRector extends Abstract
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $annotation;
|
||||
private const INJECT_ANNOTATION = 'inject';
|
||||
|
||||
/**
|
||||
* @var DocBlockManipulator
|
||||
*/
|
||||
private $docBlockManipulator;
|
||||
|
||||
public function __construct(DocBlockManipulator $docBlockManipulator, string $annotation = 'inject')
|
||||
public function __construct(DocBlockManipulator $docBlockManipulator)
|
||||
{
|
||||
$this->docBlockManipulator = $docBlockManipulator;
|
||||
$this->annotation = $annotation;
|
||||
}
|
||||
|
||||
public function getDefinition(): RectorDefinition
|
||||
@ -44,7 +43,7 @@ final class AnnotatedPropertyInjectToConstructorInjectionRector extends Abstract
|
||||
return new RectorDefinition(
|
||||
'Turns non-private properties with `@annotation` to private properties and constructor injection',
|
||||
[
|
||||
new ConfiguredCodeSample(
|
||||
new CodeSample(
|
||||
<<<'CODE_SAMPLE'
|
||||
/**
|
||||
* @var SomeService
|
||||
@ -64,10 +63,6 @@ public function __construct(SomeService $someService)
|
||||
$this->someService = $someService;
|
||||
}
|
||||
CODE_SAMPLE
|
||||
,
|
||||
[
|
||||
'$annotation' => 'inject',
|
||||
]
|
||||
),
|
||||
]
|
||||
);
|
||||
@ -86,16 +81,11 @@ CODE_SAMPLE
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
if (! $this->docBlockManipulator->hasTag($node, $this->annotation)) {
|
||||
if ($this->shouldSkipProperty($node)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// it needs @var tag as well, to get the type
|
||||
if (! $this->docBlockManipulator->hasTag($node, 'var')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->docBlockManipulator->removeTagFromNode($node, $this->annotation);
|
||||
$this->docBlockManipulator->removeTagFromNode($node, self::INJECT_ANNOTATION);
|
||||
|
||||
// set to private
|
||||
$this->makePrivate($node);
|
||||
@ -124,4 +114,18 @@ CODE_SAMPLE
|
||||
|
||||
$this->addPropertyToClass($classNode, $propertyType, $propertyName);
|
||||
}
|
||||
|
||||
private function shouldSkipProperty(Node $node): bool
|
||||
{
|
||||
if (! $this->docBlockManipulator->hasTag($node, self::INJECT_ANNOTATION)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// it needs @var tag as well, to get the type
|
||||
if (! $this->docBlockManipulator->hasTag($node, 'var')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -142,6 +142,7 @@ CODE_SAMPLE
|
||||
$tagClass = $this->annotationToTagClass[$annotationClass];
|
||||
|
||||
$injectTagValueNode = $phpDocInfo->getByType($tagClass);
|
||||
|
||||
if ($injectTagValueNode === null) {
|
||||
continue;
|
||||
}
|
||||
@ -165,10 +166,7 @@ CODE_SAMPLE
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! $this->docBlockManipulator->hasTag($property, 'var')) {
|
||||
$this->docBlockManipulator->changeVarTag($property, $type);
|
||||
}
|
||||
|
||||
$this->docBlockManipulator->changeVarTag($property, $type);
|
||||
$this->docBlockManipulator->removeTagFromNode($property, $tagClass);
|
||||
|
||||
$classNode = $property->getAttribute(AttributeKey::CLASS_NODE);
|
||||
|
@ -24,15 +24,8 @@ final class AnnotatedPropertyInjectToConstructorInjectionRectorTest extends Abst
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
protected function getRectorsWithConfiguration(): array
|
||||
protected function getRectorClass(): string
|
||||
{
|
||||
return [
|
||||
AnnotatedPropertyInjectToConstructorInjectionRector::class => [
|
||||
'$annotation' => 'inject',
|
||||
],
|
||||
];
|
||||
return AnnotatedPropertyInjectToConstructorInjectionRector::class;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user