Skip to content

Commit

Permalink
[TypeDeclaration] Add Closure support on NumericReturnTypeFromStrictS…
Browse files Browse the repository at this point in the history
…calarReturnsRector (#4631)

* [TypeDeclaration] Add Closure support on NumericReturnTypeFromStrictScalarReturnsRector

* use native type

* clean up non typed check by native type check

* [ci-review] Rector Rectify

---------

Co-authored-by: GitHub Action <actions@github.com>
  • Loading branch information
samsonasik and actions-user committed Aug 3, 2023
1 parent c8d49fb commit 36e88e1
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 27 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

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

class WithClosure
{
public function resolve(int $first, int $second)
{
return function () use ($first, $second) {
return $first + $second;
};
}
}

?>
-----
<?php

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

class WithClosure
{
public function resolve(int $first, int $second)
{
return function () use ($first, $second): int {
return $first + $second;
};
}
}

?>
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
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;
Expand All @@ -25,7 +26,6 @@
use PhpParser\Node\Stmt\Return_;
use PHPStan\Type\FloatType;
use PHPStan\Type\IntegerType;
use Rector\Core\NodeAnalyzer\ExprAnalyzer;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\ValueObject\PhpVersionFeature;
use Rector\VersionBonding\Contract\MinPhpVersionInterface;
Expand All @@ -37,11 +37,6 @@
*/
final class NumericReturnTypeFromStrictScalarReturnsRector extends AbstractRector implements MinPhpVersionInterface
{
public function __construct(
private readonly ExprAnalyzer $exprAnalyzer,
) {
}

public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition('Change numeric return type based on strict returns type operations', [
Expand Down Expand Up @@ -75,11 +70,11 @@ public function resolve(int $first, int $second): int
*/
public function getNodeTypes(): array
{
return [ClassMethod::class, Function_::class];
return [ClassMethod::class, Function_::class, Closure::class];
}

/**
* @param ClassMethod|Function_ $node
* @param ClassMethod|Function_|Closure $node
*/
public function refactor(Node $node): ?Node
{
Expand All @@ -101,7 +96,7 @@ public function refactor(Node $node): ?Node
|| $return->expr instanceof PostDec
|| $return->expr instanceof PreDec
) {
$exprType = $this->getType($return->expr);
$exprType = $this->nodeTypeResolver->getNativeType($return->expr);
if ($exprType instanceof IntegerType) {
$node->returnType = new Identifier('int');
return $node;
Expand All @@ -120,10 +115,6 @@ public function refactor(Node $node): ?Node
|| $return->expr instanceof ShiftLeft
|| $return->expr instanceof BitwiseOr
) {
if ($this->isBinaryOpContainingNonTypedParam($return->expr)) {
return null;
}

return $this->refactorBinaryOp($return->expr, $node);
}

Expand All @@ -135,7 +126,7 @@ public function provideMinPhpVersion(): int
return PhpVersionFeature::SCALAR_TYPES;
}

private function matchRootReturnWithExpr(ClassMethod|Function_ $functionLike): ?Return_
private function matchRootReturnWithExpr(ClassMethod|Function_|Closure $functionLike): ?Return_
{
if ($functionLike->stmts === null) {
return null;
Expand All @@ -158,10 +149,10 @@ private function matchRootReturnWithExpr(ClassMethod|Function_ $functionLike): ?

private function refactorBinaryOp(
BinaryOp $binaryOp,
ClassMethod|Function_ $functionLike
): null|Function_|ClassMethod {
$leftType = $this->getType($binaryOp->left);
$rightType = $this->getType($binaryOp->right);
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');
Expand All @@ -187,13 +178,4 @@ private function refactorBinaryOp(

return null;
}

private function isBinaryOpContainingNonTypedParam(BinaryOp $binaryOp): bool
{
if ($this->exprAnalyzer->isNonTypedFromParam($binaryOp->left)) {
return true;
}

return $this->exprAnalyzer->isNonTypedFromParam($binaryOp->right);
}
}

0 comments on commit 36e88e1

Please sign in to comment.