From c58b55796da01a2bf580e759c234933b872310a4 Mon Sep 17 00:00:00 2001 From: TomasVotruba Date: Thu, 19 Oct 2017 01:02:47 +0200 Subject: [PATCH] decouple to AbstractRector --- src/Rector/AbstractRector.php | 73 +++++++++++++++++++ .../Nette/DI/CompilerArgumentsRector.php | 59 +-------------- .../PseudoNamespaceToNamespaceRector.php | 12 +-- 3 files changed, 79 insertions(+), 65 deletions(-) diff --git a/src/Rector/AbstractRector.php b/src/Rector/AbstractRector.php index 932df4540bf..238009b541c 100644 --- a/src/Rector/AbstractRector.php +++ b/src/Rector/AbstractRector.php @@ -3,10 +3,14 @@ namespace Rector\Rector; use PhpParser\Node; +use PhpParser\Node\Expr; +use PhpParser\Node\Stmt\Expression; use PhpParser\Node\Stmt\Nop; use PhpParser\NodeTraverser; use PhpParser\NodeVisitorAbstract; use Rector\Contract\Rector\RectorInterface; +use Rector\Node\Attribute; +use SplObjectStorage; abstract class AbstractRector extends NodeVisitorAbstract implements RectorInterface { @@ -15,6 +19,22 @@ abstract class AbstractRector extends NodeVisitorAbstract implements RectorInter */ protected $shouldRemoveNode = false; + /** + * @var SplObjectStorage|Expression[] + */ + private $expressionsToPrepend = []; + + /** + * @param Node[] $nodes + * @return Node[] + */ + final public function beforeTraverse(array $nodes): array + { + $this->expressionsToPrepend = new SplObjectStorage; + + return $nodes; + } + /** * @return null|int|Node */ @@ -44,4 +64,57 @@ abstract class AbstractRector extends NodeVisitorAbstract implements RectorInter return null; } + + /** + * @param Node[] $nodes + * @return Node[] + */ + public function afterTraverse(array $nodes): array + { + return $this->prependExpressionNodes($nodes); + } + + protected function prependNodeBehindNode(Expr $nodeToPrepend, Node $positionNode): void + { + /** @var Node $parentNode */ + $parentNode = $positionNode->getAttribute(Attribute::PARENT_NODE); + if (! $parentNode instanceof Expression) { + // validate? + return; + } + + $expressionToPrepend = new Expression($nodeToPrepend); + + if (isset($this->expressionsToPrepend[$parentNode])) { + $this->expressionsToPrepend[$parentNode] = array_merge( + $this->expressionsToPrepend[$parentNode], + [$expressionToPrepend] + ); + } else { + $this->expressionsToPrepend[$parentNode] = [$expressionToPrepend]; + } + } + + /** + * @param Node[] $nodes + * @return Node[] array + */ + private function prependExpressionNodes(array $nodes): array + { + foreach ($nodes as $i => $node) { + if ($node instanceof Expression) { + if (! isset($this->expressionsToPrepend[$node])) { + continue; + } + + array_splice($nodes, $i + 1, 0, $this->expressionsToPrepend[$node]); + + unset($this->expressionsToPrepend[$node]); + } elseif (isset($node->stmts)) { + $node->stmts = $this->prependExpressionNodes($node->stmts); + } + } + + return $nodes; + } } diff --git a/src/Rector/Contrib/Nette/DI/CompilerArgumentsRector.php b/src/Rector/Contrib/Nette/DI/CompilerArgumentsRector.php index 6dd30e63c72..a050f0e8d8b 100644 --- a/src/Rector/Contrib/Nette/DI/CompilerArgumentsRector.php +++ b/src/Rector/Contrib/Nette/DI/CompilerArgumentsRector.php @@ -5,12 +5,8 @@ namespace Rector\Rector\Contrib\Nette\DI; use PhpParser\Node; use PhpParser\Node\Arg; use PhpParser\Node\Expr\MethodCall; -use PhpParser\Node\Stmt\Expression; -use Rector\Builder\StatementGlue; -use Rector\Node\Attribute; use Rector\NodeAnalyzer\MethodCallAnalyzer; use Rector\Rector\AbstractRector; -use SplObjectStorage; /** * Nette\DI\Compiler::compile arguments are deprecated, use Compiler::addConfig() and Compiler::setClassName(). @@ -30,21 +26,9 @@ final class CompilerArgumentsRector extends AbstractRector */ private $methodCallAnalyzer; - /** - * @var SplObjectStorage|Expression[] - */ - private $expressionsToPrepend = []; - - /** - * @var StatementGlue - */ - private $statementGlue; - - public function __construct(MethodCallAnalyzer $methodCallAnalyzer, StatementGlue $statementGlue) + public function __construct(MethodCallAnalyzer $methodCallAnalyzer) { - $this->expressionsToPrepend = new SplObjectStorage; $this->methodCallAnalyzer = $methodCallAnalyzer; - $this->statementGlue = $statementGlue; } public function isCandidate(Node $node): bool @@ -57,31 +41,19 @@ final class CompilerArgumentsRector extends AbstractRector return count($node->args) >= 1; } - /** - * @todo build into abstract? - * - * @param Node[] $nodes - * @return Node[] - */ - public function afterTraverse(array $nodes): array - { - return $this->processNodes($nodes); - } - /** * @param MethodCall $methodCallNode */ public function refactor(Node $methodCallNode): ?Node { $oldArguments = $methodCallNode->args; - $nodesToPrepend = []; $addConfigMethodCallNode = $this->cloneMethodWithNameAndArgument( $methodCallNode, 'addConfig', $oldArguments[0] ); - $nodesToPrepend[] = new Expression($addConfigMethodCallNode); + $this->prependNodeBehindNode($addConfigMethodCallNode, $methodCallNode); if (isset($oldArguments[1])) { $setClassNameMethodCallNode = $this->cloneMethodWithNameAndArgument( @@ -89,39 +61,14 @@ final class CompilerArgumentsRector extends AbstractRector 'setClassName', $oldArguments[1] ); - $nodesToPrepend[] = new Expression($setClassNameMethodCallNode); + $this->prependNodeBehindNode($setClassNameMethodCallNode, $methodCallNode); } - $parentExpressionNode = $methodCallNode->getAttribute(Attribute::PARENT_NODE); - $this->expressionsToPrepend[$parentExpressionNode] = $nodesToPrepend; - $methodCallNode->args = []; return $methodCallNode; } - /** - * @param Node[] $nodes - * @return Node[] array - */ - private function processNodes(array $nodes): array - { - foreach ($nodes as $i => $node) { - if ($node instanceof Expression) { - if (! isset($this->expressionsToPrepend[$node])) { - continue; - } - - $nodes = $this->statementGlue->insertNewNodesAfter($nodes, $this->expressionsToPrepend[$node], $i); - $this->expressionsToPrepend[$node] = null; - } elseif (isset($node->stmts)) { - $node->stmts = $this->processNodes($node->stmts); - } - } - - return $nodes; - } - private function cloneMethodWithNameAndArgument( MethodCall $methodCallNode, string $method, diff --git a/src/Rector/Dynamic/PseudoNamespaceToNamespaceRector.php b/src/Rector/Dynamic/PseudoNamespaceToNamespaceRector.php index 9bb92e9e65e..e8a92e3b357 100644 --- a/src/Rector/Dynamic/PseudoNamespaceToNamespaceRector.php +++ b/src/Rector/Dynamic/PseudoNamespaceToNamespaceRector.php @@ -55,15 +55,6 @@ final class PseudoNamespaceToNamespaceRector extends AbstractRector $this->statementGlue = $statementGlue; } - /** - * @param mixed[] $nodes - */ - public function beforeTraverse(array $nodes): void - { - $this->newNamespace = null; - $this->oldToNewUseStatements = []; - } - public function isCandidate(Node $node): bool { $name = $this->resolveNameFromNode($node); @@ -134,6 +125,9 @@ final class PseudoNamespaceToNamespaceRector extends AbstractRector } } + $this->newNamespace = null; + $this->oldToNewUseStatements = []; + return $nodes; }