mirror of
https://github.com/rectorphp/rector.git
synced 2025-02-24 11:44:14 +01:00
Add ConsoleExecuteReturnIntRector
Fixes: https://github.com/rectorphp/rector/issues/2119
This commit is contained in:
parent
5e440fb900
commit
33a41ddb4a
5
config/set/symfony/symfony44.yaml
Normal file
5
config/set/symfony/symfony44.yaml
Normal file
@ -0,0 +1,5 @@
|
||||
services:
|
||||
# https://github.com/symfony/symfony/blob/4.4/UPGRADE-4.4.md
|
||||
|
||||
# https://github.com/symfony/symfony/pull/33775
|
||||
Rector\Symfony\Rector\Console\ConsoleExecuteReturnIntRector: ~
|
@ -0,0 +1,125 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\Symfony\Rector\Console;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\ConstFetch;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Expr\StaticCall;
|
||||
use PhpParser\Node\FunctionLike;
|
||||
use PhpParser\Node\Identifier;
|
||||
use PhpParser\Node\Scalar\LNumber;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PhpParser\Node\Stmt\Return_;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\RectorDefinition\CodeSample;
|
||||
use Rector\RectorDefinition\RectorDefinition;
|
||||
|
||||
/**
|
||||
* Covers:
|
||||
* - https://github.com/symfony/symfony/pull/33775/files
|
||||
* @see \Rector\Symfony\Tests\Rector\Console\ConsoleExecuteReturnIntRector\ConsoleExecuteReturnIntRectorTest
|
||||
*/
|
||||
final class ConsoleExecuteReturnIntRector extends AbstractRector
|
||||
{
|
||||
private const COMMAND_CLASS = '\Symfony\Component\Console\Command\Command';
|
||||
|
||||
public function getDefinition(): RectorDefinition
|
||||
{
|
||||
return new RectorDefinition('Returns int from Command::execute command', [
|
||||
new CodeSample(
|
||||
<<<'PHP'
|
||||
class SomeCommand extends Command
|
||||
{
|
||||
public function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
PHP
|
||||
,
|
||||
<<<'PHP'
|
||||
class SomeCommand extends Command
|
||||
{
|
||||
public function index(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
PHP
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [ClassMethod::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ClassMethod $node
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
if ($this->getName($node) !== 'execute') {
|
||||
return null;
|
||||
}
|
||||
|
||||
$class = $node->getAttribute(AttributeKey::CLASS_NODE);
|
||||
if (! $class || ! $class instanceof Class_) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!$class->extends || $class->extends->toCodeString() !== self::COMMAND_CLASS) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$node->returnType = new Identifier('int');
|
||||
|
||||
return $this->addReturn0ToMethod($node);
|
||||
}
|
||||
|
||||
private function setReturnTo0InsteadOfNull(Return_ $return)
|
||||
{
|
||||
if (! $return->expr ) {
|
||||
$return->expr = new LNumber(0);
|
||||
}
|
||||
|
||||
if ($return->expr instanceof ConstFetch && $this->getName($return->expr) === 'null') {
|
||||
$return->expr = new LNumber(0);
|
||||
}
|
||||
|
||||
if ($return->expr instanceof MethodCall || $return->expr instanceof StaticCall) {
|
||||
// how to get the Node of teh called method?!
|
||||
}
|
||||
}
|
||||
|
||||
private function addReturn0ToMethod(FunctionLike $node): FunctionLike
|
||||
{
|
||||
$hasReturn = false;
|
||||
$this->traverseNodesWithCallable($node->getStmts(), function (Node &$stmt) use ($node, &$hasReturn) {
|
||||
if (!$stmt instanceof Return_) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->areNodesEqual($stmt->getAttribute(AttributeKey::PARENT_NODE), $node)) {
|
||||
$hasReturn = true;
|
||||
}
|
||||
|
||||
$this->setReturnTo0InsteadOfNull($stmt);
|
||||
});
|
||||
|
||||
if ($hasReturn) {
|
||||
return $node;
|
||||
}
|
||||
|
||||
$node->stmts[] = new Return_(new LNumber(0));
|
||||
|
||||
return $node;
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\Symfony\Tests\Rector\Console\ConsoleExecuteReturnIntRector;
|
||||
|
||||
use Iterator;
|
||||
use Rector\Symfony\Rector\Console\ConsoleExecuteReturnIntRector;
|
||||
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
|
||||
final class ConsoleExecuteReturnIntRectorTest extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider provideDataForTest()
|
||||
*/
|
||||
public function test(string $file): void
|
||||
{
|
||||
$this->doTestFile($file);
|
||||
}
|
||||
|
||||
public function provideDataForTest(): Iterator
|
||||
{
|
||||
yield [__DIR__ . '/Fixture/explicit-return-null.php.inc'];
|
||||
yield [__DIR__ . '/Fixture/no-return.php.inc'];
|
||||
yield [__DIR__ . '/Fixture/empty-return.php.inc'];
|
||||
yield [__DIR__ . '/Fixture/multiple-returns.php.inc'];
|
||||
yield [__DIR__ . '/Fixture/add-return-type.php.inc'];
|
||||
yield [__DIR__ . '/Fixture/return-function-call.php.inc'];
|
||||
}
|
||||
|
||||
protected function getRectorClass(): string
|
||||
{
|
||||
return ConsoleExecuteReturnIntRector::class;
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
<?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 AddReturnTypeCommand extends Command
|
||||
{
|
||||
public function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?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 AddReturnTypeCommand extends Command
|
||||
{
|
||||
public function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,35 @@
|
||||
<?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 EmptyReturnCommand extends Command
|
||||
{
|
||||
public function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?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 EmptyReturnCommand extends Command
|
||||
{
|
||||
public function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,37 @@
|
||||
<?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 ExplicitReturnNullCommand extends Command
|
||||
{
|
||||
public function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
// execute
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?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 ExplicitReturnNullCommand extends Command
|
||||
{
|
||||
public function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
// execute
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,48 @@
|
||||
<?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 MultipleReturnCommand extends Command
|
||||
{
|
||||
public function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
if ($earlyReturn) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($erroCondition) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?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 MultipleReturnCommand extends Command
|
||||
{
|
||||
public function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
if ($earlyReturn) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ($erroCondition) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,36 @@
|
||||
<?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 NoReturnCommand extends Command
|
||||
{
|
||||
public function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$this->doSomething();
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?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 NoReturnCommand extends Command
|
||||
{
|
||||
public function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$this->doSomething();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,45 @@
|
||||
<?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 ReturnFunctionCallCommand extends Command
|
||||
{
|
||||
public function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
return $this->doSomething();
|
||||
}
|
||||
|
||||
private function doSomething()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?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 ReturnFunctionCallCommand extends Command
|
||||
{
|
||||
public function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
return $this->doSomething();
|
||||
}
|
||||
|
||||
private function doSomething()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
Loading…
x
Reference in New Issue
Block a user