Skip to content

Commit

Permalink
[TypeDeclaration] Skip assign override in ReturnTypeFromReturnNewRect…
Browse files Browse the repository at this point in the history
…or (#2648)
  • Loading branch information
TomasVotruba committed Jul 9, 2022
1 parent e8e2db7 commit 17ba943
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 15 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

declare(strict_types=1);

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

use Rector\Tests\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromReturnNewRector\Source\SomeResponse;

final class SkipDoubleAssignedToVariable
{
public function action()
{
$ambiguousResponse = new SomeResponse();

$ambiguousResponse = 5000;

return $ambiguousResponse;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Expr\Yield_;
use PhpParser\Node\Stmt;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Expression;
use PhpParser\Node\Stmt\Function_;
use PhpParser\Node\Stmt\Return_;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\NodeNameResolver\NodeNameResolver;
use Rector\TypeDeclaration\ValueObject\AssignToVariable;

final class StrictReturnNewAnalyzer
{
Expand Down Expand Up @@ -102,29 +104,24 @@ private function resolveCreatedVariablesToTypes(ClassMethod|Function_|Closure $f

// what new is assigned to it?
foreach ((array) $functionLike->stmts as $stmt) {
if (! $stmt instanceof Expression) {
$assignToVariable = $this->matchAssignToVariable($stmt);
if (! $assignToVariable instanceof AssignToVariable) {
continue;
}

if (! $stmt->expr instanceof Assign) {
continue;
}

$assign = $stmt->expr;
if (! $assign->expr instanceof New_) {
continue;
}
$assignedExpr = $assignToVariable->getAssignedExpr();
$variableName = $assignToVariable->getVariableName();

if (! $assign->var instanceof Variable) {
continue;
}
if (! $assignedExpr instanceof New_) {
// possible variable override by another type! - unset it
if (isset($createdVariablesToTypes[$variableName])) {
unset($createdVariablesToTypes[$variableName]);
}

$variableName = $this->nodeNameResolver->getName($assign->var);
if (! is_string($variableName)) {
continue;
}

$className = $this->nodeNameResolver->getName($assign->expr->class);
$className = $this->nodeNameResolver->getName($assignedExpr->class);
if (! is_string($className)) {
continue;
}
Expand All @@ -134,4 +131,29 @@ private function resolveCreatedVariablesToTypes(ClassMethod|Function_|Closure $f

return $createdVariablesToTypes;
}

private function matchAssignToVariable(Stmt $stmt): ?AssignToVariable
{
if (! $stmt instanceof Expression) {
return null;
}

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

$assign = $stmt->expr;
$assignedVar = $assign->var;

if (! $assignedVar instanceof Variable) {
return null;
}

$variableName = $this->nodeNameResolver->getName($assignedVar);
if (! is_string($variableName)) {
return null;
}

return new AssignToVariable($assignedVar, $variableName, $assign->expr);
}
}
33 changes: 33 additions & 0 deletions rules/TypeDeclaration/ValueObject/AssignToVariable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);

namespace Rector\TypeDeclaration\ValueObject;

use PhpParser\Node\Expr;
use PhpParser\Node\Expr\Variable;

final class AssignToVariable
{
public function __construct(
private readonly Variable $variable,
private readonly string $variableName,
private readonly Expr $assignedExpr
) {
}

public function getVariable(): Variable
{
return $this->variable;
}

public function getVariableName(): string
{
return $this->variableName;
}

public function getAssignedExpr(): Expr
{
return $this->assignedExpr;
}
}

0 comments on commit 17ba943

Please sign in to comment.