2022-04-28 14:55:01 +00:00
< ? php
declare ( strict_types = 1 );
2022-06-06 17:12:56 +00:00
namespace Rector\CodeQuality\Rector\ClassMethod ;
2022-04-28 14:55:01 +00:00
2022-06-06 17:12:56 +00:00
use PhpParser\Node ;
use PhpParser\Node\Expr\Array_ ;
use PhpParser\Node\Expr\ArrayItem ;
use PhpParser\Node\Expr\Assign ;
use PhpParser\Node\Expr\Variable ;
use PhpParser\Node\Stmt ;
use PhpParser\Node\Stmt\Expression ;
use PhpParser\Node\Stmt\Return_ ;
use Rector\CodeQuality\NodeAnalyzer\VariableDimFetchAssignResolver ;
use Rector\CodeQuality\ValueObject\KeyAndExpr ;
use Rector\Core\Contract\PhpParser\Node\StmtsAwareInterface ;
use Rector\Core\Rector\AbstractRector ;
use Rector\NodeTypeResolver\Node\AttributeKey ;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample ;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition ;
2022-04-28 14:55:01 +00:00
/**
* @ see \Rector\Tests\CodeQuality\Rector\ClassMethod\InlineArrayReturnAssignRector\InlineArrayReturnAssignRectorTest
*/
2022-06-06 17:12:56 +00:00
final class InlineArrayReturnAssignRector extends \Rector\Core\Rector\AbstractRector
2022-04-28 14:55:01 +00:00
{
/**
* @ readonly
* @ var \Rector\CodeQuality\NodeAnalyzer\VariableDimFetchAssignResolver
*/
private $variableDimFetchAssignResolver ;
2022-06-06 17:12:56 +00:00
public function __construct ( \Rector\CodeQuality\NodeAnalyzer\VariableDimFetchAssignResolver $variableDimFetchAssignResolver )
2022-04-28 14:55:01 +00:00
{
$this -> variableDimFetchAssignResolver = $variableDimFetchAssignResolver ;
}
2022-06-06 17:12:56 +00:00
public function getRuleDefinition () : \Symplify\RuleDocGenerator\ValueObject\RuleDefinition
2022-04-28 14:55:01 +00:00
{
2022-06-06 17:12:56 +00:00
return new \Symplify\RuleDocGenerator\ValueObject\RuleDefinition ( 'Inline just in time array dim fetch assigns to direct return' , [ new \Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample ( <<< 'CODE_SAMPLE'
2022-04-28 14:55:01 +00:00
function getPerson ()
{
$person = [];
$person [ 'name' ] = 'Timmy' ;
$person [ 'surname' ] = 'Back' ;
return $person ;
}
CODE_SAMPLE
, <<< 'CODE_SAMPLE'
function getPerson ()
{
return [
'name' => 'Timmy' ,
'surname' => 'Back' ,
];
}
CODE_SAMPLE
)]);
}
/**
* @ return array < class - string < Node >>
*/
public function getNodeTypes () : array
{
2022-06-06 17:12:56 +00:00
return [ \Rector\Core\Contract\PhpParser\Node\StmtsAwareInterface :: class ];
2022-04-28 14:55:01 +00:00
}
2022-05-08 20:57:50 +00:00
/**
* @ param StmtsAwareInterface $node
*/
2022-06-06 17:12:56 +00:00
public function refactor ( \PhpParser\Node $node ) : ? \PhpParser\Node
2022-04-28 14:55:01 +00:00
{
$stmts = $node -> stmts ;
if ( $stmts === null ) {
return null ;
}
if ( \count ( $stmts ) < 3 ) {
return null ;
}
$firstStmt = \array_shift ( $stmts );
$variable = $this -> matchVariableAssignOfEmptyArray ( $firstStmt );
2022-06-06 17:12:56 +00:00
if ( ! $variable instanceof \PhpParser\Node\Expr\Variable ) {
2022-04-28 14:55:01 +00:00
return null ;
}
$lastStmt = \array_pop ( $stmts );
2022-06-06 17:12:56 +00:00
if ( ! $lastStmt instanceof \PhpParser\Node\Stmt ) {
2022-04-28 14:55:01 +00:00
return null ;
}
if ( ! $this -> isReturnOfVariable ( $lastStmt , $variable )) {
return null ;
}
$keysAndExprs = $this -> variableDimFetchAssignResolver -> resolveFromStmtsAndVariable ( $stmts , $variable );
if ( $keysAndExprs === []) {
return null ;
}
$array = $this -> createArray ( $keysAndExprs );
2022-06-06 17:12:56 +00:00
$node -> stmts = [ new \PhpParser\Node\Stmt\Return_ ( $array )];
2022-04-28 14:55:01 +00:00
return $node ;
}
2022-06-06 17:12:56 +00:00
private function matchVariableAssignOfEmptyArray ( \PhpParser\Node\Stmt $stmt ) : ? \PhpParser\Node\Expr\Variable
2022-04-28 14:55:01 +00:00
{
2022-06-06 17:12:56 +00:00
if ( ! $stmt instanceof \PhpParser\Node\Stmt\Expression ) {
2022-04-28 14:55:01 +00:00
return null ;
}
2022-06-06 17:12:56 +00:00
if ( ! $stmt -> expr instanceof \PhpParser\Node\Expr\Assign ) {
2022-04-28 14:55:01 +00:00
return null ;
}
$assign = $stmt -> expr ;
if ( ! $this -> valueResolver -> isValue ( $assign -> expr , [])) {
return null ;
}
2022-06-06 17:12:56 +00:00
if ( ! $assign -> var instanceof \PhpParser\Node\Expr\Variable ) {
2022-04-28 14:55:01 +00:00
return null ;
}
return $assign -> var ;
}
2022-06-06 17:12:56 +00:00
private function isReturnOfVariable ( \PhpParser\Node\Stmt $stmt , \PhpParser\Node\Expr\Variable $variable ) : bool
2022-04-28 14:55:01 +00:00
{
2022-06-06 17:12:56 +00:00
if ( ! $stmt instanceof \PhpParser\Node\Stmt\Return_ ) {
2022-04-28 14:55:01 +00:00
return \false ;
}
2022-06-06 17:12:56 +00:00
if ( ! $stmt -> expr instanceof \PhpParser\Node\Expr\Variable ) {
2022-04-28 14:55:01 +00:00
return \false ;
}
return $this -> nodeComparator -> areNodesEqual ( $stmt -> expr , $variable );
}
/**
* @ param KeyAndExpr [] $keysAndExprs
*/
2022-06-06 17:12:56 +00:00
private function createArray ( array $keysAndExprs ) : \PhpParser\Node\Expr\Array_
2022-04-28 14:55:01 +00:00
{
$arrayItems = [];
foreach ( $keysAndExprs as $keyAndExpr ) {
2022-06-06 17:12:56 +00:00
$arrayItem = new \PhpParser\Node\Expr\ArrayItem ( $keyAndExpr -> getExpr (), $keyAndExpr -> getKeyExpr ());
$arrayItem -> setAttribute ( \Rector\NodeTypeResolver\Node\AttributeKey :: COMMENTS , $keyAndExpr -> getComments ());
2022-05-31 07:47:20 +00:00
$arrayItems [] = $arrayItem ;
2022-04-28 14:55:01 +00:00
}
2022-06-06 17:12:56 +00:00
return new \PhpParser\Node\Expr\Array_ ( $arrayItems );
2022-04-28 14:55:01 +00:00
}
}