Fix scope overflow in AddDefaultValueForUndefinedVariableRector (#1557)

Fix scope overflow in AddDefaultValueForUndefinedVariableRector
This commit is contained in:
Tomáš Votruba 2019-06-04 16:39:30 +03:00 committed by GitHub
commit ae833f1e82
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 45 additions and 20 deletions

View File

@ -0,0 +1,6 @@
/**
* Stage constructor.
*
* @param string $stage
* @param boolean $undefined Should the object be undefined?
*/

View File

@ -67,6 +67,7 @@ final class PhpDocInfoPrinterTest extends AbstractKernelTestCase
yield [__DIR__ . '/PhpDocInfoPrinterSource/doc12.txt'];
yield [__DIR__ . '/PhpDocInfoPrinterSource/doc13.txt'];
yield [__DIR__ . '/PhpDocInfoPrinterSource/doc14.txt'];
yield [__DIR__ . '/PhpDocInfoPrinterSource/doc15.txt'];
}
public function provideMultiline(): Iterator

View File

@ -0,0 +1,9 @@
<?php declare(strict_types=1);
namespace Rector\Php\Exception;
use Exception;
final class BreakScopeException extends Exception
{
}

View File

@ -15,6 +15,7 @@ use PhpParser\Node\Stmt\StaticVar;
use PhpParser\Node\Stmt\Unset_;
use PHPStan\Analyser\Scope;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\Php\Exception\BreakScopeException;
use Rector\PhpParser\NodeTraverser\CallableNodeTraverser;
use Rector\Rector\AbstractRector;
use Rector\RectorDefinition\CodeSample;
@ -90,30 +91,38 @@ CODE_SAMPLE
{
$this->undefinedVariables = [];
$this->callableNodeTraverser->traverseNodesWithCallable((array) $node->stmts, function (Node $node) {
if (! $node instanceof Variable) {
return null;
}
try {
$this->callableNodeTraverser->traverseNodesWithCallable((array) $node->stmts, function (Node $node) {
// entering new scope - break!
if ($node instanceof FunctionLike) {
throw new BreakScopeException();
}
if ($this->shouldSkipVariable($node)) {
return null;
}
if (! $node instanceof Variable) {
return null;
}
$variableName = $this->getName($node);
if ($variableName === null) {
return null;
}
if ($this->shouldSkipVariable($node)) {
return null;
}
// defined 100 %
/** @var Scope $nodeScope */
$nodeScope = $node->getAttribute(AttributeKey::SCOPE);
if ($nodeScope->hasVariableType($variableName)->yes()) {
return null;
}
$variableName = $this->getName($node);
if ($variableName === null) {
return null;
}
// @todo improve
$this->undefinedVariables[] = $variableName;
});
// defined 100 %
/** @var Scope $nodeScope */
$nodeScope = $node->getAttribute(AttributeKey::SCOPE);
if ($nodeScope->hasVariableType($variableName)->yes()) {
return null;
}
$this->undefinedVariables[] = $variableName;
});
} catch (BreakScopeException $breakScopeException) {
// nothing
}
if ($this->undefinedVariables === []) {
return null;