StatementGlue added

This commit is contained in:
TomasVotruba 2017-08-06 23:24:58 +02:00
parent 5d7c589533
commit d818014477
5 changed files with 105 additions and 58 deletions

View File

@ -2,7 +2,6 @@
namespace Rector\Builder; namespace Rector\Builder;
use Nette\Utils\Arrays;
use PhpParser\Builder\Method; use PhpParser\Builder\Method;
use PhpParser\Builder\Param; use PhpParser\Builder\Param;
use PhpParser\BuilderFactory; use PhpParser\BuilderFactory;
@ -23,10 +22,16 @@ final class ConstructorMethodBuilder
*/ */
private $builderFactory; private $builderFactory;
public function __construct(Parser $parser, BuilderFactory $builderFactory) /**
* @var StatementGlue
*/
private $statementGlue;
public function __construct(Parser $parser, BuilderFactory $builderFactory, StatementGlue $statementGlue)
{ {
$this->parser = $parser; $this->parser = $parser;
$this->builderFactory = $builderFactory; $this->builderFactory = $builderFactory;
$this->statementGlue = $statementGlue;
} }
public function addPropertyAssignToClass(Class_ $classNode, string $propertyType, string $propertyName): void public function addPropertyAssignToClass(Class_ $classNode, string $propertyType, string $propertyName): void
@ -50,7 +55,7 @@ final class ConstructorMethodBuilder
->addParam($this->createParameter($propertyType, $propertyName)) ->addParam($this->createParameter($propertyType, $propertyName))
->addStmts($assign); ->addStmts($assign);
$this->addAsFirstMethod($classNode, $constructorMethod->getNode()); $this->statementGlue->addAsFirstMethod($classNode, $constructorMethod->getNode());
} }
private function createParameter(string $propertyType, string $propertyName): Param private function createParameter(string $propertyType, string $propertyName): Param
@ -70,21 +75,4 @@ final class ConstructorMethodBuilder
$propertyName $propertyName
)); ));
} }
private function addAsFirstMethod(Class_ $classNode, ClassMethod $constructorMethod): void
{
foreach ($classNode->stmts as $key => $classElementNode) {
if ($classElementNode instanceof ClassMethod) {
Arrays::insertBefore(
$classNode->stmts,
$key,
['before_' . $key => $constructorMethod]
);
return;
}
}
$classNode->stmts[] = $constructorMethod;
}
} }

View File

@ -2,11 +2,9 @@
namespace Rector\Builder; namespace Rector\Builder;
use Nette\Utils\Arrays;
use PhpParser\BuilderFactory; use PhpParser\BuilderFactory;
use PhpParser\Comment\Doc; use PhpParser\Comment\Doc;
use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Property; use PhpParser\Node\Stmt\Property;
final class PropertyBuilder final class PropertyBuilder
@ -16,45 +14,22 @@ final class PropertyBuilder
*/ */
private $builderFactory; private $builderFactory;
public function __construct(BuilderFactory $builderFactory) /**
* @var StatementGlue
*/
private $statementGlue;
public function __construct(BuilderFactory $builderFactory, StatementGlue $statementGlue)
{ {
$this->builderFactory = $builderFactory; $this->builderFactory = $builderFactory;
$this->statementGlue = $statementGlue;
} }
public function addPropertyToClass(Class_ $classNode, string $propertyType, string $propertyName): void public function addPropertyToClass(Class_ $classNode, string $propertyType, string $propertyName): void
{ {
$propertyNode = $this->buildPrivatePropertyNode($propertyType, $propertyName); $propertyNode = $this->buildPrivatePropertyNode($propertyType, $propertyName);
// add before first method $this->statementGlue->addAsFirstMethod($classNode, $propertyNode);
foreach ($classNode->stmts as $key => $classElementNode) {
if ($classElementNode instanceof ClassMethod) {
Arrays::insertBefore(
$classNode->stmts,
$key,
['before_' . $key => $propertyNode]
);
return;
}
}
// or after last property
$previousElement = null;
foreach ($classNode->stmts as $key => $classElementNode) {
if ($previousElement instanceof Property && ! $classElementNode instanceof Property) {
Arrays::insertBefore(
$classNode->stmts,
$key,
['before_' . $key => $propertyNode]
);
return;
}
$previousElement = $classElementNode;
}
$classNode->stmts[] = $propertyNode;
} }
private function buildPrivatePropertyNode(string $propertyType, string $propertyName): Property private function buildPrivatePropertyNode(string $propertyType, string $propertyName): Property

View File

@ -0,0 +1,63 @@
<?php declare(strict_types=1);
namespace Rector\Builder;
use Nette\Utils\Arrays;
use PhpParser\Node;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Property;
use PhpParser\Node\Stmt\TraitUse;
final class StatementGlue
{
/**
* @param ClassMethod|Property $node
*/
public function addAsFirstMethod(Class_ $classNode, Node $node): void
{
foreach ($classNode->stmts as $key => $classElementNode) {
if ($classElementNode instanceof ClassMethod) {
$this->insertBefore($classNode, $node, $key);
return;
}
}
$previousElement = null;
foreach ($classNode->stmts as $key => $classElementNode) {
if ($previousElement instanceof Property && ! $classElementNode instanceof Property) {
$this->insertBefore($classNode, $node, $key);
return;
}
$previousElement = $classElementNode;
}
$classNode->stmts[] = $node;
}
public function addAsFirstTrait(Class_ $classNode, TraitUse $traitUse): void
{
foreach ($classNode->stmts as $key => $classElementNode) {
if ($classElementNode instanceof TraitUse) {
$this->insertBefore($classNode, $traitUse, $key);
return;
}
}
$classNode->stmts[] = $traitUse;
}
/**
* @param int|string $key
*/
private function insertBefore(Class_ $classNode, Node $node, $key): void
{
Arrays::insertBefore($classNode->stmts, $key, [
'before_' . $key => $node
]);
}
}

View File

@ -8,12 +8,23 @@ use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\TraitUse; use PhpParser\Node\Stmt\TraitUse;
use PhpParser\NodeTraverser; use PhpParser\NodeTraverser;
use PhpParser\NodeVisitorAbstract; use PhpParser\NodeVisitorAbstract;
use Rector\Builder\StatementGlue;
/** /**
* Reflects @link https://doc.nette.org/en/2.4/migration-2-4#toc-nette-smartobject * Reflects @link https://doc.nette.org/en/2.4/migration-2-4#toc-nette-smartobject
*/ */
final class DeprecatedParentClassToTraitNodeVisitor extends NodeVisitorAbstract final class DeprecatedParentClassToTraitNodeVisitor extends NodeVisitorAbstract
{ {
/**
* @var StatementGlue
*/
private $statementGlue;
public function __construct(StatementGlue $statementGlue)
{
$this->statementGlue = $statementGlue;
}
public function getParentClassName(): string public function getParentClassName(): string
{ {
return 'Nette\Object'; return 'Nette\Object';
@ -57,9 +68,15 @@ final class DeprecatedParentClassToTraitNodeVisitor extends NodeVisitorAbstract
// remove parent class // remove parent class
$classNode->extends = null; $classNode->extends = null;
// add new trait $traitUseNode = $this->createTraitUse($this->getTraitName());
$nameParts = explode('\\', $this->getTraitName()); $this->statementGlue->addAsFirstTrait($classNode, $traitUseNode);
$classNode->stmts[] = new TraitUse([ }
private function createTraitUse(string $traitName): TraitUse
{
$nameParts = explode('\\', $traitName);
return new TraitUse([
new FullyQualified($nameParts) new FullyQualified($nameParts)
]); ]);
} }

View File

@ -8,9 +8,13 @@ final class Test extends AbstractReconstructorTestCase
{ {
public function test(): void public function test(): void
{ {
// $this->doTestFileMatchesExpectedContent(
// __DIR__ . '/wrong/wrong.php.inc',
// __DIR__ . '/correct/correct.php.inc'
// );
$this->doTestFileMatchesExpectedContent( $this->doTestFileMatchesExpectedContent(
__DIR__ . '/wrong/wrong.php.inc', __DIR__ . '/wrong/wrong2.php.inc',
__DIR__ . '/correct/correct.php.inc' __DIR__ . '/correct/correct2.php.inc'
); );
} }
} }