[DX] Remove SingleToManyMethodRector, rather one time job useful for PHPStorm (#1831)

This commit is contained in:
Tomas Votruba 2022-02-18 00:49:31 +00:00 committed by GitHub
parent f022c20446
commit cab8299093
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 2 additions and 435 deletions

View File

@ -1,4 +1,4 @@
# 519 Rules Overview
# 518 Rules Overview
<br>
@ -94,7 +94,7 @@
- [Strict](#strict) (5)
- [Transform](#transform) (37)
- [Transform](#transform) (36)
- [TypeDeclaration](#typedeclaration) (22)
@ -11373,46 +11373,6 @@ return static function (ContainerConfigurator $containerConfigurator): void {
<br>
### SingleToManyMethodRector
Change method that returns single value to multiple values
:wrench: **configure it!**
- class: [`Rector\Transform\Rector\ClassMethod\SingleToManyMethodRector`](../rules/Transform/Rector/ClassMethod/SingleToManyMethodRector.php)
```php
use Rector\Transform\Rector\ClassMethod\SingleToManyMethodRector;
use Rector\Transform\ValueObject\SingleToManyMethod;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
$services->set(SingleToManyMethodRector::class)
->configure([new SingleToManyMethod('SomeClass', 'getNode', 'getNodes')]);
};
```
```diff
class SomeClass
{
- public function getNode(): string
+ /**
+ * @return string[]
+ */
+ public function getNodes(): array
{
- return 'Echo_';
+ return ['Echo_'];
}
}
```
<br>
### StaticCallToFuncCallRector
Turns static call to function call.

View File

@ -1,37 +0,0 @@
<?php
namespace Rector\Tests\Transform\Rector\ClassMethod\SingleToManyMethodRector\Fixture;
use Rector\Tests\Transform\Rector\ClassMethod\SingleToManyMethodRector\Source\OneToManyInterface;
class SomeClass implements OneToManyInterface
{
/**
* @return class-string<\PhpParser\Node>
*/
public function getNode(): string
{
return 'Echo_';
}
}
?>
-----
<?php
namespace Rector\Tests\Transform\Rector\ClassMethod\SingleToManyMethodRector\Fixture;
use Rector\Tests\Transform\Rector\ClassMethod\SingleToManyMethodRector\Source\OneToManyInterface;
class SomeClass implements OneToManyInterface
{
/**
* @return string[]
*/
public function getNodes(): array
{
return ['Echo_'];
}
}
?>

View File

@ -1,45 +0,0 @@
<?php
namespace Rector\Tests\Transform\Rector\ClassMethod\SingleToManyMethodRector\Fixture;
use Rector\Tests\Transform\Rector\ClassMethod\SingleToManyMethodRector\Source\OneToManyInterface;
class MultiReturn implements OneToManyInterface
{
/**
* @return class-string<\PhpParser\Node>
*/
public function getNode(): string
{
if (true) {
return 'Echo_';
}
return 'Exit_';
}
}
?>
-----
<?php
namespace Rector\Tests\Transform\Rector\ClassMethod\SingleToManyMethodRector\Fixture;
use Rector\Tests\Transform\Rector\ClassMethod\SingleToManyMethodRector\Source\OneToManyInterface;
class MultiReturn implements OneToManyInterface
{
/**
* @return string[]
*/
public function getNodes(): array
{
if (true) {
return ['Echo_'];
}
return ['Exit_'];
}
}
?>

View File

@ -1,31 +0,0 @@
<?php
namespace Rector\Tests\Transform\Rector\ClassMethod\SingleToManyMethodRector\Fixture;
use Rector\Tests\Transform\Rector\ClassMethod\SingleToManyMethodRector\Source\OneToManyInterface;
class NoReturnType implements OneToManyInterface
{
public function getNode()
{
return 'Echo_';
}
}
?>
-----
<?php
namespace Rector\Tests\Transform\Rector\ClassMethod\SingleToManyMethodRector\Fixture;
use Rector\Tests\Transform\Rector\ClassMethod\SingleToManyMethodRector\Source\OneToManyInterface;
class NoReturnType implements OneToManyInterface
{
public function getNodes(): array
{
return ['Echo_'];
}
}
?>

View File

@ -1,37 +0,0 @@
<?php
namespace Rector\Tests\Transform\Rector\ClassMethod\SingleToManyMethodRector\Fixture;
use Rector\Tests\Transform\Rector\ClassMethod\SingleToManyMethodRector\Source\OneToManyInterface;
class ReturnClassConstFetch implements OneToManyInterface
{
/**
* @return class-string<\PhpParser\Node>
*/
public function getNode(): string
{
return self::class;
}
}
?>
-----
<?php
namespace Rector\Tests\Transform\Rector\ClassMethod\SingleToManyMethodRector\Fixture;
use Rector\Tests\Transform\Rector\ClassMethod\SingleToManyMethodRector\Source\OneToManyInterface;
class ReturnClassConstFetch implements OneToManyInterface
{
/**
* @return string[]
*/
public function getNodes(): array
{
return [self::class];
}
}
?>

View File

@ -1,33 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\Tests\Transform\Rector\ClassMethod\SingleToManyMethodRector;
use Iterator;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
use Symplify\SmartFileSystem\SmartFileInfo;
final class SingleToManyMethodRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(SmartFileInfo $fileInfo): void
{
$this->doTestFileInfo($fileInfo);
}
/**
* @return Iterator<SmartFileInfo>
*/
public function provideData(): Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}
public function provideConfigFilePath(): string
{
return __DIR__ . '/config/configured_rule.php';
}
}

View File

@ -1,10 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\Tests\Transform\Rector\ClassMethod\SingleToManyMethodRector\Source;
interface OneToManyInterface
{
}

View File

@ -1,14 +0,0 @@
<?php
declare(strict_types=1);
use Rector\Tests\Transform\Rector\ClassMethod\SingleToManyMethodRector\Source\OneToManyInterface;
use Rector\Transform\Rector\ClassMethod\SingleToManyMethodRector;
use Rector\Transform\ValueObject\SingleToManyMethod;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
$services->set(SingleToManyMethodRector::class)
->configure([new SingleToManyMethod(OneToManyInterface::class, 'getNode', 'getNodes')]);
};

View File

@ -1,152 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\Transform\Rector\ClassMethod;
use PhpParser\Node;
use PhpParser\Node\Identifier;
use PhpParser\Node\Stmt\ClassLike;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Return_;
use PHPStan\Type\ArrayType;
use PHPStan\Type\MixedType;
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\Rector\AbstractRector;
use Rector\Transform\ValueObject\SingleToManyMethod;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
use Webmozart\Assert\Assert;
/**
* @see \Rector\Tests\Transform\Rector\ClassMethod\SingleToManyMethodRector\SingleToManyMethodRectorTest
*/
final class SingleToManyMethodRector extends AbstractRector implements ConfigurableRectorInterface
{
/**
* @api
* @deprecated
* @var string
*/
public const SINGLES_TO_MANY_METHODS = 'singles_to_many_methods';
/**
* @var SingleToManyMethod[]
*/
private array $singleToManyMethods = [];
public function __construct(
private readonly PhpDocTypeChanger $phpDocTypeChanger
) {
}
public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition('Change method that returns single value to multiple values', [
new ConfiguredCodeSample(
<<<'CODE_SAMPLE'
class SomeClass
{
public function getNode(): string
{
return 'Echo_';
}
}
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
class SomeClass
{
/**
* @return string[]
*/
public function getNodes(): array
{
return ['Echo_'];
}
}
CODE_SAMPLE
,
[new SingleToManyMethod('SomeClass', 'getNode', 'getNodes')]
),
]);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes(): array
{
return [ClassMethod::class];
}
/**
* @param ClassMethod $node
*/
public function refactor(Node $node): ?Node
{
$classLike = $this->betterNodeFinder->findParentType($node, ClassLike::class);
if (! $classLike instanceof ClassLike) {
return null;
}
foreach ($this->singleToManyMethods as $singleToManyMethod) {
if (! $this->isObjectType($classLike, $singleToManyMethod->getObjectType())) {
continue;
}
if (! $this->isName($node, $singleToManyMethod->getSingleMethodName())) {
continue;
}
$node->name = new Identifier($singleToManyMethod->getManyMethodName());
$this->keepOldReturnTypeInDocBlock($node);
$node->returnType = new Identifier('array');
$this->wrapReturnValueToArray($node);
return $node;
}
return null;
}
/**
* @param mixed[] $configuration
*/
public function configure(array $configuration): void
{
$singleToManyMethods = $configuration[self::SINGLES_TO_MANY_METHODS] ?? $configuration;
Assert::allIsAOf($singleToManyMethods, SingleToManyMethod::class);
$this->singleToManyMethods = $singleToManyMethods;
}
private function keepOldReturnTypeInDocBlock(ClassMethod $classMethod): void
{
// keep old return type in the docblock
$oldReturnType = $classMethod->returnType;
if ($oldReturnType === null) {
return;
}
$staticType = $this->staticTypeMapper->mapPhpParserNodePHPStanType($oldReturnType);
$arrayType = new ArrayType(new MixedType(), $staticType);
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($classMethod);
$this->phpDocTypeChanger->changeReturnType($phpDocInfo, $arrayType);
}
private function wrapReturnValueToArray(ClassMethod $classMethod): void
{
$this->traverseNodesWithCallable((array) $classMethod->stmts, function (Node $node) {
if (! $node instanceof Return_) {
return null;
}
$node->expr = $this->nodeFactory->createArray([$node->expr]);
return null;
});
}
}

View File

@ -1,34 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\Transform\ValueObject;
use PHPStan\Type\ObjectType;
use Rector\Core\Validation\RectorAssert;
final class SingleToManyMethod
{
public function __construct(
private readonly string $class,
private readonly string $singleMethodName,
private readonly string $manyMethodName
) {
RectorAssert::className($class);
}
public function getObjectType(): ObjectType
{
return new ObjectType($this->class);
}
public function getSingleMethodName(): string
{
return $this->singleMethodName;
}
public function getManyMethodName(): string
{
return $this->manyMethodName;
}
}