> */ private const BREAK_NODES = [\PhpParser\Node\FunctionLike::class, \PhpParser\Node\Stmt\ClassMethod::class]; /** * @var array> */ private const LOOP_NODES = [\PhpParser\Node\Stmt\For_::class, \PhpParser\Node\Stmt\Foreach_::class, \PhpParser\Node\Stmt\While_::class, \PhpParser\Node\Stmt\Do_::class]; /** * @var \Rector\Core\PhpParser\Node\BetterNodeFinder */ private $betterNodeFinder; /** * @var \Rector\NodeTypeResolver\NodeTypeResolver */ private $nodeTypeResolver; /** * @var \Rector\NodeNestingScope\ParentFinder */ private $parentFinder; public function __construct(\Rector\Core\PhpParser\Node\BetterNodeFinder $betterNodeFinder, \Rector\NodeTypeResolver\NodeTypeResolver $nodeTypeResolver, \Rector\NodeNestingScope\ParentFinder $parentFinder) { $this->betterNodeFinder = $betterNodeFinder; $this->nodeTypeResolver = $nodeTypeResolver; $this->parentFinder = $parentFinder; } public function isInLoop(\PhpParser\Node $node) : bool { $stopNodes = \array_merge(self::LOOP_NODES, self::BREAK_NODES); $firstParent = $this->parentFinder->findByTypes($node, $stopNodes); if (!$firstParent instanceof \PhpParser\Node) { return \false; } foreach (self::LOOP_NODES as $type) { if (\is_a($firstParent, $type, \true)) { return \true; } } return \false; } public function isInSwitch(\PhpParser\Node $node) : bool { return (bool) $this->betterNodeFinder->findParentType($node, \PhpParser\Node\Stmt\Switch_::class); } public function isInIf(\PhpParser\Node $node) : bool { $breakNodes = \array_merge([\PhpParser\Node\Stmt\If_::class], self::BREAK_NODES); $previousNode = $this->parentFinder->findByTypes($node, $breakNodes); if (!$previousNode instanceof \PhpParser\Node) { return \false; } return $previousNode instanceof \PhpParser\Node\Stmt\If_; } public function isHasAssignWithIndirectReturn(\PhpParser\Node $node, \PhpParser\Node\Stmt\If_ $if) : bool { $loopNodes = self::LOOP_NODES; foreach ($loopNodes as $loopNode) { $loopObjectType = new \PHPStan\Type\ObjectType($loopNode); $parentType = $this->nodeTypeResolver->getType($node); $superType = $parentType->isSuperTypeOf($loopObjectType); $isLoopType = $superType->yes(); if (!$isLoopType) { continue; } $next = $node->getAttribute(\Rector\NodeTypeResolver\Node\AttributeKey::NEXT_NODE); if ($next instanceof \PhpParser\Node) { if ($next instanceof \PhpParser\Node\Stmt\Return_ && $next->expr === null) { continue; } $hasAssign = (bool) $this->betterNodeFinder->findInstanceOf($if->stmts, \PhpParser\Node\Expr\Assign::class); if (!$hasAssign) { continue; } return \true; } } return \false; } }