optimize ConsoleExecuteReturnIntRector

This commit is contained in:
Tomas Votruba 2019-10-26 12:11:49 +02:00
parent 10043573e9
commit 07413334f7
5 changed files with 59 additions and 57 deletions

View File

@ -7,7 +7,6 @@ namespace Rector\Symfony\Rector\Console;
use PhpParser\Node;
use PhpParser\Node\Expr\BinaryOp\Coalesce;
use PhpParser\Node\Expr\Cast\Int_;
use PhpParser\Node\Expr\ConstFetch;
use PhpParser\Node\Identifier;
use PhpParser\Node\Scalar\LNumber;
use PhpParser\Node\Stmt\Class_;
@ -21,8 +20,7 @@ use Rector\RectorDefinition\RectorDefinition;
use Symfony\Component\Console\Command\Command;
/**
* Covers:
* - https://github.com/symfony/symfony/pull/33775/files
* @see https://github.com/symfony/symfony/pull/33775/files
* @see \Rector\Symfony\Tests\Rector\Console\ConsoleExecuteReturnIntRector\ConsoleExecuteReturnIntRectorTest
*/
final class ConsoleExecuteReturnIntRector extends AbstractRector
@ -67,26 +65,26 @@ PHP
*/
public function refactor(Node $node): ?Node
{
if ($this->getName($node) !== 'execute') {
if (! $this->isName($node, 'execute')) {
return null;
}
$class = $node->getAttribute(AttributeKey::CLASS_NODE);
if (! $class || ! $class instanceof Class_) {
if (! $class instanceof Class_) {
return null;
}
$reflection = new \ReflectionClass($this->getName($class));
if (! $reflection->isSubclassOf(Command::class)) {
if (! $this->isObjectType($class, Command::class)) {
return null;
}
$node->returnType = new Identifier('int');
$this->refactorReturnType($node);
$this->addReturn0ToMethod($node);
return $this->addReturn0ToMethod($node);
return $node;
}
private function addReturn0ToMethod(ClassMethod $classMethod): ClassMethod
private function addReturn0ToMethod(ClassMethod $classMethod): void
{
$hasReturn = false;
$this->traverseNodesWithCallable($classMethod->getStmts() ?? [], function (Node $stmt) use (
@ -105,12 +103,10 @@ PHP
});
if ($hasReturn) {
return $classMethod;
return;
}
$classMethod->stmts[] = new Return_(new LNumber(0));
return $classMethod;
}
private function setReturnTo0InsteadOfNull(Return_ $return): void
@ -120,14 +116,12 @@ PHP
return;
}
if ($return->expr instanceof ConstFetch && $this->getName($return->expr) === 'null') {
if ($this->isNull($return->expr)) {
$return->expr = new LNumber(0);
return;
}
if ($return->expr instanceof Coalesce && $return->expr->right instanceof ConstFetch && $this->getName(
$return->expr->right
) === 'null') {
if ($return->expr instanceof Coalesce && $this->isNull($return->expr->right)) {
$return->expr->right = new LNumber(0);
return;
}
@ -137,4 +131,16 @@ PHP
return;
}
}
private function refactorReturnType(ClassMethod $classMethod): void
{
if ($classMethod->returnType) {
// already set
if ($this->isName($classMethod->returnType, 'int')) {
return;
}
}
$classMethod->returnType = new Identifier('int');
}
}

View File

@ -20,7 +20,6 @@ final class ConsoleExecuteReturnIntRectorTest extends AbstractRectorTestCase
public function provideDataForTest(): Iterator
{
yield [__DIR__ . '/Fixture/non-console-command.php.inc'];
yield [__DIR__ . '/Fixture/extends-command-not-directly.php.inc'];
yield [__DIR__ . '/Fixture/explicit-return-null.php.inc'];
yield [__DIR__ . '/Fixture/no-return.php.inc'];
@ -29,6 +28,10 @@ final class ConsoleExecuteReturnIntRectorTest extends AbstractRectorTestCase
yield [__DIR__ . '/Fixture/add-return-type.php.inc'];
yield [__DIR__ . '/Fixture/return-function-call.php.inc'];
yield [__DIR__ . '/Fixture/return-static-function-call.php.inc'];
// skip
yield [__DIR__ . '/Fixture/skip_non_console_command.php.inc'];
yield [__DIR__ . '/Fixture/skip_already_int.php.inc'];
}
protected function getRectorClass(): string

View File

@ -1,39 +0,0 @@
<?php
namespace Rector\Symfony\Tests\Rector\Console\ConsoleExecuteReturnIntRector\Fixture;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
final class NonConsoleCommand extends NotACommand
{
public function execute(string $foo, string $bar)
{
return null;
}
}
class NotACommand {}
?>
-----
<?php
namespace Rector\Symfony\Tests\Rector\Console\ConsoleExecuteReturnIntRector\Fixture;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
final class NonConsoleCommand extends NotACommand
{
public function execute(string $foo, string $bar)
{
return null;
}
}
class NotACommand {}
?>

View File

@ -0,0 +1,15 @@
<?php
namespace Rector\Symfony\Tests\Rector\Console\ConsoleExecuteReturnIntRector\Fixture;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
final class SkipAlreadyInt extends Command
{
public function execute(InputInterface $input, OutputInterface $output): int
{
return 2;
}
}

View File

@ -0,0 +1,17 @@
<?php
namespace Rector\Symfony\Tests\Rector\Console\ConsoleExecuteReturnIntRector\Fixture;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
final class SkipNonConsoleCommand extends NotACommand
{
public function execute(string $foo, string $bar)
{
return null;
}
}
class NotACommand {}