rector/packages/NodeNestingScope/NodeFinder/ScopeAwareNodeFinder.php

68 lines
2.4 KiB
PHP
Raw Normal View History

2020-04-01 03:55:44 +02:00
<?php
declare (strict_types=1);
2020-04-01 03:55:44 +02:00
namespace Rector\NodeNestingScope\NodeFinder;
use PhpParser\Node;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\NodeNestingScope\ValueObject\ControlStructure;
final class ScopeAwareNodeFinder
{
/**
* @var bool
2020-04-01 03:55:44 +02:00
*/
private $isBreakingNodeFoundFirst = \false;
2020-04-01 03:55:44 +02:00
/**
* @var \Rector\Core\PhpParser\Node\BetterNodeFinder
2020-04-01 03:55:44 +02:00
*/
private $betterNodeFinder;
public function __construct(\Rector\Core\PhpParser\Node\BetterNodeFinder $betterNodeFinder)
2020-04-01 03:55:44 +02:00
{
$this->betterNodeFinder = $betterNodeFinder;
}
/**
* Find node based on $callable or null, when the nesting scope is broken
2021-03-21 19:41:17 +01:00
* @param array<class-string<Node>> $allowedTypes
*/
public function findParentType(\PhpParser\Node $node, array $allowedTypes) : ?\PhpParser\Node
{
$callable = function (\PhpParser\Node $node) use($allowedTypes) : bool {
foreach ($allowedTypes as $allowedType) {
if (!\is_a($node, $allowedType)) {
continue;
}
return \true;
}
return \false;
};
return $this->findParent($node, $callable, $allowedTypes);
}
2020-04-01 03:55:44 +02:00
/**
* Find node based on $callable or null, when the nesting scope is broken
2021-03-22 00:07:40 +01:00
* @param array<class-string<Node>> $allowedTypes
2020-04-01 03:55:44 +02:00
*/
public function findParent(\PhpParser\Node $node, callable $callable, array $allowedTypes) : ?\PhpParser\Node
2020-04-01 03:55:44 +02:00
{
2021-03-22 00:07:40 +01:00
/** @var array<class-string<Node>> $parentNestingBreakTypes */
$parentNestingBreakTypes = \array_diff(\Rector\NodeNestingScope\ValueObject\ControlStructure::BREAKING_SCOPE_NODE_TYPES, $allowedTypes);
$this->isBreakingNodeFoundFirst = \false;
$foundNode = $this->betterNodeFinder->findFirstPrevious($node, function (\PhpParser\Node $node) use($callable, $parentNestingBreakTypes) : bool {
2020-04-01 03:55:44 +02:00
if ($callable($node)) {
return \true;
2020-04-01 03:55:44 +02:00
}
foreach ($parentNestingBreakTypes as $parentNestingBreakType) {
if (!\is_a($node, $parentNestingBreakType, \true)) {
2021-01-23 00:11:10 +01:00
continue;
2020-04-01 03:55:44 +02:00
}
$this->isBreakingNodeFoundFirst = \true;
return \true;
2020-04-01 03:55:44 +02:00
}
return \false;
2020-04-01 03:55:44 +02:00
});
if ($this->isBreakingNodeFoundFirst) {
return null;
}
return $foundNode;
}
}