mirror of https://github.com/rectorphp/rector.git
rename StateHolder, to TokenSwitcher
This commit is contained in:
parent
d8849f04cd
commit
7d5a1250eb
|
@ -1,21 +0,0 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\NodeTraverser;
|
||||
|
||||
final class StateHolder
|
||||
{
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $isAfterTraverseCalled = false;
|
||||
|
||||
public function setAfterTraverserIsCalled(): void
|
||||
{
|
||||
$this->isAfterTraverseCalled = true;
|
||||
}
|
||||
|
||||
public function isAfterTraverseCalled(): bool
|
||||
{
|
||||
return $this->isAfterTraverseCalled;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\NodeTraverser;
|
||||
|
||||
final class TokenSwitcher
|
||||
{
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $isEnabled = false;
|
||||
|
||||
public function enable(): void
|
||||
{
|
||||
$this->isEnabled = true;
|
||||
}
|
||||
|
||||
public function isEnabled(): bool
|
||||
{
|
||||
return $this->isEnabled;
|
||||
}
|
||||
}
|
|
@ -1,107 +0,0 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\NodeVisitor\DependencyInjection;
|
||||
|
||||
use PhpCsFixer\DocBlock\DocBlock;
|
||||
use PhpParser\Comment\Doc;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\Property;
|
||||
use PhpParser\NodeVisitorAbstract;
|
||||
use Rector\Builder\ConstructorMethodBuilder;
|
||||
|
||||
final class InjectAnnotationToConstructorNodeVisitor extends NodeVisitorAbstract
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private const ANNOTATION_INJECT = 'inject';
|
||||
|
||||
/**
|
||||
* @var ConstructorMethodBuilder
|
||||
*/
|
||||
private $constructorMethodBuilder;
|
||||
|
||||
public function __construct(ConstructorMethodBuilder $constructorMethodBuilder)
|
||||
{
|
||||
$this->constructorMethodBuilder = $constructorMethodBuilder;
|
||||
}
|
||||
|
||||
public function isCandidate(Node $node): bool
|
||||
{
|
||||
return $node instanceof Class_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when entering a node.
|
||||
*
|
||||
* Return value semantics:
|
||||
* * null
|
||||
* => $node stays as-is
|
||||
* * NodeTraverser::DONT_TRAVERSE_CHILDREN
|
||||
* => Children of $node are not traversed. $node stays as-is
|
||||
* * NodeTraverser::STOP_TRAVERSAL
|
||||
* => Traversal is aborted. $node stays as-is
|
||||
* * otherwise
|
||||
* => $node is set to the return value
|
||||
*
|
||||
* @return null|int|Node Replacement node (or special return value)
|
||||
*/
|
||||
public function enterNode(Node $node)
|
||||
{
|
||||
if ($node instanceof Class_) {
|
||||
return $this->reconstruct($node);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function reconstruct(Class_ $classNode): Node
|
||||
{
|
||||
foreach ($classNode->stmts as $classElementStatement) {
|
||||
if (! $classElementStatement instanceof Property) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$propertyNode = $classElementStatement;
|
||||
|
||||
$propertyDocBlock = $this->createDocBlockFromProperty($propertyNode);
|
||||
$injectAnnotations = $propertyDocBlock->getAnnotationsOfType(self::ANNOTATION_INJECT);
|
||||
if (! $injectAnnotations) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->removeInjectAnnotationFromProperty($propertyNode, $propertyDocBlock);
|
||||
$this->makePropertyPrivate($propertyNode);
|
||||
|
||||
$propertyType = $propertyDocBlock->getAnnotationsOfType('var')[0]
|
||||
->getTypes()[0];
|
||||
$propertyName = (string) $propertyNode->props[0]->name;
|
||||
|
||||
$this->constructorMethodBuilder->addPropertyAssignToClass($classNode, $propertyType, $propertyName);
|
||||
}
|
||||
|
||||
return $classNode;
|
||||
}
|
||||
|
||||
private function createDocBlockFromProperty(Property $propertyNode): DocBlock
|
||||
{
|
||||
return new DocBlock($propertyNode->getDocComment());
|
||||
}
|
||||
|
||||
private function makePropertyPrivate(Property $propertyNode): void
|
||||
{
|
||||
$propertyNode->flags = Class_::MODIFIER_PRIVATE;
|
||||
}
|
||||
|
||||
private function removeInjectAnnotationFromProperty(Property $propertyNode, DocBlock $propertyDocBlock): void
|
||||
{
|
||||
$injectAnnotations = $propertyDocBlock->getAnnotationsOfType(self::ANNOTATION_INJECT);
|
||||
|
||||
foreach ($injectAnnotations as $injectAnnotation) {
|
||||
$injectAnnotation->remove();
|
||||
}
|
||||
|
||||
$propertyNode->setDocComment(new Doc($propertyDocBlock->getContent()));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,127 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\NodeVisitor\DependencyInjection;
|
||||
|
||||
use PhpCsFixer\DocBlock\DocBlock;
|
||||
use PhpParser\Comment\Doc;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Stmt\Property;
|
||||
use PhpParser\NodeVisitorAbstract;
|
||||
use Rector\NodeTraverser\TokenSwitcher;
|
||||
|
||||
final class InjectAnnotationToConstructorRector extends NodeVisitorAbstract
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private const ANNOTATION_INJECT = 'inject';
|
||||
|
||||
/**
|
||||
* @var TokenSwitcher
|
||||
*/
|
||||
private $tokenSwitcher;
|
||||
|
||||
// /**
|
||||
// * @var ConstructorMethodBuilder
|
||||
// */
|
||||
// private $constructorMethodBuilder;
|
||||
//
|
||||
// public function __construct(ConstructorMethodBuilder $constructorMethodBuilder)
|
||||
// {
|
||||
// $this->constructorMethodBuilder = $constructorMethodBuilder;
|
||||
// }
|
||||
|
||||
public function __construct(TokenSwitcher $tokenSwitcher)
|
||||
{
|
||||
$this->tokenSwitcher = $tokenSwitcher;
|
||||
}
|
||||
|
||||
public function enterNode(Node $node): ?Node
|
||||
{
|
||||
if (! $this->isCandidate($node)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->reconstructProperty($node);
|
||||
}
|
||||
|
||||
public function isCandidate(Node $node): bool
|
||||
{
|
||||
if (! $node instanceof Property) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! $this->hasInjectAnnotation($node)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->tokenSwitcher->enable();
|
||||
return true;
|
||||
}
|
||||
|
||||
// private function reconstruct(Class_ $classNode): Node
|
||||
// {
|
||||
// dump($classNode);
|
||||
// die;
|
||||
//
|
||||
// foreach ($classNode->stmts as $classElementStatement) {
|
||||
// if (! $classElementStatement instanceof Property) {
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
// $propertyNode = $classElementStatement;
|
||||
//
|
||||
// $propertyDocBlock = $this->createDocBlockFromNode($propertyNode);
|
||||
// $injectAnnotations = $propertyDocBlock->getAnnotationsOfType(self::ANNOTATION_INJECT);
|
||||
// if (! $injectAnnotations) {
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
// $this->removeInjectAnnotationFromProperty($propertyNode, $propertyDocBlock);
|
||||
// $this->makePropertyPrivate($propertyNode);
|
||||
//
|
||||
// $propertyType = $propertyDocBlock->getAnnotationsOfType('var')[0]
|
||||
// ->getTypes()[0];
|
||||
// $propertyName = (string) $propertyNode->props[0]->name;
|
||||
//
|
||||
// $this->constructorMethodBuilder->addPropertyAssignToClass($classNode, $propertyType, $propertyName);
|
||||
// }
|
||||
//
|
||||
// return $classNode;
|
||||
// }
|
||||
|
||||
private function reconstructProperty($propertyNode): Property
|
||||
{
|
||||
$propertyDocBlock = $this->createDocBlockFromNode($propertyNode);
|
||||
$propertyNode = $this->removeInjectAnnotationFromProperty($propertyNode, $propertyDocBlock);
|
||||
|
||||
// $propertyNode->flags = Class_::MODIFIER_PRIVATE;
|
||||
|
||||
return $propertyNode;
|
||||
}
|
||||
|
||||
private function hasInjectAnnotation(Property $propertyNode): bool
|
||||
{
|
||||
$propertyDocBlock = $this->createDocBlockFromNode($propertyNode);
|
||||
|
||||
return (bool) $propertyDocBlock->getAnnotationsOfType(self::ANNOTATION_INJECT);
|
||||
}
|
||||
|
||||
private function createDocBlockFromNode(Node $node): DocBlock
|
||||
{
|
||||
return new DocBlock($node->getDocComment());
|
||||
}
|
||||
|
||||
private function removeInjectAnnotationFromProperty(Property $propertyNode, DocBlock $propertyDocBlock): Property
|
||||
{
|
||||
$injectAnnotations = $propertyDocBlock->getAnnotationsOfType(self::ANNOTATION_INJECT);
|
||||
|
||||
foreach ($injectAnnotations as $injectAnnotation) {
|
||||
$injectAnnotation->remove();
|
||||
}
|
||||
|
||||
$propertyNode->setDocComment(new Doc($propertyDocBlock->getContent()));
|
||||
|
||||
return $propertyNode;
|
||||
}
|
||||
}
|
|
@ -8,7 +8,7 @@ use PhpParser\NodeVisitorAbstract;
|
|||
use Rector\Builder\Class_\ClassPropertyCollector;
|
||||
use Rector\Builder\ConstructorMethodBuilder;
|
||||
use Rector\Builder\PropertyBuilder;
|
||||
use Rector\NodeTraverser\StateHolder;
|
||||
use Rector\NodeTraverser\TokenSwitcher;
|
||||
|
||||
/**
|
||||
* Add new propertis to class and to contructor.
|
||||
|
@ -31,20 +31,20 @@ final class AddPropertiesToClassNodeVisitor extends NodeVisitorAbstract
|
|||
private $newClassPropertyCollector;
|
||||
|
||||
/**
|
||||
* @var StateHolder
|
||||
* @var TokenSwitcher
|
||||
*/
|
||||
private $stateHolder;
|
||||
private $tokenSwitcher;
|
||||
|
||||
public function __construct(
|
||||
ConstructorMethodBuilder $constructorMethodBuilder,
|
||||
PropertyBuilder $propertyBuilder,
|
||||
ClassPropertyCollector $newClassPropertyCollector,
|
||||
StateHolder $stateHolder
|
||||
TokenSwitcher $tokenSwitcher
|
||||
) {
|
||||
$this->constructorMethodBuilder = $constructorMethodBuilder;
|
||||
$this->propertyBuilder = $propertyBuilder;
|
||||
$this->newClassPropertyCollector = $newClassPropertyCollector;
|
||||
$this->stateHolder = $stateHolder;
|
||||
$this->tokenSwitcher = $tokenSwitcher;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -68,7 +68,7 @@ final class AddPropertiesToClassNodeVisitor extends NodeVisitorAbstract
|
|||
$propertiesForClass = $this->newClassPropertyCollector->getPropertiesforClass($className);
|
||||
|
||||
foreach ($propertiesForClass as $propertyType => $propertyName) {
|
||||
$this->stateHolder->setAfterTraverserIsCalled();
|
||||
$this->tokenSwitcher->enable();
|
||||
$this->constructorMethodBuilder->addPropertyAssignToClass($classNode, $propertyType, $propertyName);
|
||||
$this->propertyBuilder->addPropertyToClass($classNode, $propertyType, $propertyName);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ use PhpParser\Node\Stmt\Class_;
|
|||
use PhpParser\Node\Stmt\TraitUse;
|
||||
use Rector\Builder\StatementGlue;
|
||||
use Rector\Deprecation\SetNames;
|
||||
use Rector\NodeTraverser\TokenSwitcher;
|
||||
use Rector\Rector\AbstractRector;
|
||||
|
||||
/**
|
||||
|
@ -20,9 +21,15 @@ final class NetteObjectToSmartTraitRector extends AbstractRector
|
|||
*/
|
||||
private $statementGlue;
|
||||
|
||||
public function __construct(StatementGlue $statementGlue)
|
||||
/**
|
||||
* @var TokenSwitcher
|
||||
*/
|
||||
private $tokenSwitcher;
|
||||
|
||||
public function __construct(StatementGlue $statementGlue, TokenSwitcher $tokenSwitcher)
|
||||
{
|
||||
$this->statementGlue = $statementGlue;
|
||||
$this->tokenSwitcher = $tokenSwitcher;
|
||||
}
|
||||
|
||||
public function getSetName(): string
|
||||
|
@ -47,6 +54,7 @@ final class NetteObjectToSmartTraitRector extends AbstractRector
|
|||
return false;
|
||||
}
|
||||
|
||||
$this->tokenSwitcher->enable();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -58,12 +66,12 @@ final class NetteObjectToSmartTraitRector extends AbstractRector
|
|||
*/
|
||||
public function refactor($classNode): ?Node
|
||||
{
|
||||
// remove parent class
|
||||
$classNode->extends = null;
|
||||
|
||||
$traitUseNode = $this->createTraitUse('Nette\SmartObject');
|
||||
$this->statementGlue->addAsFirstTrait($classNode, $traitUseNode);
|
||||
|
||||
// remove parent class
|
||||
$classNode->extends = null;
|
||||
|
||||
return $classNode;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ namespace Rector\Testing\Application;
|
|||
use PhpParser\Lexer;
|
||||
use PhpParser\NodeTraverser;
|
||||
use PhpParser\Parser;
|
||||
use Rector\NodeTraverser\TokenSwitcher;
|
||||
use Rector\Printer\FormatPerservingPrinter;
|
||||
use SplFileInfo;
|
||||
|
||||
|
@ -30,16 +31,23 @@ final class FileReconstructor
|
|||
*/
|
||||
private $nodeTraverser;
|
||||
|
||||
/**
|
||||
* @var TokenSwitcher
|
||||
*/
|
||||
private $tokenSwitcher;
|
||||
|
||||
public function __construct(
|
||||
Parser $parser,
|
||||
FormatPerservingPrinter $codeStyledPrinter,
|
||||
Lexer $lexer,
|
||||
NodeTraverser $nodeTraverser
|
||||
NodeTraverser $nodeTraverser,
|
||||
TokenSwitcher $tokenSwitcher
|
||||
) {
|
||||
$this->parser = $parser;
|
||||
$this->codeStyledPrinter = $codeStyledPrinter;
|
||||
$this->lexer = $lexer;
|
||||
$this->nodeTraverser = $nodeTraverser;
|
||||
$this->tokenSwitcher = $tokenSwitcher;
|
||||
}
|
||||
|
||||
// ref: https://github.com/nikic/PHP-Parser/issues/344#issuecomment-298162516
|
||||
|
@ -51,6 +59,10 @@ final class FileReconstructor
|
|||
$oldTokens = $this->lexer->getTokens();
|
||||
$newStmts = $this->nodeTraverser->traverse($oldStmts);
|
||||
|
||||
if ($this->tokenSwitcher->isEnabled()) {
|
||||
[$oldStmts, $newStmts] = [$newStmts, $oldStmts];
|
||||
}
|
||||
|
||||
return $this->codeStyledPrinter->printToString($newStmts, $oldStmts, $oldTokens);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\NodeVisitor\DependencyInjection\InjectAnnotationToConstructorReconstructor;
|
||||
namespace Rector\Tests\NodeVisitor\DependencyInjection\InjectAnnotationToConstructorRector;
|
||||
|
||||
use Rector\Testing\PHPUnit\AbstractReconstructorTestCase;
|
||||
|
|
@ -6,10 +6,12 @@ class ClassWithInjects
|
|||
* @var stdClass
|
||||
*/
|
||||
private $property;
|
||||
|
||||
/**
|
||||
* @var DateTimeInterface
|
||||
*/
|
||||
private $otherProperty;
|
||||
|
||||
public function __construct(stdClass $property, DateTimeInterface $otherProperty)
|
||||
{
|
||||
$this->property = $property;
|
Loading…
Reference in New Issue