Skip to content

Commit

Permalink
[TypeDeclaration] Skip union false on NumericReturnTypeFromStrictScal…
Browse files Browse the repository at this point in the history
…arReturnsRector (#5204)

* [TypeDeclaration] Skip union false on NumericReturnTypeFromStrictScalarReturnsRector

* Fix

* int and float fixture

* skip int|float

* fix
  • Loading branch information
samsonasik committed Oct 26, 2023
1 parent be0cc77 commit 89b3e62
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 99 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\NumericReturnTypeFromStrictScalarReturnsRector\Fixture;

final class IntInt
{
public function resolve($param, int $first, int $second)
{
if (! $param) {
return $first - $second;
}

return 1 + (int) $param;
}
}

?>
-----
<?php

namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\NumericReturnTypeFromStrictScalarReturnsRector\Fixture;

final class IntInt
{
public function resolve($param, int $first, int $second): int
{
if (! $param) {
return $first - $second;
}

return 1 + (int) $param;
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\NumericReturnTypeFromStrictScalarReturnsRector\Fixture;

final class SkipIntFloat
{
public function resolve($param, float $first, float $second)
{
if (! $param) {
return $first - $second;
}

return 1 + (int) $param;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\NumericReturnTypeFromStrictScalarReturnsRector\Fixture;

final class SkipUnionFalse
{
public function resolve($param)
{
if (! $param) {
return false;
}

return 1 + (int) $param;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,14 @@
namespace Rector\TypeDeclaration\Rector\ClassMethod;

use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\BinaryOp;
use PhpParser\Node\Expr\BinaryOp\BitwiseAnd;
use PhpParser\Node\Expr\BinaryOp\BitwiseOr;
use PhpParser\Node\Expr\BinaryOp\Minus;
use PhpParser\Node\Expr\BinaryOp\Mod;
use PhpParser\Node\Expr\BinaryOp\Mul;
use PhpParser\Node\Expr\BinaryOp\Plus;
use PhpParser\Node\Expr\BinaryOp\ShiftLeft;
use PhpParser\Node\Expr\BinaryOp\ShiftRight;
use PhpParser\Node\Expr\Closure;
use PhpParser\Node\Expr\PostDec;
use PhpParser\Node\Expr\PostInc;
use PhpParser\Node\Expr\PreDec;
use PhpParser\Node\Expr\PreInc;
use PhpParser\Node\Identifier;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Function_;
use PhpParser\Node\Stmt\Return_;
use PHPStan\Analyser\Scope;
use PHPStan\Type\FloatType;
use PHPStan\Type\IntegerType;
use Rector\Core\Rector\AbstractScopeAwareRector;
use Rector\Core\ValueObject\PhpVersionFeature;
use Rector\TypeDeclaration\TypeInferer\ReturnTypeInferer;
use Rector\VendorLocker\NodeVendorLocker\ClassMethodReturnTypeOverrideGuard;
use Rector\VersionBonding\Contract\MinPhpVersionInterface;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
Expand All @@ -40,7 +24,8 @@
final class NumericReturnTypeFromStrictScalarReturnsRector extends AbstractScopeAwareRector implements MinPhpVersionInterface
{
public function __construct(
private readonly ClassMethodReturnTypeOverrideGuard $classMethodReturnTypeOverrideGuard
private readonly ClassMethodReturnTypeOverrideGuard $classMethodReturnTypeOverrideGuard,
private readonly ReturnTypeInferer $returnTypeInferer
) {
}

Expand Down Expand Up @@ -100,36 +85,15 @@ public function refactorWithScope(Node $node, Scope $scope): ?Node
return null;
}

$return = $this->matchRootReturnWithExpr($node);
if (! $return instanceof Return_) {
return null;
$returnType = $this->returnTypeInferer->inferFunctionLike($node);
if ($returnType->isFloat()->yes()) {
$node->returnType = new Identifier('float');
return $node;
}

if ($return->expr instanceof PreInc
|| $return->expr instanceof PostInc
|| $return->expr instanceof PostDec
|| $return->expr instanceof PreDec
) {
$exprType = $this->nodeTypeResolver->getNativeType($return->expr);
if ($exprType instanceof IntegerType) {
$node->returnType = new Identifier('int');
return $node;
}

return null;
}

// @see https://chat.openai.com/share/a9e4fb74-5366-4c4c-9998-d6caeb8b5acc
if ($return->expr instanceof Minus
|| $return->expr instanceof Plus
|| $return->expr instanceof Mul
|| $return->expr instanceof Mod
|| $return->expr instanceof BitwiseAnd
|| $return->expr instanceof ShiftRight
|| $return->expr instanceof ShiftLeft
|| $return->expr instanceof BitwiseOr
) {
return $this->refactorBinaryOp($return->expr, $node);
if ($returnType->isInteger()->yes()) {
$node->returnType = new Identifier('int');
return $node;
}

return null;
Expand All @@ -139,57 +103,4 @@ public function provideMinPhpVersion(): int
{
return PhpVersionFeature::SCALAR_TYPES;
}

private function matchRootReturnWithExpr(ClassMethod|Function_|Closure $functionLike): ?Return_
{
if ($functionLike->stmts === null) {
return null;
}

foreach ($functionLike->stmts as $stmt) {
if (! $stmt instanceof Return_) {
continue;
}

if (! $stmt->expr instanceof Expr) {
return null;
}

return $stmt;
}

return null;
}

private function refactorBinaryOp(
BinaryOp $binaryOp,
ClassMethod|Function_|Closure $functionLike
): null|Function_|ClassMethod|Closure {
$leftType = $this->nodeTypeResolver->getNativeType($binaryOp->left);
$rightType = $this->nodeTypeResolver->getNativeType($binaryOp->right);

if ($leftType instanceof IntegerType && $rightType instanceof IntegerType) {
$functionLike->returnType = new Identifier('int');
return $functionLike;
}

if ($leftType instanceof FloatType && $rightType instanceof FloatType) {
$functionLike->returnType = new Identifier('float');
return $functionLike;
}

if ($binaryOp instanceof Mul) {
if ($leftType instanceof FloatType && $rightType instanceof IntegerType) {
$functionLike->returnType = new Identifier('float');
return $functionLike;
}

if ($leftType instanceof IntegerType && $rightType instanceof FloatType) {
$functionLike->returnType = new Identifier('float');
return $functionLike;
}
}

return null;
}
}

0 comments on commit 89b3e62

Please sign in to comment.