mirror of
https://github.com/rectorphp/rector.git
synced 2025-02-25 12:14:02 +01:00
Cast return value if its not an int
This commit is contained in:
parent
16e225ba06
commit
1ecef4cedd
@ -4,25 +4,20 @@ 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\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\ClassLike;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PhpParser\Node\Stmt\Namespace_;
|
||||
use PhpParser\Node\Stmt\Return_;
|
||||
use PHPStan\Type\ObjectType;
|
||||
use PHPStan\Type\Type;
|
||||
use PHPStan\Type\UnionType;
|
||||
use Rector\Exception\ShouldNotHappenException;
|
||||
use PHPStan\Type\IntegerType;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\RectorDefinition\CodeSample;
|
||||
use Rector\RectorDefinition\RectorDefinition;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
|
||||
/**
|
||||
* Covers:
|
||||
@ -31,16 +26,6 @@ use Rector\RectorDefinition\RectorDefinition;
|
||||
*/
|
||||
final class ConsoleExecuteReturnIntRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private const COMMAND_CLASS = '\Symfony\Component\Console\Command\Command';
|
||||
|
||||
/**
|
||||
* @var ClassLike[]
|
||||
*/
|
||||
private $classes = [];
|
||||
|
||||
public function getDefinition(): RectorDefinition
|
||||
{
|
||||
return new RectorDefinition('Returns int from Command::execute command', [
|
||||
@ -90,7 +75,7 @@ PHP
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! $class->extends || $class->extends->toCodeString() !== self::COMMAND_CLASS) {
|
||||
if (! $class->extends || $class->extends->toCodeString() !== '\\' . Command::class) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -99,25 +84,10 @@ PHP
|
||||
return $this->addReturn0ToMethod($node);
|
||||
}
|
||||
|
||||
public function beforeTraverse(array $nodes): void
|
||||
{
|
||||
foreach ($nodes as $node) {
|
||||
if ($node instanceof Namespace_) {
|
||||
$this->beforeTraverse($node->stmts);
|
||||
}
|
||||
|
||||
if (! $node instanceof ClassLike) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->classes[$this->getName($node)] = $node;
|
||||
}
|
||||
}
|
||||
|
||||
private function addReturn0ToMethod(FunctionLike $functionLike): FunctionLike
|
||||
{
|
||||
$hasReturn = false;
|
||||
$this->traverseNodesWithCallable($functionLike->getStmts(), function (Node &$stmt) use (
|
||||
$this->traverseNodesWithCallable($functionLike->getStmts(), function (Node $stmt) use (
|
||||
$functionLike,
|
||||
&$hasReturn
|
||||
): void {
|
||||
@ -145,73 +115,24 @@ PHP
|
||||
{
|
||||
if (! $return->expr) {
|
||||
$return->expr = new LNumber(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if ($return->expr instanceof ConstFetch && $this->getName($return->expr) === 'null') {
|
||||
$return->expr = new LNumber(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if ($return->expr instanceof Coalesce && $return->expr->right instanceof ConstFetch && $this->getName(
|
||||
$return->expr->right
|
||||
) === 'null') {
|
||||
$return->expr->right = new LNumber(0);
|
||||
}
|
||||
|
||||
if ($return->expr instanceof MethodCall) {
|
||||
$object = $this->getObjectType($return->expr->var);
|
||||
|
||||
$this->refactorMethodOnObject($return, $object);
|
||||
}
|
||||
|
||||
if ($return->expr instanceof StaticCall) {
|
||||
$object = $this->getObjectType($return->expr->class);
|
||||
|
||||
$this->refactorMethodOnObject($return, $object);
|
||||
}
|
||||
}
|
||||
|
||||
private function refactorMethodOnObject(Return_ $return, Type $type): void
|
||||
{
|
||||
if ($type instanceof ObjectType) {
|
||||
$this->refactorClassMethod($type->getClassName(), $this->getName($return->expr));
|
||||
return;
|
||||
}
|
||||
|
||||
if ($type instanceof UnionType) {
|
||||
$baseClass = $type->getTypes()[0];
|
||||
if (! $baseClass instanceof ObjectType) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
$this->refactorClassMethod($baseClass->getClassName(), $this->getName($return->expr));
|
||||
if (! $this->getStaticType($return->expr) instanceof IntegerType) {
|
||||
$return->expr = new Int_($return->expr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private function refactorClassMethod(string $className, string $methodName): void
|
||||
{
|
||||
if (! array_key_exists($className, $this->classes)) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
$methods = $this->betterNodeFinder->find($this->classes[$className]->getMethods(), function (Node $node) use (
|
||||
$methodName
|
||||
) {
|
||||
if (! $node instanceof ClassMethod) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($this->getName($node) === $methodName) {
|
||||
return $node;
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
if (count($methods) !== 1) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
$this->addReturn0ToMethod($methods[0]);
|
||||
}
|
||||
}
|
||||
|
@ -24,9 +24,7 @@ final class ConsoleExecuteReturnIntRectorTest extends AbstractRectorTestCase
|
||||
yield [__DIR__ . '/Fixture/multiple-returns.php.inc'];
|
||||
yield [__DIR__ . '/Fixture/add-return-type.php.inc'];
|
||||
yield [__DIR__ . '/Fixture/return-function-call.php.inc'];
|
||||
yield [__DIR__ . '/Fixture/return-external-function-call.php.inc'];
|
||||
yield [__DIR__ . '/Fixture/return-static-function-call.php.inc'];
|
||||
yield [__DIR__ . '/Fixture/return-external-static-function-call.php.inc'];
|
||||
}
|
||||
|
||||
protected function getRectorClass(): string
|
||||
|
@ -1,57 +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 ReturnExternalFunctionCall extends Command
|
||||
{
|
||||
/** @var ExternalClass */
|
||||
private $external;
|
||||
|
||||
public function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
return $this->external->doSomething();
|
||||
}
|
||||
}
|
||||
|
||||
final class ExternalCLass
|
||||
{
|
||||
public 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 ReturnExternalFunctionCall extends Command
|
||||
{
|
||||
/** @var ExternalClass */
|
||||
private $external;
|
||||
|
||||
public function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
return $this->external->doSomething();
|
||||
}
|
||||
}
|
||||
|
||||
final class ExternalCLass
|
||||
{
|
||||
public function doSomething()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -1,51 +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 ReturnExternalStaticFunctionCall extends Command
|
||||
{
|
||||
public function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
return ExternalStaticCLass::doSomething();
|
||||
}
|
||||
}
|
||||
|
||||
final class ExternalStaticCLass
|
||||
{
|
||||
public static 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 ReturnExternalStaticFunctionCall extends Command
|
||||
{
|
||||
public function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
return ExternalStaticCLass::doSomething();
|
||||
}
|
||||
}
|
||||
|
||||
final class ExternalStaticCLass
|
||||
{
|
||||
public static function doSomething()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -33,12 +33,12 @@ final class ReturnFunctionCallCommand extends Command
|
||||
{
|
||||
public function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
return $this->doSomething();
|
||||
return (int) $this->doSomething();
|
||||
}
|
||||
|
||||
private function doSomething()
|
||||
{
|
||||
return 0;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,12 +33,12 @@ final class ReturnStaticFunctionCallCommand extends Command
|
||||
{
|
||||
public function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
return static::doSomething();
|
||||
return (int) static::doSomething();
|
||||
}
|
||||
|
||||
private static function doSomething()
|
||||
{
|
||||
return 0;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user