mirror of
https://github.com/rectorphp/rector.git
synced 2025-01-29 19:37:55 +01:00
Updated Rector to commit 6758a5e892acaf241b1c2afaea117a6c69df15f0
6758a5e892
[Php56] Remove parent attribute usage on UndefinedVariableResolver (#4147)
This commit is contained in:
parent
2886ec2c81
commit
04e769bf65
@ -5,8 +5,8 @@ namespace Rector\Php56\NodeAnalyzer;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\Array_;
|
||||
use PhpParser\Node\Expr\ArrayItem;
|
||||
use PhpParser\Node\Expr\ArrowFunction;
|
||||
use PhpParser\Node\Expr\Assign;
|
||||
use PhpParser\Node\Expr\AssignOp\Coalesce as AssignOpCoalesce;
|
||||
use PhpParser\Node\Expr\AssignRef;
|
||||
use PhpParser\Node\Expr\BinaryOp\Coalesce;
|
||||
@ -22,7 +22,6 @@ use PhpParser\Node\Stmt\Case_;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PhpParser\Node\Stmt\Foreach_;
|
||||
use PhpParser\Node\Stmt\Function_;
|
||||
use PhpParser\Node\Stmt\Switch_;
|
||||
use PhpParser\Node\Stmt\Unset_;
|
||||
use PhpParser\NodeTraverser;
|
||||
use PHPStan\Analyser\Scope;
|
||||
@ -84,15 +83,18 @@ final class UndefinedVariableResolver
|
||||
// handled above
|
||||
return NodeTraverser::DONT_TRAVERSE_CURRENT_AND_CHILDREN;
|
||||
}
|
||||
$checkedVariables = $this->resolveCheckedVariables($node, $checkedVariables);
|
||||
if ($node instanceof Case_) {
|
||||
return NodeTraverser::DONT_TRAVERSE_CURRENT_AND_CHILDREN;
|
||||
}
|
||||
if (!$node instanceof Variable) {
|
||||
return null;
|
||||
}
|
||||
$parentNode = $node->getAttribute(AttributeKey::PARENT_NODE);
|
||||
if (!$parentNode instanceof Node) {
|
||||
if ($node->getAttribute(AttributeKey::IS_BEING_ASSIGNED) === \true) {
|
||||
return null;
|
||||
}
|
||||
$variableName = (string) $this->nodeNameResolver->getName($node);
|
||||
if ($this->shouldSkipVariable($node, $variableName, $checkedVariables, $parentNode)) {
|
||||
if ($this->shouldSkipVariable($node, $variableName, $checkedVariables)) {
|
||||
return null;
|
||||
}
|
||||
if ($this->hasVariableTypeOrCurrentStmtUnreachable($node, $variableName)) {
|
||||
@ -104,6 +106,70 @@ final class UndefinedVariableResolver
|
||||
});
|
||||
return \array_unique($undefinedVariables);
|
||||
}
|
||||
/**
|
||||
* @param string[] $checkedVariables
|
||||
* @return string[]
|
||||
*/
|
||||
private function resolveCheckedVariables(Node $node, array $checkedVariables) : array
|
||||
{
|
||||
if ($node instanceof Empty_ && $node->expr instanceof Variable) {
|
||||
$checkedVariables[] = (string) $this->nodeNameResolver->getName($node->expr);
|
||||
return $checkedVariables;
|
||||
}
|
||||
if ($node instanceof Isset_ || $node instanceof Unset_) {
|
||||
return $this->resolveCheckedVariablesFromIssetOrUnset($node, $checkedVariables);
|
||||
}
|
||||
if ($node instanceof UnsetCast && $node->expr instanceof Variable) {
|
||||
$checkedVariables[] = (string) $this->nodeNameResolver->getName($node->expr);
|
||||
return $checkedVariables;
|
||||
}
|
||||
if ($node instanceof Coalesce && $node->left instanceof Variable) {
|
||||
$checkedVariables[] = (string) $this->nodeNameResolver->getName($node->left);
|
||||
return $checkedVariables;
|
||||
}
|
||||
if ($node instanceof AssignOpCoalesce && $node->var instanceof Variable) {
|
||||
$checkedVariables[] = (string) $this->nodeNameResolver->getName($node->var);
|
||||
return $checkedVariables;
|
||||
}
|
||||
if ($node instanceof AssignRef && $node->var instanceof Variable) {
|
||||
$checkedVariables[] = (string) $this->nodeNameResolver->getName($node->var);
|
||||
}
|
||||
return $this->resolveCheckedVariablesFromArrayOrList($node, $checkedVariables);
|
||||
}
|
||||
/**
|
||||
* @param string[] $checkedVariables
|
||||
* @return string[]
|
||||
* @param \PhpParser\Node\Expr\Isset_|\PhpParser\Node\Stmt\Unset_ $node
|
||||
*/
|
||||
private function resolveCheckedVariablesFromIssetOrUnset($node, array $checkedVariables) : array
|
||||
{
|
||||
foreach ($node->vars as $expr) {
|
||||
if ($expr instanceof Variable) {
|
||||
$checkedVariables[] = (string) $this->nodeNameResolver->getName($expr);
|
||||
}
|
||||
}
|
||||
return $checkedVariables;
|
||||
}
|
||||
/**
|
||||
* @param string[] $checkedVariables
|
||||
* @return string[]
|
||||
*/
|
||||
private function resolveCheckedVariablesFromArrayOrList(Node $node, array $checkedVariables) : array
|
||||
{
|
||||
if (!$node instanceof Array_ && !$node instanceof List_) {
|
||||
return $checkedVariables;
|
||||
}
|
||||
foreach ($node->items as $item) {
|
||||
if (!$item instanceof ArrayItem) {
|
||||
continue;
|
||||
}
|
||||
if (!$item->value instanceof Variable) {
|
||||
continue;
|
||||
}
|
||||
$checkedVariables[] = (string) $this->nodeNameResolver->getName($item->value);
|
||||
}
|
||||
return $checkedVariables;
|
||||
}
|
||||
private function hasVariableTypeOrCurrentStmtUnreachable(Variable $variable, ?string $variableName) : bool
|
||||
{
|
||||
if (!\is_string($variableName)) {
|
||||
@ -118,47 +184,11 @@ final class UndefinedVariableResolver
|
||||
$currentStmt = $this->betterNodeFinder->resolveCurrentStatement($variable);
|
||||
return $currentStmt instanceof Stmt && $currentStmt->getAttribute(AttributeKey::IS_UNREACHABLE) === \true;
|
||||
}
|
||||
private function shouldSkipWithParent(Node $parentNode) : bool
|
||||
{
|
||||
if (\in_array(\get_class($parentNode), [Unset_::class, UnsetCast::class, Isset_::class, Empty_::class], \true)) {
|
||||
return \true;
|
||||
}
|
||||
// when parent Node origNode is null, it means parent Node just reprinted, so it can't be verified
|
||||
// so skip it
|
||||
return !$parentNode->getAttribute(AttributeKey::ORIGINAL_NODE) instanceof Node;
|
||||
}
|
||||
private function isAsCoalesceLeftOrAssignOpCoalesceVar(Node $parentNode, Variable $variable) : bool
|
||||
{
|
||||
if ($parentNode instanceof Coalesce && $parentNode->left === $variable) {
|
||||
return \true;
|
||||
}
|
||||
if (!$parentNode instanceof AssignOpCoalesce) {
|
||||
return \false;
|
||||
}
|
||||
return $parentNode->var === $variable;
|
||||
}
|
||||
private function isAssign(Node $parentNode) : bool
|
||||
{
|
||||
return \in_array(\get_class($parentNode), [Assign::class, AssignRef::class], \true);
|
||||
}
|
||||
/**
|
||||
* @param string[] $checkedVariables
|
||||
*/
|
||||
private function shouldSkipVariable(Variable $variable, string $variableName, array &$checkedVariables, Node $parentNode) : bool
|
||||
private function shouldSkipVariable(Variable $variable, string $variableName, array &$checkedVariables) : bool
|
||||
{
|
||||
if ($this->isAsCoalesceLeftOrAssignOpCoalesceVar($parentNode, $variable)) {
|
||||
return \true;
|
||||
}
|
||||
if ($this->isAssign($parentNode)) {
|
||||
return \true;
|
||||
}
|
||||
if ($this->shouldSkipWithParent($parentNode)) {
|
||||
return \true;
|
||||
}
|
||||
// list() = | [$values] = defines variables as null
|
||||
if ($this->isListAssign($parentNode)) {
|
||||
return \true;
|
||||
}
|
||||
$variableName = $this->nodeNameResolver->getName($variable);
|
||||
// skip $this, as probably in outer scope
|
||||
if ($variableName === 'this') {
|
||||
@ -173,26 +203,10 @@ final class UndefinedVariableResolver
|
||||
if ($this->variableAnalyzer->isStaticOrGlobal($variable)) {
|
||||
return \true;
|
||||
}
|
||||
if (\in_array($variableName, $checkedVariables, \true)) {
|
||||
return \true;
|
||||
}
|
||||
$checkedVariables[] = $variableName;
|
||||
if ($this->hasPreviousCheckedWithIsset($variable)) {
|
||||
return \true;
|
||||
}
|
||||
if ($this->hasPreviousCheckedWithEmpty($variable)) {
|
||||
return \true;
|
||||
}
|
||||
return $this->isAfterSwitchCaseWithParentCase($variable);
|
||||
}
|
||||
private function isAfterSwitchCaseWithParentCase(Variable $variable) : bool
|
||||
{
|
||||
$previousSwitch = $this->betterNodeFinder->findFirstPreviousOfTypes($variable, [Switch_::class]);
|
||||
if (!$previousSwitch instanceof Switch_) {
|
||||
return \false;
|
||||
}
|
||||
$parentNode = $previousSwitch->getAttribute(AttributeKey::PARENT_NODE);
|
||||
return $parentNode instanceof Case_;
|
||||
$checkedVariables = \array_filter($checkedVariables, static function (string $variableName) : bool {
|
||||
return $variableName !== '';
|
||||
});
|
||||
return \in_array($variableName, $checkedVariables, \true);
|
||||
}
|
||||
private function isDifferentWithOriginalNodeOrNoScope(Variable $variable) : bool
|
||||
{
|
||||
@ -203,37 +217,4 @@ final class UndefinedVariableResolver
|
||||
$nodeScope = $variable->getAttribute(AttributeKey::SCOPE);
|
||||
return !$nodeScope instanceof Scope;
|
||||
}
|
||||
private function hasPreviousCheckedWithIsset(Variable $variable) : bool
|
||||
{
|
||||
return (bool) $this->betterNodeFinder->findFirstPrevious($variable, function (Node $subNode) use($variable) : bool {
|
||||
if (!$subNode instanceof Isset_) {
|
||||
return \false;
|
||||
}
|
||||
$vars = $subNode->vars;
|
||||
foreach ($vars as $var) {
|
||||
if ($this->nodeComparator->areNodesEqual($variable, $var)) {
|
||||
return \true;
|
||||
}
|
||||
}
|
||||
return \false;
|
||||
});
|
||||
}
|
||||
private function hasPreviousCheckedWithEmpty(Variable $variable) : bool
|
||||
{
|
||||
return (bool) $this->betterNodeFinder->findFirstPrevious($variable, function (Node $subNode) use($variable) : bool {
|
||||
if (!$subNode instanceof Empty_) {
|
||||
return \false;
|
||||
}
|
||||
$subNodeExpr = $subNode->expr;
|
||||
return $this->nodeComparator->areNodesEqual($subNodeExpr, $variable);
|
||||
});
|
||||
}
|
||||
private function isListAssign(Node $node) : bool
|
||||
{
|
||||
$parentNode = $node->getAttribute(AttributeKey::PARENT_NODE);
|
||||
if ($parentNode instanceof List_) {
|
||||
return \true;
|
||||
}
|
||||
return $parentNode instanceof Array_;
|
||||
}
|
||||
}
|
||||
|
@ -19,12 +19,12 @@ final class VersionResolver
|
||||
* @api
|
||||
* @var string
|
||||
*/
|
||||
public const PACKAGE_VERSION = '5ba083c88dc02a30a03ecb2fc5925caa2d2f88c0';
|
||||
public const PACKAGE_VERSION = '6758a5e892acaf241b1c2afaea117a6c69df15f0';
|
||||
/**
|
||||
* @api
|
||||
* @var string
|
||||
*/
|
||||
public const RELEASE_DATE = '2023-06-09 17:38:50';
|
||||
public const RELEASE_DATE = '2023-06-10 02:51:07';
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
|
2
vendor/autoload.php
vendored
2
vendor/autoload.php
vendored
@ -22,4 +22,4 @@ if (PHP_VERSION_ID < 50600) {
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInit2edf4d8676de5cd836c60932d2e70c25::getLoader();
|
||||
return ComposerAutoloaderInit3847fecbeceb295061c4d9ca7f51789f::getLoader();
|
||||
|
10
vendor/composer/autoload_real.php
vendored
10
vendor/composer/autoload_real.php
vendored
@ -2,7 +2,7 @@
|
||||
|
||||
// autoload_real.php @generated by Composer
|
||||
|
||||
class ComposerAutoloaderInit2edf4d8676de5cd836c60932d2e70c25
|
||||
class ComposerAutoloaderInit3847fecbeceb295061c4d9ca7f51789f
|
||||
{
|
||||
private static $loader;
|
||||
|
||||
@ -22,17 +22,17 @@ class ComposerAutoloaderInit2edf4d8676de5cd836c60932d2e70c25
|
||||
return self::$loader;
|
||||
}
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInit2edf4d8676de5cd836c60932d2e70c25', 'loadClassLoader'), true, true);
|
||||
spl_autoload_register(array('ComposerAutoloaderInit3847fecbeceb295061c4d9ca7f51789f', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInit2edf4d8676de5cd836c60932d2e70c25', 'loadClassLoader'));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInit3847fecbeceb295061c4d9ca7f51789f', 'loadClassLoader'));
|
||||
|
||||
require __DIR__ . '/autoload_static.php';
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInit2edf4d8676de5cd836c60932d2e70c25::getInitializer($loader));
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInit3847fecbeceb295061c4d9ca7f51789f::getInitializer($loader));
|
||||
|
||||
$loader->setClassMapAuthoritative(true);
|
||||
$loader->register(true);
|
||||
|
||||
$filesToLoad = \Composer\Autoload\ComposerStaticInit2edf4d8676de5cd836c60932d2e70c25::$files;
|
||||
$filesToLoad = \Composer\Autoload\ComposerStaticInit3847fecbeceb295061c4d9ca7f51789f::$files;
|
||||
$requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
|
||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||
|
8
vendor/composer/autoload_static.php
vendored
8
vendor/composer/autoload_static.php
vendored
@ -4,7 +4,7 @@
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
class ComposerStaticInit2edf4d8676de5cd836c60932d2e70c25
|
||||
class ComposerStaticInit3847fecbeceb295061c4d9ca7f51789f
|
||||
{
|
||||
public static $files = array (
|
||||
'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php',
|
||||
@ -3128,9 +3128,9 @@ class ComposerStaticInit2edf4d8676de5cd836c60932d2e70c25
|
||||
public static function getInitializer(ClassLoader $loader)
|
||||
{
|
||||
return \Closure::bind(function () use ($loader) {
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInit2edf4d8676de5cd836c60932d2e70c25::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInit2edf4d8676de5cd836c60932d2e70c25::$prefixDirsPsr4;
|
||||
$loader->classMap = ComposerStaticInit2edf4d8676de5cd836c60932d2e70c25::$classMap;
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInit3847fecbeceb295061c4d9ca7f51789f::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInit3847fecbeceb295061c4d9ca7f51789f::$prefixDirsPsr4;
|
||||
$loader->classMap = ComposerStaticInit3847fecbeceb295061c4d9ca7f51789f::$classMap;
|
||||
|
||||
}, null, ClassLoader::class);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user