Merge pull request #3505 from rectorphp/inject-parent-construct

add parent::__construct() in case of existing empty ctor
This commit is contained in:
Tomas Votruba 2020-06-10 00:22:53 +02:00 committed by GitHub
commit bd520cafd4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 34 additions and 19 deletions

View File

@ -18,7 +18,7 @@ final class ChildAndParentClassManipulator
/**
* @var string
*/
private const __CONSTRUCT = '__construct';
private const CONSTRUCT = '__construct';
/**
* @var NodeFactory
@ -71,7 +71,7 @@ final class ChildAndParentClassManipulator
}
// complete parent call for __construct()
if ($parentClassName !== '' && method_exists($parentClassName, self::__CONSTRUCT)) {
if ($parentClassName !== '' && method_exists($parentClassName, self::CONSTRUCT)) {
$parentConstructCallNode = $this->nodeFactory->createParentConstructWithParams([]);
$classMethod->stmts[] = new Expression($parentConstructCallNode);
}
@ -87,55 +87,49 @@ final class ChildAndParentClassManipulator
$childClassNodes = $this->classLikeParsedNodesFinder->findChildrenOfClass($className);
foreach ($childClassNodes as $childClassNode) {
if ($childClassNode->getMethod(self::__CONSTRUCT) === null) {
$childConstructorClassMethod = $childClassNode->getMethod(self::CONSTRUCT);
if ($childConstructorClassMethod === null) {
continue;
}
/** @var ClassMethod $childClassConstructorMethodNode */
$childClassConstructorMethodNode = $childClassNode->getMethod(self::__CONSTRUCT);
// replicate parent parameters
$childClassConstructorMethodNode->params = array_merge(
$childConstructorClassMethod->params = array_merge(
$constructorClassMethod->params,
$childClassConstructorMethodNode->params
$childConstructorClassMethod->params
);
$parentConstructCallNode = $this->nodeFactory->createParentConstructWithParams(
$constructorClassMethod->params
);
$childClassConstructorMethodNode->stmts = array_merge(
$childConstructorClassMethod->stmts = array_merge(
[new Expression($parentConstructCallNode)],
(array) $childClassConstructorMethodNode->stmts
(array) $childConstructorClassMethod->stmts
);
}
}
private function completeParentConstructorBasedOnParentNode(Class_ $parentClassNode, ClassMethod $classMethod): void
{
// iterate up?
$firstParentConstructMethodNode = $this->findFirstParentConstructor($parentClassNode);
if ($firstParentConstructMethodNode === null) {
return;
}
if ($firstParentConstructMethodNode->params === []) {
return;
}
// replicate parent parameters
$classMethod->params = array_merge($firstParentConstructMethodNode->params, $classMethod->params);
$parentConstructCallNode = $this->nodeFactory->createParentConstructWithParams(
$firstParentConstructMethodNode->params
);
$classMethod->stmts[] = new Expression($parentConstructCallNode);
}
private function findFirstParentConstructor(Class_ $classNode): ?ClassMethod
{
while ($classNode !== null) {
$constructMethodNode = $classNode->getMethod(self::__CONSTRUCT);
$constructMethodNode = $classNode->getMethod(self::CONSTRUCT);
if ($constructMethodNode !== null) {
return $constructMethodNode;
}

View File

@ -77,7 +77,7 @@ final class ClassDependencyManipulator
): void {
$constructorMethod = $classNode->getMethod(self::CONSTRUCTOR);
/** @var ClassMethod $constructorMethod */
/** @var ClassMethod|null $constructorMethod */
if ($constructorMethod !== null) {
$this->classMethodAssignManipulator->addParameterAndAssignToMethod(
$constructorMethod,

View File

@ -4,7 +4,7 @@ namespace Rector\Core\Tests\Rector\Architecture\DependencyInjection\AnnotatedPro
use Rector\Core\Tests\Rector\Architecture\DependencyInjection\AnnotatedPropertyInjectToConstructorInjectionRector\Source\SomeProductWithParent;
class ClassWithInjects6
class ClassWithParentWithConstructor extends SomeClassWithParent
{
/**
* @var SomeProductWithParent
@ -13,6 +13,16 @@ class ClassWithInjects6
protected $property;
}
class SomeClassWithParent
{
private $value;
public function __construct()
{
$this->value = '123';
}
}
?>
-----
<?php
@ -21,7 +31,7 @@ namespace Rector\Core\Tests\Rector\Architecture\DependencyInjection\AnnotatedPro
use Rector\Core\Tests\Rector\Architecture\DependencyInjection\AnnotatedPropertyInjectToConstructorInjectionRector\Source\SomeProductWithParent;
class ClassWithInjects6
class ClassWithParentWithConstructor extends SomeClassWithParent
{
/**
* @var SomeProductWithParent
@ -30,6 +40,17 @@ class ClassWithInjects6
public function __construct(\Rector\Core\Tests\Rector\Architecture\DependencyInjection\AnnotatedPropertyInjectToConstructorInjectionRector\Source\SomeProductWithParent $property)
{
$this->property = $property;
parent::__construct();
}
}
class SomeClassWithParent
{
private $value;
public function __construct()
{
$this->value = '123';
}
}