2019-10-13 05:59:52 +00:00
|
|
|
<?php
|
|
|
|
|
2021-05-09 20:15:43 +00:00
|
|
|
declare (strict_types=1);
|
2022-06-06 17:12:56 +00:00
|
|
|
namespace Rector\Renaming\Rector\ClassMethod;
|
2018-02-09 00:14:45 +00:00
|
|
|
|
2022-06-06 17:12:56 +00:00
|
|
|
use PhpParser\Node;
|
|
|
|
use PhpParser\Node\Stmt\Class_;
|
|
|
|
use PhpParser\Node\Stmt\ClassMethod;
|
|
|
|
use PhpParser\Node\Stmt\Expression;
|
|
|
|
use PhpParser\Node\Stmt\Property;
|
2023-09-11 21:30:42 +00:00
|
|
|
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
2023-09-20 12:41:26 +00:00
|
|
|
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
|
2023-09-11 21:30:42 +00:00
|
|
|
use Rector\Comments\NodeDocBlock\DocBlockUpdater;
|
2024-01-02 02:40:38 +00:00
|
|
|
use Rector\Contract\Rector\ConfigurableRectorInterface;
|
2022-06-06 17:12:56 +00:00
|
|
|
use Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockTagReplacer;
|
2024-01-02 02:40:38 +00:00
|
|
|
use Rector\Rector\AbstractRector;
|
2022-06-06 17:12:56 +00:00
|
|
|
use Rector\Renaming\Contract\RenameAnnotationInterface;
|
|
|
|
use Rector\Renaming\ValueObject\RenameAnnotationByType;
|
2022-06-07 09:18:30 +00:00
|
|
|
use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample;
|
|
|
|
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
2024-03-01 20:02:28 +00:00
|
|
|
use RectorPrefix202403\Webmozart\Assert\Assert;
|
2019-09-03 09:11:45 +00:00
|
|
|
/**
|
2021-03-12 22:20:25 +00:00
|
|
|
* @see \Rector\Tests\Renaming\Rector\ClassMethod\RenameAnnotationRector\RenameAnnotationRectorTest
|
2019-09-03 09:11:45 +00:00
|
|
|
*/
|
2022-06-07 08:22:29 +00:00
|
|
|
final class RenameAnnotationRector extends AbstractRector implements ConfigurableRectorInterface
|
2018-02-09 00:14:45 +00:00
|
|
|
{
|
2021-01-19 15:03:26 +00:00
|
|
|
/**
|
2023-06-11 23:01:39 +00:00
|
|
|
* @readonly
|
2021-05-10 23:39:21 +00:00
|
|
|
* @var \Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockTagReplacer
|
2021-01-19 15:03:26 +00:00
|
|
|
*/
|
|
|
|
private $docBlockTagReplacer;
|
2023-09-11 21:30:42 +00:00
|
|
|
/**
|
|
|
|
* @readonly
|
|
|
|
* @var \Rector\Comments\NodeDocBlock\DocBlockUpdater
|
|
|
|
*/
|
|
|
|
private $docBlockUpdater;
|
2023-09-20 12:41:26 +00:00
|
|
|
/**
|
|
|
|
* @readonly
|
|
|
|
* @var \Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory
|
|
|
|
*/
|
|
|
|
private $phpDocInfoFactory;
|
2023-06-08 22:00:17 +00:00
|
|
|
/**
|
|
|
|
* @var RenameAnnotationInterface[]
|
|
|
|
*/
|
|
|
|
private $renameAnnotations = [];
|
2023-09-20 12:41:26 +00:00
|
|
|
public function __construct(DocBlockTagReplacer $docBlockTagReplacer, DocBlockUpdater $docBlockUpdater, PhpDocInfoFactory $phpDocInfoFactory)
|
2021-01-19 15:03:26 +00:00
|
|
|
{
|
|
|
|
$this->docBlockTagReplacer = $docBlockTagReplacer;
|
2023-09-11 21:30:42 +00:00
|
|
|
$this->docBlockUpdater = $docBlockUpdater;
|
2023-09-20 12:41:26 +00:00
|
|
|
$this->phpDocInfoFactory = $phpDocInfoFactory;
|
2021-01-19 15:03:26 +00:00
|
|
|
}
|
2022-06-07 08:22:29 +00:00
|
|
|
public function getRuleDefinition() : RuleDefinition
|
2018-04-08 11:51:26 +00:00
|
|
|
{
|
2022-06-07 08:22:29 +00:00
|
|
|
return new RuleDefinition('Turns defined annotations above properties and methods to their new values.', [new ConfiguredCodeSample(<<<'CODE_SAMPLE'
|
2021-11-29 10:27:24 +00:00
|
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
|
|
|
|
final class SomeTest extends TestCase
|
2018-08-01 19:52:44 +00:00
|
|
|
{
|
2018-08-04 07:33:54 +00:00
|
|
|
/**
|
|
|
|
* @test
|
|
|
|
*/
|
2018-08-01 19:52:44 +00:00
|
|
|
public function someMethod()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
}
|
2020-09-15 08:23:13 +00:00
|
|
|
CODE_SAMPLE
|
2021-05-09 20:15:43 +00:00
|
|
|
, <<<'CODE_SAMPLE'
|
2021-11-29 10:27:24 +00:00
|
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
|
|
|
|
final class SomeTest extends TestCase
|
2018-08-01 19:52:44 +00:00
|
|
|
{
|
2020-02-04 07:54:00 +00:00
|
|
|
/**
|
2018-08-04 07:33:54 +00:00
|
|
|
* @scenario
|
|
|
|
*/
|
2018-08-01 19:52:44 +00:00
|
|
|
public function someMethod()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
}
|
2020-09-15 08:23:13 +00:00
|
|
|
CODE_SAMPLE
|
2022-06-07 09:46:15 +00:00
|
|
|
, [new RenameAnnotationByType('PHPUnit\\Framework\\TestCase', 'test', 'scenario')])]);
|
2018-04-08 11:51:26 +00:00
|
|
|
}
|
2018-08-14 22:12:41 +00:00
|
|
|
/**
|
2021-02-27 00:06:15 +00:00
|
|
|
* @return array<class-string<Node>>
|
2018-08-14 22:12:41 +00:00
|
|
|
*/
|
2021-05-09 20:15:43 +00:00
|
|
|
public function getNodeTypes() : array
|
2018-08-14 21:33:39 +00:00
|
|
|
{
|
2023-06-10 06:35:34 +00:00
|
|
|
return [Class_::class, Expression::class];
|
2018-08-14 21:33:39 +00:00
|
|
|
}
|
|
|
|
/**
|
2023-06-10 06:35:34 +00:00
|
|
|
* @param Class_|Expression $node
|
2018-08-14 21:33:39 +00:00
|
|
|
*/
|
2022-06-07 08:22:29 +00:00
|
|
|
public function refactor(Node $node) : ?Node
|
2018-02-09 00:14:45 +00:00
|
|
|
{
|
2023-06-10 06:35:34 +00:00
|
|
|
if ($node instanceof Expression) {
|
2023-09-11 21:30:42 +00:00
|
|
|
return $this->refactorExpression($node);
|
2021-01-19 15:03:26 +00:00
|
|
|
}
|
2023-09-11 21:30:42 +00:00
|
|
|
$hasChanged = \false;
|
2023-06-10 06:35:34 +00:00
|
|
|
foreach ($node->stmts as $stmt) {
|
|
|
|
if (!$stmt instanceof ClassMethod && !$stmt instanceof Property) {
|
2020-08-26 10:54:53 +00:00
|
|
|
continue;
|
2018-02-09 09:27:48 +00:00
|
|
|
}
|
2023-09-11 21:30:42 +00:00
|
|
|
$phpDocInfo = $this->phpDocInfoFactory->createFromNode($stmt);
|
|
|
|
if (!$phpDocInfo instanceof PhpDocInfo) {
|
|
|
|
continue;
|
|
|
|
}
|
2023-06-10 06:35:34 +00:00
|
|
|
foreach ($this->renameAnnotations as $renameAnnotation) {
|
|
|
|
if ($renameAnnotation instanceof RenameAnnotationByType && !$this->isObjectType($node, $renameAnnotation->getObjectType())) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
$hasDocBlockChanged = $this->docBlockTagReplacer->replaceTagByAnother($phpDocInfo, $renameAnnotation->getOldAnnotation(), $renameAnnotation->getNewAnnotation());
|
|
|
|
if ($hasDocBlockChanged) {
|
2023-09-11 21:30:42 +00:00
|
|
|
$this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($stmt);
|
2023-06-10 06:35:34 +00:00
|
|
|
$hasChanged = \true;
|
|
|
|
}
|
2022-06-04 07:44:43 +00:00
|
|
|
}
|
2022-02-28 06:43:27 +00:00
|
|
|
}
|
|
|
|
if (!$hasChanged) {
|
|
|
|
return null;
|
2018-02-09 00:14:45 +00:00
|
|
|
}
|
2018-02-09 09:27:48 +00:00
|
|
|
return $node;
|
|
|
|
}
|
2021-05-02 10:46:55 +00:00
|
|
|
/**
|
2021-11-28 17:01:20 +00:00
|
|
|
* @param mixed[] $configuration
|
2021-05-02 10:46:55 +00:00
|
|
|
*/
|
2021-12-10 10:22:23 +00:00
|
|
|
public function configure(array $configuration) : void
|
2020-07-29 13:55:33 +00:00
|
|
|
{
|
2022-06-07 08:22:29 +00:00
|
|
|
Assert::allIsAOf($configuration, RenameAnnotationInterface::class);
|
2022-02-18 01:46:17 +00:00
|
|
|
$this->renameAnnotations = $configuration;
|
2020-07-29 13:55:33 +00:00
|
|
|
}
|
2023-09-11 21:30:42 +00:00
|
|
|
private function refactorExpression(Expression $expression) : ?Expression
|
|
|
|
{
|
|
|
|
$hasChanged = \false;
|
|
|
|
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($expression);
|
|
|
|
foreach ($this->renameAnnotations as $renameAnnotation) {
|
|
|
|
$hasDocBlockChanged = $this->docBlockTagReplacer->replaceTagByAnother($phpDocInfo, $renameAnnotation->getOldAnnotation(), $renameAnnotation->getNewAnnotation());
|
|
|
|
if ($hasDocBlockChanged) {
|
|
|
|
$hasChanged = \true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ($hasChanged) {
|
|
|
|
$this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($expression);
|
|
|
|
return $expression;
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
2018-02-09 00:14:45 +00:00
|
|
|
}
|