2019-10-13 05:59:52 +00:00
< ? php
2021-05-09 20:15:43 +00:00
declare ( strict_types = 1 );
2020-02-06 21:48:18 +00:00
namespace Rector\Core\Rector ;
2017-08-07 15:27:04 +00:00
2021-03-03 21:28:27 +00:00
use PhpParser\Node ;
use PhpParser\Node\Arg ;
use PhpParser\Node\Expr ;
use PhpParser\Node\Stmt ;
use PhpParser\Node\Stmt\Class_ ;
use PhpParser\Node\Stmt\ClassMethod ;
use PhpParser\Node\Stmt\Expression ;
use PhpParser\Node\Stmt\Function_ ;
2021-04-08 12:44:26 +00:00
use PhpParser\NodeTraverser ;
use PhpParser\NodeVisitor\ParentConnectingVisitor ;
2021-03-03 21:28:27 +00:00
use PhpParser\NodeVisitorAbstract ;
use PHPStan\Type\ObjectType ;
use PHPStan\Type\Type ;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory ;
2021-04-22 21:51:32 +00:00
use Rector\ChangesReporting\ValueObject\RectorWithLineChange ;
2021-03-03 21:28:27 +00:00
use Rector\Core\Application\FileSystem\RemovedAndAddedFilesCollector ;
use Rector\Core\Configuration\CurrentNodeProvider ;
2022-02-11 12:13:24 +00:00
use Rector\Core\Contract\Console\OutputStyleInterface ;
2021-03-03 21:28:27 +00:00
use Rector\Core\Contract\Rector\PhpRectorInterface ;
2021-04-13 00:12:48 +00:00
use Rector\Core\Exception\ShouldNotHappenException ;
2021-03-03 21:28:27 +00:00
use Rector\Core\Exclusion\ExclusionManager ;
use Rector\Core\Logging\CurrentRectorProvider ;
2021-12-31 10:33:05 +00:00
use Rector\Core\NodeDecorator\CreatedByRuleDecorator ;
2021-03-03 21:28:27 +00:00
use Rector\Core\Php\PhpVersionProvider ;
use Rector\Core\PhpParser\Comparing\NodeComparator ;
use Rector\Core\PhpParser\Node\BetterNodeFinder ;
use Rector\Core\PhpParser\Node\NodeFactory ;
use Rector\Core\PhpParser\Node\Value\ValueResolver ;
use Rector\Core\PhpParser\Printer\BetterStandardPrinter ;
2021-10-18 19:19:09 +00:00
use Rector\Core\ProcessAnalyzer\RectifiedAnalyzer ;
2021-04-13 00:12:48 +00:00
use Rector\Core\Provider\CurrentFileProvider ;
use Rector\Core\ValueObject\Application\File ;
2021-10-18 19:19:09 +00:00
use Rector\Core\ValueObject\RectifiedNode ;
2021-03-03 21:28:27 +00:00
use Rector\NodeNameResolver\NodeNameResolver ;
use Rector\NodeRemoval\NodeRemover ;
use Rector\NodeTypeResolver\Node\AttributeKey ;
use Rector\NodeTypeResolver\NodeTypeResolver ;
use Rector\PostRector\Collector\NodesToAddCollector ;
use Rector\PostRector\Collector\NodesToRemoveCollector ;
use Rector\StaticTypeMapper\StaticTypeMapper ;
2022-02-27 00:40:38 +00:00
use RectorPrefix20220227\Symfony\Contracts\Service\Attribute\Required ;
use RectorPrefix20220227\Symplify\Astral\NodeTraverser\SimpleCallableNodeTraverser ;
use RectorPrefix20220227\Symplify\PackageBuilder\Parameter\ParameterProvider ;
use RectorPrefix20220227\Symplify\Skipper\Skipper\Skipper ;
2021-02-28 07:47:48 +00:00
/**
* @ see \Rector\Testing\PHPUnit\AbstractRectorTestCase
*/
2021-05-10 22:23:08 +00:00
abstract class AbstractRector extends \PhpParser\NodeVisitorAbstract implements \Rector\Core\Contract\Rector\PhpRectorInterface
2017-08-07 15:27:04 +00:00
{
2021-03-03 21:28:27 +00:00
/**
* @ var string []
*/
2021-11-07 04:15:35 +00:00
private const ATTRIBUTES_TO_MIRROR = [ \Rector\NodeTypeResolver\Node\AttributeKey :: USE_NODES , \Rector\NodeTypeResolver\Node\AttributeKey :: SCOPE , \Rector\NodeTypeResolver\Node\AttributeKey :: RESOLVED_NAME , \Rector\NodeTypeResolver\Node\AttributeKey :: PARENT_NODE , \Rector\NodeTypeResolver\Node\AttributeKey :: CURRENT_STATEMENT , \Rector\NodeTypeResolver\Node\AttributeKey :: PREVIOUS_STATEMENT ];
2021-03-03 21:28:27 +00:00
/**
2021-05-12 13:15:45 +00:00
* @ var \Rector\NodeNameResolver\NodeNameResolver
2021-03-03 21:28:27 +00:00
*/
protected $nodeNameResolver ;
/**
2021-05-12 13:15:45 +00:00
* @ var \Rector\NodeTypeResolver\NodeTypeResolver
2021-03-03 21:28:27 +00:00
*/
protected $nodeTypeResolver ;
/**
2021-05-12 13:15:45 +00:00
* @ var \Rector\Core\PhpParser\Printer\BetterStandardPrinter
2021-03-03 21:28:27 +00:00
*/
protected $betterStandardPrinter ;
/**
2021-05-12 13:15:45 +00:00
* @ var \Rector\Core\Application\FileSystem\RemovedAndAddedFilesCollector
2021-03-03 21:28:27 +00:00
*/
protected $removedAndAddedFilesCollector ;
/**
2021-08-23 00:20:32 +00:00
* @ var \Symplify\PackageBuilder\Parameter\ParameterProvider
2021-03-03 21:28:27 +00:00
*/
protected $parameterProvider ;
/**
2021-05-12 13:15:45 +00:00
* @ var \Rector\Core\Php\PhpVersionProvider
2021-03-03 21:28:27 +00:00
*/
protected $phpVersionProvider ;
/**
2021-05-12 13:15:45 +00:00
* @ var \Rector\StaticTypeMapper\StaticTypeMapper
2021-03-03 21:28:27 +00:00
*/
protected $staticTypeMapper ;
/**
2021-05-12 13:15:45 +00:00
* @ var \Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory
2021-03-03 21:28:27 +00:00
*/
protected $phpDocInfoFactory ;
/**
2021-05-12 13:15:45 +00:00
* @ var \Rector\Core\PhpParser\Node\NodeFactory
2021-03-03 21:28:27 +00:00
*/
protected $nodeFactory ;
/**
2021-05-12 13:15:45 +00:00
* @ var \Rector\Core\PhpParser\Node\Value\ValueResolver
2021-03-03 21:28:27 +00:00
*/
protected $valueResolver ;
/**
2021-05-12 13:15:45 +00:00
* @ var \Rector\Core\PhpParser\Node\BetterNodeFinder
2021-03-03 21:28:27 +00:00
*/
protected $betterNodeFinder ;
/**
2021-05-12 13:15:45 +00:00
* @ var \Rector\NodeRemoval\NodeRemover
2021-03-03 21:28:27 +00:00
*/
protected $nodeRemover ;
/**
2021-05-12 13:15:45 +00:00
* @ var \Rector\Core\PhpParser\Comparing\NodeComparator
2021-03-03 21:28:27 +00:00
*/
protected $nodeComparator ;
2021-03-03 21:51:04 +00:00
/**
2021-05-12 13:15:45 +00:00
* @ var \Rector\PostRector\Collector\NodesToRemoveCollector
2021-03-03 21:51:04 +00:00
*/
protected $nodesToRemoveCollector ;
2021-04-13 00:12:48 +00:00
/**
2021-05-12 13:15:45 +00:00
* @ var \Rector\Core\ValueObject\Application\File
2021-04-13 00:12:48 +00:00
*/
protected $file ;
2021-09-02 06:26:12 +00:00
/**
* @ var \Rector\PostRector\Collector\NodesToAddCollector
*/
protected $nodesToAddCollector ;
2021-03-03 21:28:27 +00:00
/**
2021-08-23 00:20:32 +00:00
* @ var \Symplify\Astral\NodeTraverser\SimpleCallableNodeTraverser
2021-03-03 21:28:27 +00:00
*/
private $simpleCallableNodeTraverser ;
/**
2022-02-11 12:13:24 +00:00
* @ var \Rector\Core\Contract\Console\OutputStyleInterface
2021-03-03 21:28:27 +00:00
*/
2022-02-11 12:13:24 +00:00
private $rectorOutputStyle ;
2021-03-03 21:28:27 +00:00
/**
2021-05-12 13:15:45 +00:00
* @ var \Rector\Core\Exclusion\ExclusionManager
2021-03-03 21:28:27 +00:00
*/
private $exclusionManager ;
/**
2021-05-12 13:15:45 +00:00
* @ var \Rector\Core\Logging\CurrentRectorProvider
2021-03-03 21:28:27 +00:00
*/
private $currentRectorProvider ;
/**
2021-05-12 13:15:45 +00:00
* @ var \Rector\Core\Configuration\CurrentNodeProvider
2021-03-03 21:28:27 +00:00
*/
private $currentNodeProvider ;
/**
2021-08-23 00:20:32 +00:00
* @ var \Symplify\Skipper\Skipper\Skipper
2021-03-03 21:28:27 +00:00
*/
private $skipper ;
/**
* @ var string | null
*/
2021-10-26 09:20:50 +00:00
private $previousAppliedClass = null ;
2021-04-13 00:12:48 +00:00
/**
2021-05-12 13:15:45 +00:00
* @ var \Rector\Core\Provider\CurrentFileProvider
2021-04-13 00:12:48 +00:00
*/
private $currentFileProvider ;
2021-05-05 23:44:08 +00:00
/**
2021-05-16 18:32:58 +00:00
* @ var array < string , Node [] | Node >
2021-05-05 23:44:08 +00:00
*/
private $nodesToReturn = [];
2021-10-18 19:19:09 +00:00
/**
* @ var \Rector\Core\ProcessAnalyzer\RectifiedAnalyzer
*/
private $rectifiedAnalyzer ;
2021-12-31 10:33:05 +00:00
/**
* @ var \Rector\Core\NodeDecorator\CreatedByRuleDecorator
*/
private $createdByRuleDecorator ;
2021-03-03 21:28:27 +00:00
/**
* @ required
*/
2022-02-27 00:40:38 +00:00
public function autowire ( \Rector\PostRector\Collector\NodesToRemoveCollector $nodesToRemoveCollector , \Rector\PostRector\Collector\NodesToAddCollector $nodesToAddCollector , \Rector\NodeRemoval\NodeRemover $nodeRemover , \Rector\Core\Application\FileSystem\RemovedAndAddedFilesCollector $removedAndAddedFilesCollector , \Rector\Core\PhpParser\Printer\BetterStandardPrinter $betterStandardPrinter , \Rector\NodeNameResolver\NodeNameResolver $nodeNameResolver , \Rector\NodeTypeResolver\NodeTypeResolver $nodeTypeResolver , \RectorPrefix20220227\Symplify\Astral\NodeTraverser\SimpleCallableNodeTraverser $simpleCallableNodeTraverser , \Rector\Core\PhpParser\Node\NodeFactory $nodeFactory , \Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory $phpDocInfoFactory , \Rector\Core\Contract\Console\OutputStyleInterface $rectorOutputStyle , \Rector\Core\Php\PhpVersionProvider $phpVersionProvider , \Rector\Core\Exclusion\ExclusionManager $exclusionManager , \Rector\StaticTypeMapper\StaticTypeMapper $staticTypeMapper , \RectorPrefix20220227\Symplify\PackageBuilder\Parameter\ParameterProvider $parameterProvider , \Rector\Core\Logging\CurrentRectorProvider $currentRectorProvider , \Rector\Core\Configuration\CurrentNodeProvider $currentNodeProvider , \RectorPrefix20220227\Symplify\Skipper\Skipper\Skipper $skipper , \Rector\Core\PhpParser\Node\Value\ValueResolver $valueResolver , \Rector\Core\PhpParser\Node\BetterNodeFinder $betterNodeFinder , \Rector\Core\PhpParser\Comparing\NodeComparator $nodeComparator , \Rector\Core\Provider\CurrentFileProvider $currentFileProvider , \Rector\Core\ProcessAnalyzer\RectifiedAnalyzer $rectifiedAnalyzer , \Rector\Core\NodeDecorator\CreatedByRuleDecorator $createdByRuleDecorator ) : void
2021-05-09 20:15:43 +00:00
{
2021-03-03 21:28:27 +00:00
$this -> nodesToRemoveCollector = $nodesToRemoveCollector ;
$this -> nodesToAddCollector = $nodesToAddCollector ;
$this -> nodeRemover = $nodeRemover ;
$this -> removedAndAddedFilesCollector = $removedAndAddedFilesCollector ;
$this -> betterStandardPrinter = $betterStandardPrinter ;
$this -> nodeNameResolver = $nodeNameResolver ;
$this -> nodeTypeResolver = $nodeTypeResolver ;
$this -> simpleCallableNodeTraverser = $simpleCallableNodeTraverser ;
$this -> nodeFactory = $nodeFactory ;
$this -> phpDocInfoFactory = $phpDocInfoFactory ;
2022-02-11 12:13:24 +00:00
$this -> rectorOutputStyle = $rectorOutputStyle ;
2021-03-03 21:28:27 +00:00
$this -> phpVersionProvider = $phpVersionProvider ;
$this -> exclusionManager = $exclusionManager ;
$this -> staticTypeMapper = $staticTypeMapper ;
$this -> parameterProvider = $parameterProvider ;
$this -> currentRectorProvider = $currentRectorProvider ;
$this -> currentNodeProvider = $currentNodeProvider ;
$this -> skipper = $skipper ;
$this -> valueResolver = $valueResolver ;
$this -> betterNodeFinder = $betterNodeFinder ;
$this -> nodeComparator = $nodeComparator ;
2021-04-13 00:12:48 +00:00
$this -> currentFileProvider = $currentFileProvider ;
2021-10-18 19:19:09 +00:00
$this -> rectifiedAnalyzer = $rectifiedAnalyzer ;
2021-12-31 10:33:05 +00:00
$this -> createdByRuleDecorator = $createdByRuleDecorator ;
2021-03-03 21:28:27 +00:00
}
/**
* @ return Node [] | null
*/
2021-12-10 10:22:23 +00:00
public function beforeTraverse ( array $nodes ) : ? array
2021-03-03 21:28:27 +00:00
{
$this -> previousAppliedClass = null ;
2021-04-13 00:12:48 +00:00
// workaround for file around refactor()
$file = $this -> currentFileProvider -> getFile ();
2021-05-10 22:23:08 +00:00
if ( ! $file instanceof \Rector\Core\ValueObject\Application\File ) {
2021-12-28 12:08:43 +00:00
throw new \Rector\Core\Exception\ShouldNotHappenException ( 'File object is missing. Make sure you call $this->currentFileProvider->setFile(...) before traversing.' );
2021-04-13 00:12:48 +00:00
}
$this -> file = $file ;
2021-03-03 21:28:27 +00:00
return parent :: beforeTraverse ( $nodes );
}
/**
2021-11-28 16:42:02 +00:00
* @ return Node | int | null
2021-03-03 21:28:27 +00:00
*/
2021-12-10 10:22:23 +00:00
public final function enterNode ( \PhpParser\Node $node )
2021-03-03 21:28:27 +00:00
{
2021-05-09 20:15:43 +00:00
$nodeClass = \get_class ( $node );
if ( ! $this -> isMatchingNodeType ( $nodeClass )) {
2021-03-03 21:28:27 +00:00
return null ;
}
2022-02-08 02:16:31 +00:00
if ( $this -> shouldSkipCurrentNode ( $node )) {
2021-03-03 21:28:27 +00:00
return null ;
}
2022-02-26 10:14:02 +00:00
/** @var Node $originalNode */
$originalNode = $node -> getAttribute ( \Rector\NodeTypeResolver\Node\AttributeKey :: ORIGINAL_NODE ) ? ? clone $node ;
$createdByRule = $originalNode -> getAttribute ( \Rector\NodeTypeResolver\Node\AttributeKey :: CREATED_BY_RULE ) ? ? [];
if ( \in_array ( static :: class , $createdByRule , \true )) {
return null ;
}
2021-04-13 00:12:48 +00:00
$this -> currentRectorProvider -> changeCurrentRector ( $this );
// for PHP doc info factory and change notifier
$this -> currentNodeProvider -> setNode ( $node );
2021-03-03 21:28:27 +00:00
// show current Rector class on --debug
$this -> printDebugApplying ();
2021-04-13 00:12:48 +00:00
$originalAttributes = $node -> getAttributes ();
2021-03-03 21:28:27 +00:00
$node = $this -> refactor ( $node );
2021-12-31 10:33:05 +00:00
// nothing to change → continue
2022-02-06 10:37:45 +00:00
if ( $this -> isNothingToChange ( $node )) {
return null ;
}
2022-02-26 04:25:13 +00:00
/** @var Node[]|Node $node */
$this -> createdByRuleDecorator -> decorate ( $node , $originalNode , static :: class );
2022-02-24 18:47:53 +00:00
/** @var Node $originalNode */
$rectorWithLineChange = new \Rector\ChangesReporting\ValueObject\RectorWithLineChange ( \get_class ( $this ), $originalNode -> getLine ());
$this -> file -> addRectorClassWithLine ( $rectorWithLineChange );
2022-02-05 11:57:25 +00:00
/** @var Node $originalNode */
2021-05-09 20:15:43 +00:00
if ( \is_array ( $node )) {
$originalNodeHash = \spl_object_hash ( $originalNode );
2021-05-05 23:44:08 +00:00
$this -> nodesToReturn [ $originalNodeHash ] = $node ;
2022-02-06 10:37:45 +00:00
\reset ( $node );
$firstNodeKey = \key ( $node );
$this -> mirrorComments ( $node [ $firstNodeKey ], $originalNode );
2021-05-05 23:44:08 +00:00
// will be replaced in leaveNode() the original node must be passed
return $originalNode ;
}
2021-12-31 10:33:05 +00:00
// update parents relations - must run before connectParentNodes()
2022-02-25 10:00:26 +00:00
/** @var Node $node */
2021-12-31 10:33:05 +00:00
$this -> mirrorAttributes ( $originalAttributes , $node );
$this -> connectParentNodes ( $node );
// is equals node type? return node early
if ( \get_class ( $originalNode ) === \get_class ( $node )) {
return $node ;
}
// search "infinite recursion" in https://github.com/nikic/PHP-Parser/blob/master/doc/component/Walking_the_AST.markdown
$originalNodeHash = \spl_object_hash ( $originalNode );
if ( $originalNode instanceof \PhpParser\Node\Stmt && $node instanceof \PhpParser\Node\Expr ) {
$node = new \PhpParser\Node\Stmt\Expression ( $node );
2021-03-03 21:28:27 +00:00
}
2021-12-31 10:33:05 +00:00
$this -> nodesToReturn [ $originalNodeHash ] = $node ;
2021-03-03 21:28:27 +00:00
return $node ;
}
2021-05-16 18:32:58 +00:00
/**
* Replacing nodes in leaveNode () method avoids infinite recursion
* see " infinite recursion " in https :// github . com / nikic / PHP - Parser / blob / master / doc / component / Walking_the_AST . markdown
*/
2021-12-10 10:22:23 +00:00
public function leaveNode ( \PhpParser\Node $node )
2021-05-05 23:44:08 +00:00
{
2021-05-09 20:15:43 +00:00
$objectHash = \spl_object_hash ( $node );
2021-05-16 18:32:58 +00:00
// update parents relations!!!
return $this -> nodesToReturn [ $objectHash ] ? ? $node ;
2021-05-05 23:44:08 +00:00
}
2021-12-10 10:22:23 +00:00
protected function isName ( \PhpParser\Node $node , string $name ) : bool
2021-03-03 21:28:27 +00:00
{
return $this -> nodeNameResolver -> isName ( $node , $name );
}
/**
* @ param string [] $names
*/
2021-12-10 10:22:23 +00:00
protected function isNames ( \PhpParser\Node $node , array $names ) : bool
2021-03-03 21:28:27 +00:00
{
return $this -> nodeNameResolver -> isNames ( $node , $names );
}
2021-12-10 10:22:23 +00:00
protected function getName ( \PhpParser\Node $node ) : ? string
2021-03-03 21:28:27 +00:00
{
return $this -> nodeNameResolver -> getName ( $node );
}
2021-12-10 10:22:23 +00:00
protected function isObjectType ( \PhpParser\Node $node , \PHPStan\Type\ObjectType $objectType ) : bool
2021-03-03 21:28:27 +00:00
{
return $this -> nodeTypeResolver -> isObjectType ( $node , $objectType );
}
2021-10-07 17:46:41 +00:00
/**
* Use this method for getting expr | node type
*/
2021-12-10 10:22:23 +00:00
protected function getType ( \PhpParser\Node $node ) : \PHPStan\Type\Type
2021-03-03 21:28:27 +00:00
{
2021-10-07 17:46:41 +00:00
return $this -> nodeTypeResolver -> getType ( $node );
2021-03-03 21:28:27 +00:00
}
/**
2021-10-30 14:18:31 +00:00
* @ param mixed [] | \PhpParser\Node $nodes
2022-02-19 18:54:29 +00:00
* @ param callable ( Node $node ) : ( Node | null | int ) $callable
2021-03-03 21:28:27 +00:00
*/
2021-12-10 10:22:23 +00:00
protected function traverseNodesWithCallable ( $nodes , callable $callable ) : void
2021-03-03 21:28:27 +00:00
{
$this -> simpleCallableNodeTraverser -> traverseNodesWithCallable ( $nodes , $callable );
}
/**
2021-10-30 14:18:31 +00:00
* @ param mixed [] | \PhpParser\Node | null $node
2021-03-03 21:28:27 +00:00
*/
2021-05-09 20:15:43 +00:00
protected function print ( $node ) : string
2021-03-03 21:28:27 +00:00
{
return $this -> betterStandardPrinter -> print ( $node );
}
2021-12-10 10:22:23 +00:00
protected function mirrorComments ( \PhpParser\Node $newNode , \PhpParser\Node $oldNode ) : void
2021-03-03 21:28:27 +00:00
{
2021-05-10 22:23:08 +00:00
$newNode -> setAttribute ( \Rector\NodeTypeResolver\Node\AttributeKey :: PHP_DOC_INFO , $oldNode -> getAttribute ( \Rector\NodeTypeResolver\Node\AttributeKey :: PHP_DOC_INFO ));
$newNode -> setAttribute ( \Rector\NodeTypeResolver\Node\AttributeKey :: COMMENTS , $oldNode -> getAttribute ( \Rector\NodeTypeResolver\Node\AttributeKey :: COMMENTS ));
2021-03-03 21:28:27 +00:00
}
/**
2021-04-23 19:32:59 +00:00
* @ param Arg [] $currentArgs
2021-03-03 21:28:27 +00:00
* @ param Arg [] $appendingArgs
* @ return Arg []
*/
2021-12-10 10:22:23 +00:00
protected function appendArgs ( array $currentArgs , array $appendingArgs ) : array
2021-03-03 21:28:27 +00:00
{
2021-03-05 10:55:40 +00:00
foreach ( $appendingArgs as $appendingArg ) {
2021-05-10 22:23:08 +00:00
$currentArgs [] = new \PhpParser\Node\Arg ( $appendingArg -> value );
2021-03-03 21:28:27 +00:00
}
2021-04-23 19:32:59 +00:00
return $currentArgs ;
2021-03-03 21:28:27 +00:00
}
2021-06-18 17:31:16 +00:00
/**
* @ return \PhpParser\Node\Expr | \PhpParser\Node\Stmt
*/
2021-12-10 10:22:23 +00:00
protected function unwrapExpression ( \PhpParser\Node\Stmt $stmt )
2021-03-03 21:28:27 +00:00
{
2021-05-10 22:23:08 +00:00
if ( $stmt instanceof \PhpParser\Node\Stmt\Expression ) {
2021-03-03 21:28:27 +00:00
return $stmt -> expr ;
}
return $stmt ;
}
/**
2021-05-06 08:23:37 +00:00
* @ deprecated Use refactor () return of [] or directly $nodesToAddCollector
2021-03-03 21:28:27 +00:00
* @ param Node [] $newNodes
*/
2021-12-10 10:22:23 +00:00
protected function addNodesAfterNode ( array $newNodes , \PhpParser\Node $positionNode ) : void
2021-03-03 21:28:27 +00:00
{
$this -> nodesToAddCollector -> addNodesAfterNode ( $newNodes , $positionNode );
}
/**
* @ param Node [] $newNodes
2021-05-06 08:23:37 +00:00
* @ deprecated Use refactor () return of [] or directly $nodesToAddCollector
2021-03-03 21:28:27 +00:00
*/
2021-12-10 10:22:23 +00:00
protected function addNodesBeforeNode ( array $newNodes , \PhpParser\Node $positionNode ) : void
2021-03-03 21:28:27 +00:00
{
$this -> nodesToAddCollector -> addNodesBeforeNode ( $newNodes , $positionNode );
}
2021-05-06 08:23:37 +00:00
/**
* @ deprecated Use refactor () return of [] or directly $nodesToAddCollector
*/
2021-12-10 10:22:23 +00:00
protected function addNodeAfterNode ( \PhpParser\Node $newNode , \PhpParser\Node $positionNode ) : void
2021-03-03 21:28:27 +00:00
{
$this -> nodesToAddCollector -> addNodeAfterNode ( $newNode , $positionNode );
}
2021-05-06 08:23:37 +00:00
/**
* @ deprecated Use refactor () return of [] or directly $nodesToAddCollector
*/
2021-12-10 10:22:23 +00:00
protected function addNodeBeforeNode ( \PhpParser\Node $newNode , \PhpParser\Node $positionNode ) : void
2021-03-03 21:28:27 +00:00
{
$this -> nodesToAddCollector -> addNodeBeforeNode ( $newNode , $positionNode );
}
2021-12-10 10:22:23 +00:00
protected function removeNode ( \PhpParser\Node $node ) : void
2021-03-03 21:28:27 +00:00
{
$this -> nodeRemover -> removeNode ( $node );
}
/**
2021-08-23 00:20:32 +00:00
* @ param \PhpParser\Node\Stmt\Class_ | \PhpParser\Node\Stmt\ClassMethod | \PhpParser\Node\Stmt\Function_ $nodeWithStatements
2021-03-03 21:28:27 +00:00
*/
2021-12-10 10:22:23 +00:00
protected function removeNodeFromStatements ( $nodeWithStatements , \PhpParser\Node $toBeRemovedNode ) : void
2021-03-03 21:28:27 +00:00
{
2021-05-30 10:12:56 +00:00
$this -> nodeRemover -> removeNodeFromStatements ( $nodeWithStatements , $toBeRemovedNode );
2021-03-03 21:28:27 +00:00
}
/**
* @ param Node [] $nodes
*/
2021-12-10 10:22:23 +00:00
protected function removeNodes ( array $nodes ) : void
2021-03-03 21:28:27 +00:00
{
$this -> nodeRemover -> removeNodes ( $nodes );
}
2022-02-01 11:46:50 +00:00
/**
2022-02-06 10:37:45 +00:00
* @ param mixed [] | \PhpParser\Node | null $node
2022-02-01 11:46:50 +00:00
*/
2022-02-06 10:37:45 +00:00
private function isNothingToChange ( $node ) : bool
2022-02-01 11:46:50 +00:00
{
2022-02-06 10:37:45 +00:00
if ( $node === null ) {
return \true ;
2022-02-01 11:46:50 +00:00
}
2022-02-06 10:37:45 +00:00
return $node === [];
2022-02-01 11:46:50 +00:00
}
2021-04-13 00:12:48 +00:00
/**
* @ param class - string < Node > $nodeClass
*/
2021-05-09 20:15:43 +00:00
private function isMatchingNodeType ( string $nodeClass ) : bool
2021-03-03 21:28:27 +00:00
{
foreach ( $this -> getNodeTypes () as $nodeType ) {
2021-05-09 20:15:43 +00:00
if ( \is_a ( $nodeClass , $nodeType , \true )) {
return \true ;
2021-03-03 21:28:27 +00:00
}
}
2021-05-09 20:15:43 +00:00
return \false ;
2021-03-03 21:28:27 +00:00
}
2022-02-08 02:16:31 +00:00
private function shouldSkipCurrentNode ( \PhpParser\Node $node ) : bool
2021-03-03 21:28:27 +00:00
{
2021-03-03 21:51:04 +00:00
if ( $this -> nodesToRemoveCollector -> isNodeRemoved ( $node )) {
2021-05-09 20:15:43 +00:00
return \true ;
2021-03-03 21:28:27 +00:00
}
if ( $this -> exclusionManager -> isNodeSkippedByRector ( $node , $this )) {
2021-05-09 20:15:43 +00:00
return \true ;
2021-03-03 21:28:27 +00:00
}
2021-04-13 00:12:48 +00:00
$smartFileInfo = $this -> file -> getSmartFileInfo ();
2021-10-18 19:19:09 +00:00
if ( $this -> skipper -> shouldSkipElementAndFileInfo ( $this , $smartFileInfo )) {
return \true ;
}
2022-02-08 02:16:31 +00:00
$rectifiedNode = $this -> rectifiedAnalyzer -> verify ( $this , $node , $this -> file );
2021-10-18 19:19:09 +00:00
return $rectifiedNode instanceof \Rector\Core\ValueObject\RectifiedNode ;
2021-03-03 21:28:27 +00:00
}
2021-05-09 20:15:43 +00:00
private function printDebugApplying () : void
2021-03-03 21:28:27 +00:00
{
2022-02-11 12:13:24 +00:00
if ( ! $this -> rectorOutputStyle -> isDebug ()) {
2021-03-03 21:28:27 +00:00
return ;
}
if ( $this -> previousAppliedClass === static :: class ) {
return ;
}
// prevent spamming with the same class over and over
// indented on purpose to improve log nesting under [refactoring]
2022-02-11 12:13:24 +00:00
$this -> rectorOutputStyle -> writeln ( ' [applying] ' . static :: class );
2021-03-03 21:28:27 +00:00
$this -> previousAppliedClass = static :: class ;
}
2021-04-13 00:12:48 +00:00
/**
* @ param array < string , mixed > $originalAttributes
*/
2021-05-10 22:23:08 +00:00
private function mirrorAttributes ( array $originalAttributes , \PhpParser\Node $newNode ) : void
2021-03-03 21:28:27 +00:00
{
2021-04-13 00:12:48 +00:00
foreach ( $originalAttributes as $attributeName => $oldAttributeValue ) {
2021-05-09 20:15:43 +00:00
if ( ! \in_array ( $attributeName , self :: ATTRIBUTES_TO_MIRROR , \true )) {
2021-03-03 21:28:27 +00:00
continue ;
}
2021-04-13 00:12:48 +00:00
$newNode -> setAttribute ( $attributeName , $oldAttributeValue );
2021-03-03 21:28:27 +00:00
}
}
2021-10-23 21:09:26 +00:00
private function connectParentNodes ( \PhpParser\Node $node ) : void
2021-04-13 00:12:48 +00:00
{
2021-05-10 22:23:08 +00:00
$nodeTraverser = new \PhpParser\NodeTraverser ();
$nodeTraverser -> addVisitor ( new \PhpParser\NodeVisitor\ParentConnectingVisitor ());
2021-10-23 21:09:26 +00:00
$nodeTraverser -> traverse ([ $node ]);
2021-04-13 00:12:48 +00:00
}
2017-08-07 15:27:04 +00:00
}