Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions config/level/symfony/symfony43.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,7 @@ services:
name: 'context'
default_value: []
# type: array

Rector\Rector\ClassMethod\AddMethodParentCallRector:
Symfony\Component\EventDispatcher\EventDispatcher:
- '__construct'
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public function test(): void
{
$this->doTestFiles([
__DIR__ . '/Fixture/fixture.php.inc',
__DIR__ . '/Fixture/static_call.php.inc',
__DIR__ . '/Fixture/escape_nette_static_call.php.inc',
__DIR__ . '/Fixture/skip_concat.php.inc',
]);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ namespace Rector\CodingStyle\Tests\Rector\FuncCall\ConsistentPregDelimiterRector

use Nette\Utils\Strings;

class StaticCall
class EscapeNetteStaticCall
{
public function run($value)
{
Expand All @@ -20,7 +20,7 @@ namespace Rector\CodingStyle\Tests\Rector\FuncCall\ConsistentPregDelimiterRector

use Nette\Utils\Strings;

class StaticCall
class EscapeNetteStaticCall
{
public function run($value)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
use Rector\PhpParser\Parser\Parser;
use Rector\PhpParser\Printer\BetterStandardPrinter;
use Rector\PhpParser\Printer\FormatPerservingPrinter;
use Rector\Rector\AbstractRectorTrait;
use Rector\Rector\AbstractRector\AbstractRectorTrait;
use Symplify\PackageBuilder\FileSystem\SmartFileInfo;
use TypeError;

Expand Down
1 change: 1 addition & 0 deletions src/Rector/AbstractRector.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use Rector\Contract\Rector\PhpRectorInterface;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\Php\PhpVersionProvider;
use Rector\Rector\AbstractRector\AbstractRectorTrait;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symplify\PackageBuilder\FileSystem\SmartFileInfo;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php declare(strict_types=1);

namespace Rector\Rector;
namespace Rector\Rector\AbstractRector;

trait AbstractRectorTrait
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php declare(strict_types=1);

namespace Rector\Rector;
namespace Rector\Rector\AbstractRector;

use PhpParser\Node;
use Rector\Application\AppliedRectorCollector;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php declare(strict_types=1);

namespace Rector\Rector;
namespace Rector\Rector\AbstractRector;

use PhpParser\Node;
use Rector\PhpParser\Node\BetterNodeFinder;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php declare(strict_types=1);

namespace Rector\Rector;
namespace Rector\Rector\AbstractRector;

use PhpParser\Node;
use Rector\PhpParser\NodeTraverser\CallableNodeTraverser;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php declare(strict_types=1);

namespace Rector\Rector;
namespace Rector\Rector\AbstractRector;

use PhpParser\Node;
use Rector\PhpParser\Node\Manipulator\ConstFetchManipulator;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php declare(strict_types=1);

namespace Rector\Rector;
namespace Rector\Rector\AbstractRector;

use PhpParser\Node;
use Rector\PhpParser\Node\Resolver\NameResolver;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php declare(strict_types=1);

namespace Rector\Rector;
namespace Rector\Rector\AbstractRector;

use PhpParser\Node;
use PhpParser\Node\Stmt\Class_;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php declare(strict_types=1);

namespace Rector\Rector;
namespace Rector\Rector\AbstractRector;

use PhpParser\Node;
use PhpParser\Node\Arg;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php declare(strict_types=1);

namespace Rector\Rector;
namespace Rector\Rector\AbstractRector;

use PhpParser\Node;
use PHPStan\Type\Type;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php declare(strict_types=1);

namespace Rector\Rector;
namespace Rector\Rector\AbstractRector;

use PhpParser\Node\Expr;
use Rector\PhpParser\Node\Value\ValueResolver;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php declare(strict_types=1);

namespace Rector\Rector;
namespace Rector\Rector\AbstractRector;

use PhpParser\Node;
use PhpParser\Node\Stmt\Class_;
Expand Down
138 changes: 138 additions & 0 deletions src/Rector/ClassMethod/AddMethodParentCallRector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
<?php declare(strict_types=1);

namespace Rector\Rector\ClassMethod;

use PhpParser\Node;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Expression;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\Rector\AbstractRector;
use Rector\RectorDefinition\CodeSample;
use Rector\RectorDefinition\RectorDefinition;

final class AddMethodParentCallRector extends AbstractRector
{
/**
* @var mixed[]
*/
private $methodsByParentTypes = [];

/**
* @param mixed[] $methodsByParentTypes
*/
public function __construct(array $methodsByParentTypes = [])
{
$this->methodsByParentTypes = $methodsByParentTypes;
}

public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Add method parent call, in case new parent method is added', [
new CodeSample(
<<<'CODE_SAMPLE'
class SunshineCommand extends ParentClassWithNewConstructor
{
public function __construct()
{
$value = 5;
}
}
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
class SunshineCommand extends ParentClassWithNewConstructor
{
public function __construct()
{
$value = 5;

parent::__construct();
}
}
CODE_SAMPLE
),
]);
}

/**
* @return string[]
*/
public function getNodeTypes(): array
{
return [ClassMethod::class];
}

/**
* @param ClassMethod $node
*/
public function refactor(Node $node): ?Node
{
$class = $node->getAttribute(AttributeKey::CLASS_NODE);
if ($class === null) {
return null;
}

/** @var string $className */
$className = $node->getAttribute(AttributeKey::CLASS_NAME);

foreach ($this->methodsByParentTypes as $type => $methods) {
if (! $this->isType($class, $type)) {
continue;
}

// not itself
if ($className === $type) {
continue;
}

foreach ($methods as $method) {
if ($this->shouldSkipMethod($node, $method)) {
continue;
}

$node->stmts[] = $this->createParentStaticCall($method);

return $node;
}
}

return null;
}

/**
* Looks for "parent::<methodName>
*/
private function hasParentCallOfMethod(Node\Stmt\ClassMethod $classMethod, string $method): bool
{
return (bool) $this->betterNodeFinder->findFirst((array) $classMethod->stmts, function (Node $node) use (
$method
): bool {
if (! $node instanceof StaticCall) {
return false;
}

if (! $this->isName($node->class, 'parent')) {
return false;
}

return $this->isName($node, $method);
});
}

private function createParentStaticCall(string $method): Expression
{
$parentStaticCall = new StaticCall(new Node\Name('parent'), new Node\Identifier($method));

return new Expression($parentStaticCall);
}

private function shouldSkipMethod(ClassMethod $classMethod, string $method): bool
{
if (! $this->isName($classMethod, $method)) {
return true;
}

return $this->hasParentCallOfMethod($classMethod, $method);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php declare(strict_types=1);

namespace Rector\Tests\Rector\ClassMethod\AddMethodParentCallRector;

use Rector\Rector\ClassMethod\AddMethodParentCallRector;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
use Rector\Tests\Rector\ClassMethod\AddMethodParentCallRector\Source\ParentClassWithNewConstructor;

final class AddMethodParentCallRectorTest extends AbstractRectorTestCase
{
public function test(): void
{
$this->doTestFiles([
__DIR__ . '/Fixture/fixture.php.inc',
__DIR__ . '/Fixture/skip_already_has.php.inc',
]);
}

/**
* @return mixed[]
*/
protected function getRectorsWithConfiguration(): array
{
return [
AddMethodParentCallRector::class => [
'$methodsByParentTypes' => [
ParentClassWithNewConstructor::class => ['__construct'],
],
],
];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace Rector\Tests\Rector\ClassMethod\AddMethodParentCallRector\Fixture;

use Rector\Tests\Rector\ClassMethod\AddMethodParentCallRector\Source\ParentClassWithNewConstructor;

class SunshineCommand extends ParentClassWithNewConstructor
{
public function __construct()
{
$value = 5;
}
}

?>
-----
<?php

namespace Rector\Tests\Rector\ClassMethod\AddMethodParentCallRector\Fixture;

use Rector\Tests\Rector\ClassMethod\AddMethodParentCallRector\Source\ParentClassWithNewConstructor;

class SunshineCommand extends ParentClassWithNewConstructor
{
public function __construct()
{
$value = 5;
parent::__construct();
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace Rector\Tests\Rector\ClassMethod\AddMethodParentCallRector\Fixture;

use Rector\Tests\Rector\ClassMethod\AddMethodParentCallRector\Source\ParentClassWithNewConstructor;

class SkipAlreadyHas extends ParentClassWithNewConstructor
{
public function __construct()
{
$value = 5;

parent::__construct();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php declare(strict_types=1);

namespace Rector\Tests\Rector\ClassMethod\AddMethodParentCallRector\Source;

class ParentClassWithNewConstructor
{
/**
* @var int
*/
private $defaultValue;

public function __construct()
{
$this->defaultValue = 5;
}
}