Skip to content

Commit

Permalink
[Core] Handle no scope crash on foreach value with array item variable (
Browse files Browse the repository at this point in the history
#3068)

* [Core] Handle no scope crash on foreach value with array item variable

* [ci-review] Rector Rectify

* [ci-review] Rector Rectify

* Fixed 🎉

* raname fixture rector

* phpstan

* Final touch: check against exactly ArrayItem

Co-authored-by: GitHub Action <action@github.com>
  • Loading branch information
samsonasik and actions-user committed Nov 16, 2022
1 parent fa9a953 commit 4140e78
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Expr\ArrayItem;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\AssignOp;
Expand Down Expand Up @@ -138,6 +139,13 @@ public function processNodes(
if ($node instanceof Foreach_) {
// decorate value as well
$node->valueVar->setAttribute(AttributeKey::SCOPE, $mutatingScope);
if ($node->valueVar instanceof Array_) {
$this->processArray($node->valueVar, $mutatingScope);
}
}

if ($node instanceof Array_) {
$this->processArray($node, $mutatingScope);
}

if ($node instanceof Property) {
Expand Down Expand Up @@ -219,6 +227,15 @@ public function processNodes(
return $this->processNodesWithDependentFiles($filePath, $stmts, $scope, $nodeCallback);
}

private function processArray(Array_ $array, MutatingScope $mutatingScope): void
{
foreach ($array->items as $arrayItem) {
if ($arrayItem instanceof ArrayItem) {
$arrayItem->setAttribute(AttributeKey::SCOPE, $mutatingScope);
}
}
}

private function processArrayItem(ArrayItem $arrayItem, MutatingScope $mutatingScope): void
{
if ($arrayItem->key instanceof Expr) {
Expand Down
4 changes: 4 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ parameters:
- rules/Php70/EregToPcreTransformer.php
- packages/NodeTypeResolver/NodeTypeResolver.php
- rules/Renaming/NodeManipulator/ClassRenamer.php
- packages/NodeTypeResolver/PHPStan/Scope/PHPStanNodeScopeResolver.php

- "#^Cognitive complexity for \"Rector\\\\Php70\\\\EregToPcreTransformer\\:\\:(.*?)\" is (.*?), keep it under 10$#"
- '#Cognitive complexity for "Rector\\Core\\PhpParser\\Node\\Value\\ValueResolver\:\:getValue\(\)" is \d+, keep it under 10#'
Expand Down Expand Up @@ -816,3 +817,6 @@ parameters:

# not relevant anymore
- '#Instead of "Symfony\\Component\\Finder\\SplFileInfo" class/interface use "Symplify\\SmartFileSystem\\SmartFileInfo"#'

# fixture class
- '#Class "Rector\\Core\\Tests\\Issues\\ScopeNotAvailable\\Variable\\ArrayItemForeachValueRector" is missing @see annotation with test case class reference#'
19 changes: 19 additions & 0 deletions tests/Issues/ScopeNotAvailable/FixtureForeachValue/fixture.php.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace Rector\Core\Tests\Issues\ScopeNotAvailable\Fixture;

class FixtureForeachValue
{
public function run()
{
$value = [
[3, 1, false],
[1, 2, false],
[0, 0, true],
];

foreach ($value as [$a_b, $b_c, $d_e]) {

}
}
}
29 changes: 29 additions & 0 deletions tests/Issues/ScopeNotAvailable/ForeachValueScopeTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);

namespace Rector\Core\Tests\Issues\ScopeNotAvailable;

use Iterator;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;

final class ForeachValueScopeTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(string $filePath): void
{
$this->doTestFile($filePath);
}

public function provideData(): Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/FixtureForeachValue');
}

public function provideConfigFilePath(): string
{
return __DIR__ . '/config/foreach_value_configured.php';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

namespace Rector\Core\Tests\Issues\ScopeNotAvailable\Variable;

use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\Variable;
use PHPStan\Analyser\Scope;
use Rector\Core\Rector\AbstractScopeAwareRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;

final class ArrayItemForeachValueRector extends AbstractScopeAwareRector
{
public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition('Hello!', [new CodeSample('', '')]);
}

/**
* @return array<class-string<Expr>>
*/
public function getNodeTypes(): array
{
return [Variable::class];
}

public function refactorWithScope(Node $node, Scope $scope): Node
{
return $node;
}
}
10 changes: 10 additions & 0 deletions tests/Issues/ScopeNotAvailable/config/foreach_value_configured.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\Core\Tests\Issues\ScopeNotAvailable\Variable\ArrayItemForeachValueRector;

return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rule(ArrayItemForeachValueRector::class);
};

0 comments on commit 4140e78

Please sign in to comment.