Skip to content
Original file line number Diff line number Diff line change
@@ -1,23 +1,39 @@
<?php

$string = '';
$string = (string) $string;
namespace Rector\Tests\DeadCode\Rector\Cast\RecastingRemovalRector\Fixture;

$array = [];
$array = (array) $array;
class Fixture
{
public function run()
{
$string = '';
$string = (string) $string;

$array = (array) $string;
$array = [];
$array = (array) $array;

$array = (array) $string;
}
}

?>
-----
<?php

$string = '';
$string = $string;
namespace Rector\Tests\DeadCode\Rector\Cast\RecastingRemovalRector\Fixture;

class Fixture
{
public function run()
{
$string = '';
$string = $string;

$array = [];
$array = $array;
$array = [];
$array = $array;

$array = (array) $string;
$array = (array) $string;
}
}

?>
Original file line number Diff line number Diff line change
@@ -1,23 +1,39 @@
<?php

$object = new stdClass();
$object = (object) $object;
$object = (array) $object;
namespace Rector\Tests\DeadCode\Rector\Cast\RecastingRemovalRector\Fixture;

$int = 5;
$float = (float) $int;
$int = (int) $int;
class Fixture2
{
public function run()
{
$object = new \stdClass();
$object = (object) $object;
$object = (array) $object;

$int = 5;
$float = (float) $int;
$int = (int) $int;
}
}

?>
-----
<?php

$object = new stdClass();
$object = $object;
$object = (array) $object;
namespace Rector\Tests\DeadCode\Rector\Cast\RecastingRemovalRector\Fixture;

class Fixture2
{
public function run()
{
$object = new \stdClass();
$object = $object;
$object = (array) $object;

$int = 5;
$float = (float) $int;
$int = $int;
$int = 5;
$float = (float) $int;
$int = $int;
}
}

?>
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,20 @@

use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\ArrayDimFetch;
use PhpParser\Node\Expr\Closure;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\AssignRef;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\FunctionLike;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Function_;
use PhpParser\Node\Stmt\Return_;
use PhpParser\NodeTraverser;
use PHPStan\Analyser\Scope;
use PHPStan\Type\MixedType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\TypeCombinator;
use PHPStan\Type\UnionType;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\Rector\AbstractScopeAwareRector;
use Rector\Core\ValueObject\PhpVersionFeature;
use Rector\TypeDeclaration\TypeInferer\ReturnTypeInferer;
Expand Down Expand Up @@ -90,22 +85,28 @@ public function provideMinPhpVersion(): int
*/
public function refactorWithScope(Node $node, Scope $scope): ?Node
{
if ($node->stmts === null) {
return null;
}

if ($this->shouldSkipNode($node)) {
return null;
}

$return = $this->findCurrentScopeReturn($node);
if ($return === null || $return->expr === null) {
$return = $this->findCurrentScopeReturn($node->stmts);
if (! $return instanceof Return_ || ! $return->expr instanceof Expr) {
return null;
}

$returnName = $this->getName($return->expr);
$stmts = $node->stmts;

foreach ($node->getParams() as $param) {
if (!$param->type instanceof Node) {
if (! $param->type instanceof Node) {
continue;
}

if ($this->shouldSkipParam($param, $node)) {
if ($this->shouldSkipParam($param, $stmts)) {
continue;
}

Expand All @@ -121,15 +122,14 @@ public function refactorWithScope(Node $node, Scope $scope): ?Node
return null;
}

private function findCurrentScopeReturn(ClassMethod|Function_ $node): ?Return_
/**
* @param Stmt[] $stmts
*/
private function findCurrentScopeReturn(array $stmts): ?Return_
{
$return = null;

if ($node->stmts === null) {
return null;
}

$this->traverseNodesWithCallable($node->stmts, function (Node $node) use (&$return): ?int {
$this->traverseNodesWithCallable($stmts, static function (Node $node) use (&$return): ?int {
if (! $node instanceof Return_) {
return null;
}
Expand All @@ -152,28 +152,24 @@ private function findCurrentScopeReturn(ClassMethod|Function_ $node): ?Return_
return $return;
}

private function shouldSkipParam(Param $param, ClassMethod|Function_ $functionLike): bool
/**
* @param Stmt[] $stmts
*/
private function shouldSkipParam(Param $param, array $stmts): bool
{
$paramName = $this->getName($param);

$isParamModified = false;

if ($functionLike->stmts === null) {
return true;
}

$this->traverseNodesWithCallable($functionLike->stmts, function (Node $node) use (
$this->traverseNodesWithCallable($stmts, function (Node $node) use (
$paramName,
&$isParamModified
): int|null {
if ($node instanceof Expr\AssignRef) {
if ($this->isName($node->expr, $paramName)) {
$isParamModified = true;
return NodeTraverser::STOP_TRAVERSAL;
}
if ($node instanceof AssignRef && $this->isName($node->expr, $paramName)) {
$isParamModified = true;
return NodeTraverser::STOP_TRAVERSAL;
}

if (! $node instanceof Expr\Assign) {
if (! $node instanceof Assign) {
return null;
}

Expand Down Expand Up @@ -214,10 +210,6 @@ private function shouldSkipNode(ClassMethod|Function_ $node): bool
}

$returnType = TypeCombinator::removeNull($returnType);
if ($returnType instanceof UnionType) {
return true;
}

return false;
return $returnType instanceof UnionType;
}
}
14 changes: 9 additions & 5 deletions rules/TypeDeclaration/TypeAnalyzer/ReturnStrictTypeAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

namespace Rector\TypeDeclaration\TypeAnalyzer;

use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Scalar\LNumber;
use PhpParser\Node\Scalar\DNumber;
use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\FuncCall;
Expand Down Expand Up @@ -51,10 +55,10 @@ public function collectStrictReturnTypes(array $returns, Scope $scope): array
$containsStrictCall = true;
$returnNode = $this->resolveMethodCallReturnNode($returnedExpr);
} elseif (
$returnedExpr instanceof Expr\Array_
|| $returnedExpr instanceof Node\Scalar\String_
|| $returnedExpr instanceof Node\Scalar\LNumber
|| $returnedExpr instanceof Node\Scalar\DNumber
$returnedExpr instanceof Array_
|| $returnedExpr instanceof String_
|| $returnedExpr instanceof LNumber
|| $returnedExpr instanceof DNumber
) {
$returnNode = $this->resolveLiteralReturnNode($returnedExpr, $scope);
} else {
Expand Down Expand Up @@ -97,7 +101,7 @@ public function resolveMethodCallReturnNode(MethodCall | StaticCall | FuncCall $
return $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode($returnType, TypeKind::RETURN);
}

private function resolveLiteralReturnNode(Expr\Array_|Scalar $returnedExpr, Scope $scope): ?Node
private function resolveLiteralReturnNode(Array_|Scalar $returnedExpr, Scope $scope): ?Node
{
$returnType = $scope->getType($returnedExpr);
return $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode($returnType, TypeKind::RETURN);
Expand Down