mirror of
https://github.com/rectorphp/rector.git
synced 2025-02-15 13:25:30 +01:00
Merge pull request #2065 from rectorphp/allow-private-ctor-override-for-static-factory
[CodingStyle] Allow private ctor override for static factory
This commit is contained in:
commit
f0222eaebf
@ -3,7 +3,9 @@
|
||||
namespace Rector\CodingStyle\Rector\ClassMethod;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\New_;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PhpParser\Node\Stmt\Return_;
|
||||
use PHPStan\Analyser\Scope;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\Rector\AbstractRector;
|
||||
@ -12,6 +14,8 @@ use Rector\RectorDefinition\RectorDefinition;
|
||||
use ReflectionMethod;
|
||||
|
||||
/**
|
||||
* @see https://3v4l.org/RFYmn
|
||||
*
|
||||
* @see \Rector\CodingStyle\Tests\Rector\ClassMethod\MakeInheritedMethodVisibilitySameAsParentRector\MakeInheritedMethodVisibilitySameAsParentRectorTest
|
||||
*/
|
||||
final class MakeInheritedMethodVisibilitySameAsParentRector extends AbstractRector
|
||||
@ -93,6 +97,10 @@ PHP
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($this->isConstructorWithStaticFactory($node, $methodName)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->changeClassMethodVisibilityBasedOnReflectionMethod($node, $parentReflectionMethod);
|
||||
|
||||
return $node;
|
||||
@ -139,4 +147,72 @@ PHP
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parent constructor visibility override is allowed only since PHP 7.2+
|
||||
* @see https://3v4l.org/RFYmn
|
||||
*/
|
||||
private function isConstructorWithStaticFactory(ClassMethod $classMethod, string $methodName): bool
|
||||
{
|
||||
if (! $this->isAtLeastPhpVersion('7.2')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($methodName !== '__construct') {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @var Node\Stmt\Class_|null $class */
|
||||
$class = $classMethod->getAttribute(AttributeKey::CLASS_NODE);
|
||||
if ($class === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($class->getMethods() as $iteratedClassMethod) {
|
||||
if (! $iteratedClassMethod->isPublic()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! $iteratedClassMethod->isStatic()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$isStaticSelfFactory = $this->isStaticSelfFactory($iteratedClassMethod);
|
||||
|
||||
if ($isStaticSelfFactory === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks for:
|
||||
* public static someMethod() { return new self(); }
|
||||
*/
|
||||
private function isStaticSelfFactory(ClassMethod $classMethod): bool
|
||||
{
|
||||
if (! $classMethod->isPublic()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! $classMethod->isStatic()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (bool) $this->betterNodeFinder->findFirst($classMethod, function (Node $node): bool {
|
||||
if (! $node instanceof Return_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! $node->expr instanceof New_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->isName($node->expr->class, 'self');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\CodingStyle\Tests\Rector\ClassMethod\MakeInheritedMethodVisibilitySameAsParentRector\Fixture;
|
||||
|
||||
class SkipStaticCtor extends ParentWithPublicConstructor
|
||||
{
|
||||
protected function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public static function create()
|
||||
{
|
||||
return new self();
|
||||
}
|
||||
}
|
||||
|
||||
class ParentWithPublicConstructor
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\CodingStyle\Tests\Rector\ClassMethod\MakeInheritedMethodVisibilitySameAsParentRector;
|
||||
|
||||
use Iterator;
|
||||
use Rector\CodingStyle\Rector\ClassMethod\MakeInheritedMethodVisibilitySameAsParentRector;
|
||||
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
|
||||
final class SkipParentConstructOverrideInPHP72Test extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @requires PHP >= 7.2
|
||||
* @see https://phpunit.readthedocs.io/en/8.3/incomplete-and-skipped-tests.html#incomplete-and-skipped-tests-requires-tables-api
|
||||
*
|
||||
* @dataProvider provideDataForTest()
|
||||
*/
|
||||
public function test(string $file): void
|
||||
{
|
||||
$this->doTestFile($file);
|
||||
}
|
||||
|
||||
public function provideDataForTest(): Iterator
|
||||
{
|
||||
yield [__DIR__ . '/Fixture/skip_static_ctor.php.inc'];
|
||||
}
|
||||
|
||||
protected function getRectorClass(): string
|
||||
{
|
||||
return MakeInheritedMethodVisibilitySameAsParentRector::class;
|
||||
}
|
||||
|
||||
protected function getPhpVersion(): string
|
||||
{
|
||||
return '7.2';
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user