Decopule ChildClassMethodDecorator, and DependencyClassMethodDecorator (#600)

This commit is contained in:
Tomas Votruba 2021-08-06 10:39:44 +02:00 committed by GitHub
parent c2acf79190
commit 45766e1d95
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 25 additions and 176 deletions

View File

@ -24,11 +24,11 @@
"phpstan/phpstan-phpunit": "^0.12.21",
"rector/extension-installer": "^0.11.0",
"rector/rector-cakephp": "^0.11.3",
"rector/rector-doctrine": "^0.11.13",
"rector/rector-laravel": "^0.11.4",
"rector/rector-nette": "^0.11.16",
"rector/rector-phpunit": "^0.11.6",
"rector/rector-symfony": "^0.11.12",
"rector/rector-doctrine": "^0.11.15",
"rector/rector-laravel": "^0.11.5",
"rector/rector-nette": "^0.11.21",
"rector/rector-phpunit": "^0.11.7",
"rector/rector-symfony": "^0.11.16",
"rector/rector-phpoffice": "^0.11.2",
"sebastian/diff": "^4.0.4",
"ssch/typo3-rector": "^0.11.22",

View File

@ -1,92 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\NodeCollector\NodeCollector;
use PhpParser\Node\Stmt\Class_;
use PHPStan\Reflection\ReflectionProvider;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\NodeAnalyzer\ClassAnalyzer;
use Rector\NodeTypeResolver\Node\AttributeKey;
/**
* This service contains all the parsed nodes. E.g. all the functions, method call, classes, static calls etc. It's
* useful in case of context analysis, e.g. find all the usage of class method to detect, if the method is used.
*
* @deprecated
*/
final class NodeRepository
{
/**
* @deprecated Not reliable, as only works with so-far parsed classes
* @var Class_[]
*/
private array $classes = [];
public function __construct(
private ClassAnalyzer $classAnalyzer,
private ReflectionProvider $reflectionProvider,
) {
}
public function collectClass(Class_ $class): void
{
if ($this->classAnalyzer->isAnonymousClass($class)) {
return;
}
$className = $class->getAttribute(AttributeKey::CLASS_NAME);
if ($className === null) {
throw new ShouldNotHappenException();
}
$this->classes[$className] = $class;
}
/**
* @param class-string $className
* @return Class_[]
* @deprecated Use static reflection instead
*/
public function findChildrenOfClass(string $className): array
{
$childrenClasses = [];
// @todo refactor to reflection
foreach ($this->classes as $class) {
$currentClassName = $class->getAttribute(AttributeKey::CLASS_NAME);
if ($currentClassName === null) {
continue;
}
if (! $this->isChildOrEqualClassLike($className, $currentClassName)) {
continue;
}
$childrenClasses[] = $class;
}
return $childrenClasses;
}
private function isChildOrEqualClassLike(string $desiredClass, string $currentClassName): bool
{
if (! $this->reflectionProvider->hasClass($desiredClass)) {
return false;
}
if (! $this->reflectionProvider->hasClass($currentClassName)) {
return false;
}
$desiredClassReflection = $this->reflectionProvider->getClass($desiredClass);
$currentClassReflection = $this->reflectionProvider->getClass($currentClassName);
if (! $currentClassReflection->isSubclassOf($desiredClassReflection->getName())) {
return false;
}
return $currentClassName !== $desiredClass;
}
}

View File

@ -1,27 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\NodeCollector\NodeVisitor;
use PhpParser\Node;
use PhpParser\Node\Stmt\Class_;
use PhpParser\NodeVisitorAbstract;
use Rector\NodeCollector\NodeCollector\NodeRepository;
final class NodeCollectorNodeVisitor extends NodeVisitorAbstract
{
public function __construct(
private NodeRepository $nodeRepository,
) {
}
public function enterNode(Node $node)
{
if ($node instanceof Class_) {
$this->nodeRepository->collectClass($node);
}
return null;
}
}

View File

@ -10,7 +10,6 @@ use PhpParser\NodeVisitor\CloningVisitor;
use PhpParser\NodeVisitor\NameResolver;
use PhpParser\NodeVisitor\NodeConnectingVisitor;
use Rector\Core\ValueObject\Application\File;
use Rector\NodeCollector\NodeVisitor\NodeCollectorNodeVisitor;
use Rector\NodeTypeResolver\NodeVisitor\FileNodeVisitor;
use Rector\NodeTypeResolver\NodeVisitor\FunctionLikeParamArgPositionNodeVisitor;
use Rector\NodeTypeResolver\NodeVisitor\FunctionMethodAndClassNodeVisitor;
@ -24,7 +23,6 @@ final class NodeScopeAndMetadataDecorator
private CloningVisitor $cloningVisitor,
private FunctionMethodAndClassNodeVisitor $functionMethodAndClassNodeVisitor,
private NamespaceNodeVisitor $namespaceNodeVisitor,
private NodeCollectorNodeVisitor $nodeCollectorNodeVisitor,
private PHPStanNodeScopeResolver $phpStanNodeScopeResolver,
private StatementNodeVisitor $statementNodeVisitor,
private NodeConnectingVisitor $nodeConnectingVisitor,
@ -78,7 +76,6 @@ final class NodeScopeAndMetadataDecorator
// this split is needed, so nodes have names, classes and namespaces
$nodeTraverser = new NodeTraverser();
$nodeTraverser->addVisitor($this->statementNodeVisitor);
$nodeTraverser->addVisitor($this->nodeCollectorNodeVisitor);
return $nodeTraverser->traverse($nodes);
}

View File

@ -16,6 +16,7 @@ use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Type\Type;
use Rector\Core\NodeAnalyzer\PropertyPresenceChecker;
use Rector\Core\NodeManipulator\Dependency\DependencyClassMethodDecorator;
use Rector\Core\Php\PhpVersionProvider;
use Rector\Core\PhpParser\Node\NodeFactory;
use Rector\Core\ValueObject\MethodName;
@ -29,7 +30,6 @@ use Rector\TypeDeclaration\NodeAnalyzer\AutowiredClassMethodOrPropertyAnalyzer;
final class ClassDependencyManipulator
{
public function __construct(
private ChildAndParentClassManipulator $childAndParentClassManipulator,
private ClassInsertManipulator $classInsertManipulator,
private ClassMethodAssignManipulator $classMethodAssignManipulator,
private NodeFactory $nodeFactory,
@ -38,7 +38,8 @@ final class ClassDependencyManipulator
private PropertyPresenceChecker $propertyPresenceChecker,
private NodeNameResolver $nodeNameResolver,
private NodesToRemoveCollector $nodesToRemoveCollector,
private AutowiredClassMethodOrPropertyAnalyzer $autowiredClassMethodOrPropertyAnalyzer
private AutowiredClassMethodOrPropertyAnalyzer $autowiredClassMethodOrPropertyAnalyzer,
private DependencyClassMethodDecorator $dependencyClassMethodDecorator
) {
}
@ -97,8 +98,11 @@ final class ClassDependencyManipulator
/** @var Scope $scope */
$scope = $class->getAttribute(AttributeKey::SCOPE);
$this->childAndParentClassManipulator->completeParentConstructor($class, $constructorMethod, $scope);
$this->childAndParentClassManipulator->completeChildConstructors($class, $constructorMethod);
$this->dependencyClassMethodDecorator->decorateConstructorWithParentDependencies(
$class,
$constructorMethod,
$scope
);
}
/**
@ -162,8 +166,11 @@ final class ClassDependencyManipulator
/** @var Scope $scope */
$scope = $class->getAttribute(AttributeKey::SCOPE);
$this->childAndParentClassManipulator->completeParentConstructor($class, $constructClassMethod, $scope);
$this->childAndParentClassManipulator->completeChildConstructors($class, $constructClassMethod);
$this->dependencyClassMethodDecorator->decorateConstructorWithParentDependencies(
$class,
$constructClassMethod,
$scope
);
}
private function hasClassParentClassMethod(Class_ $class, string $methodName): bool

View File

@ -2,7 +2,7 @@
declare(strict_types=1);
namespace Rector\Core\NodeManipulator;
namespace Rector\Core\NodeManipulator\Dependency;
use PhpParser\Node;
use PhpParser\Node\Param;
@ -15,16 +15,14 @@ use Rector\Core\NodeAnalyzer\PromotedPropertyParamCleaner;
use Rector\Core\PhpParser\AstResolver;
use Rector\Core\PhpParser\Node\NodeFactory;
use Rector\Core\ValueObject\MethodName;
use Rector\NodeCollector\NodeCollector\NodeRepository;
use Rector\NodeNameResolver\NodeNameResolver;
use Symplify\Astral\NodeTraverser\SimpleCallableNodeTraverser;
final class ChildAndParentClassManipulator
final class DependencyClassMethodDecorator
{
public function __construct(
private NodeFactory $nodeFactory,
private NodeNameResolver $nodeNameResolver,
private NodeRepository $nodeRepository,
private PromotedPropertyParamCleaner $promotedPropertyParamCleaner,
private ReflectionProvider $reflectionProvider,
private AstResolver $astResolver,
@ -35,8 +33,11 @@ final class ChildAndParentClassManipulator
/**
* Add "parent::__construct(X, Y, Z)" where needed
*/
public function completeParentConstructor(Class_ $class, ClassMethod $classMethod, Scope $scope): void
{
public function decorateConstructorWithParentDependencies(
Class_ $class,
ClassMethod $classMethod,
Scope $scope
): void {
$className = $this->nodeNameResolver->getName($class);
if ($className === null) {
return;
@ -68,38 +69,6 @@ final class ChildAndParentClassManipulator
}
}
public function completeChildConstructors(Class_ $class, ClassMethod $constructorClassMethod): void
{
$className = $this->nodeNameResolver->getName($class);
if ($className === null) {
return;
}
$childClasses = $this->nodeRepository->findChildrenOfClass($className);
foreach ($childClasses as $childClass) {
$childConstructorClassMethod = $childClass->getMethod(MethodName::CONSTRUCT);
if (! $childConstructorClassMethod instanceof ClassMethod) {
continue;
}
// replicate parent parameters
$childConstructorClassMethod->params = array_merge(
$constructorClassMethod->params,
$childConstructorClassMethod->params
);
$parentConstructCallNode = $this->nodeFactory->createParentConstructWithParams(
$constructorClassMethod->params
);
$childConstructorClassMethod->stmts = array_merge(
[new Expression($parentConstructCallNode)],
(array) $childConstructorClassMethod->stmts
);
}
}
private function completeParentConstructorBasedOnParentNode(
ClassMethod $classMethod,
ClassMethod $parentClassMethod

View File

@ -37,7 +37,6 @@ use Rector\Core\PhpParser\Printer\BetterStandardPrinter;
use Rector\Core\Provider\CurrentFileProvider;
use Rector\Core\Validation\InfiniteLoopValidator;
use Rector\Core\ValueObject\Application\File;
use Rector\NodeCollector\NodeCollector\NodeRepository;
use Rector\NodeNameResolver\NodeNameResolver;
use Rector\NodeRemoval\NodeRemover;
use Rector\NodeTypeResolver\Node\AttributeKey;
@ -94,8 +93,6 @@ abstract class AbstractRector extends NodeVisitorAbstract implements PhpRectorIn
protected ValueResolver $valueResolver;
protected NodeRepository $nodeRepository;
protected BetterNodeFinder $betterNodeFinder;
protected NodeRemover $nodeRemover;
@ -161,7 +158,6 @@ abstract class AbstractRector extends NodeVisitorAbstract implements PhpRectorIn
CurrentNodeProvider $currentNodeProvider,
Skipper $skipper,
ValueResolver $valueResolver,
NodeRepository $nodeRepository,
BetterNodeFinder $betterNodeFinder,
NodeComparator $nodeComparator,
CurrentFileProvider $currentFileProvider,
@ -189,7 +185,6 @@ abstract class AbstractRector extends NodeVisitorAbstract implements PhpRectorIn
$this->currentNodeProvider = $currentNodeProvider;
$this->skipper = $skipper;
$this->valueResolver = $valueResolver;
$this->nodeRepository = $nodeRepository;
$this->betterNodeFinder = $betterNodeFinder;
$this->nodeComparator = $nodeComparator;
$this->currentFileProvider = $currentFileProvider;