Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -338,3 +338,7 @@ parameters:
-
message: '#Offset float\|int\|string might not exist on string#'
path: rules/Php70/EregToPcreTransformer.php

-
identifier: symplify.noReference
message: '#Use explicit return value over magic &reference#'
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@

namespace Rector\Tests\CodeQuality\Rector\ClassMethod\InlineArrayReturnAssignRector\Fixture;

final class KeepComments
final class IncludeEmptyAssign
{
public function getPerson()
public function run($person2)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when param named $person sshould be skipped

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed 👍 Could you handle it? I'm off soon

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will check if any regression if conflict with existing params

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{
$person = [];
// name
$person['name'] = 'Timmy';
// surname

$person[] = 'Timmy';
$person['surname'] = 'Back';

return $person;
Expand All @@ -22,16 +21,11 @@ final class KeepComments

namespace Rector\Tests\CodeQuality\Rector\ClassMethod\InlineArrayReturnAssignRector\Fixture;

final class KeepComments
final class IncludeEmptyAssign
{
public function getPerson()
public function run($person2)
{
return [
// name
'name' => 'Timmy',
// surname
'surname' => 'Back',
];
return ['Timmy', 'surname' => 'Back'];
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace Rector\Tests\CodeQuality\Rector\ClassMethod\InlineArrayReturnAssignRector\Fixture;

final class IncludeNestedVariable
{
public function create()
{
$items[0]['name'] = 'John';
$items[0]['surname'] = 'Doe';
$items[0]['age'] = 50;
return $items;
}
}

?>
-----
<?php

namespace Rector\Tests\CodeQuality\Rector\ClassMethod\InlineArrayReturnAssignRector\Fixture;

final class IncludeNestedVariable
{
public function create()
{
return [['name' => 'John', 'surname' => 'Doe', 'age' => 50]];
}
}

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

namespace Rector\Tests\CodeQuality\Rector\ClassMethod\InlineArrayReturnAssignRector\Fixture;

final class NestedArrayWithMultipleKeys
{
public function run()
{
$arr = [];
$arr['foo']['bar']['baz'] = ['a' => 1, 'b' => 2];

return $arr;
}
}


?>
-----
<?php

namespace Rector\Tests\CodeQuality\Rector\ClassMethod\InlineArrayReturnAssignRector\Fixture;

final class NestedArrayWithMultipleKeys
{
public function run()
{
return ['foo' => ['bar' => ['baz' => ['a' => 1, 'b' => 2]]]];
}
}


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

namespace Rector\Tests\CodeQuality\Rector\ClassMethod\InlineArrayReturnAssignRector\Fixture;

final class SkipDifferentVariable
{
public function create()
{
$item['sub_key'] = 500;

$items['name'] = 'John';
$items['surname'] = 'Doe';
$items['age'] = $item;

return $items;
}
}

This file was deleted.

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

namespace Rector\Tests\CodeQuality\Rector\ClassMethod\InlineArrayReturnAssignRector\Fixture;

final class SkipMultipleReturns
{
public function create()
{
$items['name'] = 'John';
$items['surname'] = 'Doe';
$items['age'] = 50;

if (mt_rand(1, 2)) {
return [];
}

return $items;
}
}

This file was deleted.

This file was deleted.

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

namespace Rector\Tests\CodeQuality\Rector\ClassMethod\InlineArrayReturnAssignRector\Fixture;

class SomeClass
{
public function create()
{
$items['name'] = 'John';
$items['surname'] = 'Doe';
$items['age'] = 50;
return $items;
}
}

?>
-----
<?php

namespace Rector\Tests\CodeQuality\Rector\ClassMethod\InlineArrayReturnAssignRector\Fixture;

class SomeClass
{
public function create()
{
return ['name' => 'John', 'surname' => 'Doe', 'age' => 50];
}
}

?>
93 changes: 37 additions & 56 deletions rules/CodeQuality/NodeAnalyzer/VariableDimFetchAssignResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,41 @@

namespace Rector\CodeQuality\NodeAnalyzer;

use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\ArrayDimFetch;
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\ValueObject\KeyAndExpr;
use Rector\PhpParser\Comparing\NodeComparator;
use Rector\PhpParser\Node\BetterNodeFinder;
use Rector\PhpParser\Node\Value\ValueResolver;

final readonly class VariableDimFetchAssignResolver
{
public function __construct(
private NodeComparator $nodeComparator,
private BetterNodeFinder $betterNodeFinder
private ValueResolver $valueResolver
) {
}

/**
* @param Stmt[] $stmts
* @return KeyAndExpr[]
* @return array<mixed, KeyAndExpr[]>
*/
public function resolveFromStmtsAndVariable(array $stmts, Variable $variable): array
public function resolveFromStmtsAndVariable(array $stmts, ?Assign $emptyArrayAssign): array
{
$keysAndExprs = [];
$exprs = [];

$key = 0;

foreach ($stmts as $stmt) {
if ($stmt instanceof Expression && $stmt->expr === $emptyArrayAssign) {
continue;
}

if ($stmt instanceof Return_) {
continue;
}

if (! $stmt instanceof Expression) {
return [];
}
Expand All @@ -43,66 +50,40 @@ public function resolveFromStmtsAndVariable(array $stmts, Variable $variable): a

$assign = $stmtExpr;

$keyExpr = $this->matchKeyOnArrayDimFetchOfVariable($assign, $variable);
if ($assign->var instanceof ArrayDimFetch && $assign->var->var instanceof ArrayDimFetch) {
return [];
}

$keysAndExprs[] = new KeyAndExpr($keyExpr, $assign->expr, $stmt->getComments());
}

// we can only work with same variable
// and exclusively various keys or empty keys
if (! $this->hasExclusivelyNullKeyOrFilledKey($keysAndExprs)) {
return [];
}

return $keysAndExprs;
}
$dimValues = [];

private function matchKeyOnArrayDimFetchOfVariable(Assign $assign, Variable $variable): ?Expr
{
if (! $assign->var instanceof ArrayDimFetch) {
return null;
}
$arrayDimFetch = $assign->var;
while ($arrayDimFetch instanceof ArrayDimFetch) {
$dimValues[] = $arrayDimFetch->dim instanceof Expr ? $this->valueResolver->getValue(
$arrayDimFetch->dim
) : $key;

$arrayDimFetch = $assign->var;
if (! $this->nodeComparator->areNodesEqual($arrayDimFetch->var, $variable)) {
return null;
}
$arrayDimFetch = $arrayDimFetch->var;
}

$isFoundInExpr = (bool) $this->betterNodeFinder->findFirst(
$assign->expr,
fn (Node $subNode): bool => $this->nodeComparator->areNodesEqual($subNode, $variable)
);
++$key;

if ($isFoundInExpr) {
return null;
$this->setNestedKeysExpr($exprs, $dimValues, $assign->expr);
}

return $arrayDimFetch->dim;
return $exprs;
}

/**
* @param KeyAndExpr[] $keysAndExprs
* @param mixed[] $exprsByKeys
* @param array<string|int> $keys
*/
private function hasExclusivelyNullKeyOrFilledKey(array $keysAndExprs): bool
private function setNestedKeysExpr(array &$exprsByKeys, array $keys, Expr $expr): void
{
$alwaysNullKey = true;
$alwaysStringKey = true;

foreach ($keysAndExprs as $keyAndExpr) {
if ($keyAndExpr->getKeyExpr() instanceof Expr) {
$alwaysNullKey = false;
} else {
$alwaysStringKey = false;
}
}
$reference = &$exprsByKeys;

$keys = array_reverse($keys);

if ($alwaysNullKey) {
return true;
foreach ($keys as $key) {
// create intermediate arrays automatically
$reference = &$reference[$key];
}

return $alwaysStringKey;
$reference = $expr;
}
}
Loading
Loading