fixup NodeTraverser order

This commit is contained in:
TomasVotruba 2017-08-20 16:08:24 +02:00
parent 261f9aa8f2
commit 863a20df68
11 changed files with 111 additions and 57 deletions

View File

@ -7,6 +7,7 @@ use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\FunctionLike;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Stmt\ClassLike;
use PhpParser\NodeVisitorAbstract;
use Rector\NodeTypeResolver\TypeContext;
@ -47,8 +48,9 @@ final class ClassLikeTypeResolver extends NodeVisitorAbstract
$parentNode = $node->getAttribute('parent');
if ($parentNode instanceof Assign) {
if ($parentNode->expr instanceof New_) {
$variableType = $parentNode->expr->class->toString();
$variableName = $parentNode->var->name;
$variableName = $node->name;
$variableType = $this->getTypeFromNewNode($parentNode->expr);
$this->typeContext->addLocalVariable($variableName, $variableType);
}
} else {
@ -64,4 +66,12 @@ final class ClassLikeTypeResolver extends NodeVisitorAbstract
$this->typeContext->addAssign($node->var->name, $node->expr->name);
}
}
private function getTypeFromNewNode(New_ $newNode): string
{
/** @var FullyQualified $fqnName */
$fqnName = $newNode->class->getAttribute('resolvedName');
return $fqnName->toString();
}
}

View File

@ -13,12 +13,4 @@ final class ContainerFactory
return $appKernel->getContainer();
}
public function createWithConfig(string $config): ContainerInterface
{
$appKernel = new AppKernel($config);
$appKernel->boot();
return $appKernel->getContainer();
}
}

View File

@ -0,0 +1,14 @@
<?php declare(strict_types=1);
namespace Rector\NodeTraverser;
use PhpParser\NodeTraverser;
use Rector\NodeTypeResolver\NodeVisitor\ClassLikeTypeResolver;
final class ClassLikeTypeResolvingNodeTraverser extends NodeTraverser
{
public function __construct(ClassLikeTypeResolver $classLikeTypeResolver)
{
$this->addVisitor($classLikeTypeResolver);
}
}

View File

@ -10,6 +10,6 @@ final class CloningNodeTraverser extends NodeTraverser
public function __construct()
{
// note: probably have to be recreated to clear cache
$this->visitors[] = new CloningVisitor;
$this->addVisitor(new CloningVisitor);
}
}

View File

@ -0,0 +1,14 @@
<?php declare(strict_types=1);
namespace Rector\NodeTraverser;
use PhpParser\NodeTraverser;
use Rector\NodeVisitor\NodeConnector;
final class ConnectorNodeTraverser extends NodeTraverser
{
public function __construct(NodeConnector $nodeConnector)
{
$this->addVisitor($nodeConnector);
}
}

View File

@ -0,0 +1,18 @@
<?php declare(strict_types=1);
namespace Rector\NodeTraverser;
use PhpParser\NodeTraverser;
use PhpParser\NodeVisitor\NameResolver;
final class NamingNodeTraverser extends NodeTraverser
{
/**
* NameResolver adds $namespacedName
* @see https://github.com/nikic/PHP-Parser/blob/7b36ca3b6cc1b99210c6699074d6091061e73eea/lib/PhpParser/Node/Stmt/ClassLike.php#L8
*/
public function __construct(NameResolver $nameResolver)
{
$this->addVisitor($nameResolver);
}
}

View File

@ -1,25 +0,0 @@
<?php declare(strict_types=1);
namespace Rector\NodeTraverser;
use PhpParser\NodeTraverser;
use PhpParser\NodeVisitor\NameResolver;
use Rector\NodeTypeResolver\NodeVisitor\ClassLikeTypeResolver;
use Rector\NodeVisitor\NodeConnector;
final class StartupNodeTraverser extends NodeTraverser
{
/**
* NameResolver adds $namespacedName
* @see https://github.com/nikic/PHP-Parser/blob/7b36ca3b6cc1b99210c6699074d6091061e73eea/lib/PhpParser/Node/Stmt/ClassLike.php#L8
*/
public function __construct(
NameResolver $nameResolver,
NodeConnector $nodeConnector,
ClassLikeTypeResolver $classLikeTypeResolver
) {
$this->addVisitor($nameResolver);
$this->addVisitor($nodeConnector);
$this->addVisitor($classLikeTypeResolver);
}
}

View File

@ -14,9 +14,9 @@ use Rector\Rector\AbstractRector;
final class HtmlAddMethodRector extends AbstractRector
{
/**
* @var Node[]
* @var string
*/
private $fileNodes = [];
private const CLASS_NAME = Html::class;
public function getSetName(): string
{
@ -28,14 +28,9 @@ final class HtmlAddMethodRector extends AbstractRector
return 2.4;
}
public function beforeTraverse(array $nodes): void
{
$this->fileNodes = $nodes;
}
public function isCandidate(Node $node): bool
{
if ($this->isOnTypeCall($node, Html::class)) {
if ($this->isOnTypeCall($node, self::CLASS_NAME)) {
return true;
}
@ -66,7 +61,7 @@ final class HtmlAddMethodRector extends AbstractRector
return false;
}
if ($node->class->getLast() !== 'Html') {
if ($node->class->toString() !== self::class) {
return false;
}
@ -87,11 +82,6 @@ final class HtmlAddMethodRector extends AbstractRector
return false;
}
dump($node->var);
dump($node->getAttribute('type'));
dump($node->getAttribute('type') === $class);
die;
return false;
return $node->var->getAttribute('type') === $class;
}
}

View File

@ -6,7 +6,11 @@ use PhpParser\Lexer;
use PhpParser\NodeVisitor;
use Rector\Contract\Parser\ParserInterface;
use Rector\NodeTraverser\CloningNodeTraverser;
use Rector\NodeTraverser\ConnectorNodeTraverser;
use Rector\NodeTraverser\MainNodeTraverser;
use Rector\NodeTraverser\NamingNodeTraverser;
use Rector\NodeTraverser\ShutdownNodeTraverser;
use Rector\NodeTraverser\ClassLikeTypeResolvingNodeTraverser;
use Rector\Printer\FormatPerservingPrinter;
use Rector\Rector\RectorCollector;
use SplFileInfo;
@ -43,13 +47,37 @@ final class FileProcessor
*/
private $cloningNodeTraverser;
/**
* @var ClassLikeTypeResolvingNodeTraverser
*/
private $classLikeTypeResolvingNodeTraverser;
/**
* @var ShutdownNodeTraverser
*/
private $shutdownNodeTraverser;
/**
* @var NamingNodeTraverser
*/
private $namingNodeTraverser;
/**
* @var ConnectorNodeTraverser
*/
private $connectorNodeTraverser;
public function __construct(
CloningNodeTraverser $cloningNodeTraverser,
ParserInterface $parser,
FormatPerservingPrinter $codeStyledPrinter,
Lexer $lexer,
MainNodeTraverser $mainNodeTraverser,
RectorCollector $rectorCollector
RectorCollector $rectorCollector,
ClassLikeTypeResolvingNodeTraverser $classLikeTypeResolvingNodeTraverser,
ShutdownNodeTraverser $shutdownNodeTraverser,
NamingNodeTraverser $namingNodeTraverser,
ConnectorNodeTraverser $connectorNodeTraverser
) {
$this->parser = $parser;
$this->codeStyledPrinter = $codeStyledPrinter;
@ -57,6 +85,10 @@ final class FileProcessor
$this->mainNodeTraverser = $mainNodeTraverser;
$this->rectorCollector = $rectorCollector;
$this->cloningNodeTraverser = $cloningNodeTraverser;
$this->classLikeTypeResolvingNodeTraverser = $classLikeTypeResolvingNodeTraverser;
$this->shutdownNodeTraverser = $shutdownNodeTraverser;
$this->namingNodeTraverser = $namingNodeTraverser;
$this->connectorNodeTraverser = $connectorNodeTraverser;
}
/**
@ -82,9 +114,12 @@ final class FileProcessor
$oldTokens = $this->lexer->getTokens();
$newStmts = $this->cloningNodeTraverser->traverse($oldStmts);
// @todo: first clone, then startup, then main
// @todo: introduce Traverser queue?
$newStmts = $this->namingNodeTraverser->traverse($newStmts);
$newStmts = $this->connectorNodeTraverser->traverse($newStmts);
$newStmts = $this->classLikeTypeResolvingNodeTraverser->traverse($newStmts);
$newStmts = $this->mainNodeTraverser->traverse($newStmts);
$newStmts = $this->shutdownNodeTraverser->traverse($newStmts);
return $this->codeStyledPrinter->printToString($newStmts, $oldStmts, $oldTokens);
}

View File

@ -2,6 +2,8 @@ parameters:
# todo
kernel_class: # for name based service refactoring
name: "Rector"
services:
_defaults:
autowire: true
@ -18,7 +20,7 @@ services:
# 3rd party services
Symfony\Component\Console\Application:
arguments:
$name: "Rector"
$name: "%name%"
# PhpParser - Parser
PhpParser\Parser:
@ -28,7 +30,11 @@ services:
PhpParser\ParserFactory: ~
PhpParser\BuilderFactory: ~
PhpParser\NodeVisitor\NameResolver: ~
PhpParser\NodeVisitor\NameResolver:
arguments:
$options:
'replaceNodes': false
PhpParser\NodeTraverser: ~
# PhpParser - Printer

View File

@ -3,5 +3,5 @@
class ClassWithExternalConstant
{
use \Nette\SmartObject;
use AnotherTrait;
use \AnotherTrait;
}