mirror of
https://github.com/rectorphp/rector.git
synced 2025-01-17 21:38:22 +01:00
[SOLID] Add FinalizeClassesWithoutChildrenRector
This commit is contained in:
parent
14c3251887
commit
c1d0bd1556
@ -61,7 +61,8 @@
|
||||
"Rector\\PhpSpecToPHPUnit\\": "packages/PhpSpecToPHPUnit/src",
|
||||
"Rector\\Shopware\\": "packages/Shopware/src",
|
||||
"Rector\\NetteTesterToPHPUnit\\": "packages/NetteTesterToPHPUnit/src",
|
||||
"Rector\\Nette\\": "packages/Nette/src"
|
||||
"Rector\\Nette\\": "packages/Nette/src",
|
||||
"Rector\\SOLID\\": "packages/SOLID/src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
@ -94,7 +95,8 @@
|
||||
"Rector\\PHPStanExtensions\\": "utils/PHPStanExtensions/src",
|
||||
"Rector\\Shopware\\Tests\\": "packages/Shopware/tests",
|
||||
"Rector\\NetteTesterToPHPUnit\\Tests\\": "packages/NetteTesterToPHPUnit/tests",
|
||||
"Rector\\Nette\\Tests\\": "packages/Nette/tests"
|
||||
"Rector\\Nette\\Tests\\": "packages/Nette/tests",
|
||||
"Rector\\SOLID\\Tests\\": "packages/SOLID/tests"
|
||||
},
|
||||
"classmap": [
|
||||
"packages/Symfony/tests/Rector/FrameworkBundle/AbstractToConstructorInjectionRectorSource",
|
||||
@ -138,4 +140,4 @@
|
||||
"dev-master": "0.5-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
2
config/level/solid/solid.yaml
Normal file
2
config/level/solid/solid.yaml
Normal file
@ -0,0 +1,2 @@
|
||||
services:
|
||||
Rector\SOLID\Rector\Class_\FinalizeClassesWithoutChildrenRector: ~
|
@ -200,4 +200,9 @@ final class ClassLikeNodeCollector
|
||||
|
||||
return $classNodes;
|
||||
}
|
||||
|
||||
public function hasClassChildren(string $class): bool
|
||||
{
|
||||
return $this->findChildrenOfClass($class) !== [];
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,99 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\SOLID\Rector\Class_;
|
||||
|
||||
use Nette\Utils\Strings;
|
||||
use PhpParser\Node;
|
||||
use Rector\NodeTypeResolver\Application\ClassLikeNodeCollector;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\RectorDefinition\CodeSample;
|
||||
use Rector\RectorDefinition\RectorDefinition;
|
||||
|
||||
final class FinalizeClassesWithoutChildrenRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @var ClassLikeNodeCollector
|
||||
*/
|
||||
private $classLikeNodeCollector;
|
||||
|
||||
public function __construct(ClassLikeNodeCollector $classLikeNodeCollector)
|
||||
{
|
||||
$this->classLikeNodeCollector = $classLikeNodeCollector;
|
||||
}
|
||||
|
||||
public function getDefinition(): RectorDefinition
|
||||
{
|
||||
return new RectorDefinition('Finalize every class that has no children', [
|
||||
new CodeSample(
|
||||
<<<'CODE_SAMPLE'
|
||||
class FirstClass
|
||||
{
|
||||
}
|
||||
|
||||
class SecondClass
|
||||
{
|
||||
}
|
||||
|
||||
class ThirdClass extends SecondClass
|
||||
{
|
||||
}
|
||||
CODE_SAMPLE
|
||||
,
|
||||
<<<'CODE_SAMPLE'
|
||||
final class FirstClass
|
||||
{
|
||||
}
|
||||
|
||||
class SecondClass
|
||||
{
|
||||
}
|
||||
|
||||
final class ThirdClass extends SecondClass
|
||||
{
|
||||
}
|
||||
CODE_SAMPLE
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [Node\Stmt\Class_::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Node\Stmt\Class_ $node
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
if ($node->isFinal() || $node->isAbstract() || $node->isAnonymous()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($this->isDoctrineEntity($node)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @var string $class */
|
||||
$class = $this->getName($node);
|
||||
if ($this->classLikeNodeCollector->hasClassChildren($class)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$node->flags |= Node\Stmt\Class_::MODIFIER_FINAL;
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
private function isDoctrineEntity(Node $node): bool
|
||||
{
|
||||
if ($node->getDocComment() === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Strings::contains($node->getDocComment()->getText(), 'Entity');
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\SOLID\Tests\Rector\Class_\FinalizeClassesWithoutChildrenRector;
|
||||
|
||||
use Rector\SOLID\Rector\Class_\FinalizeClassesWithoutChildrenRector;
|
||||
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
|
||||
final class FinalizeClassesWithoutChildrenRectorTest extends AbstractRectorTestCase
|
||||
{
|
||||
public function test(): void
|
||||
{
|
||||
$this->doTestFiles([
|
||||
__DIR__ . '/Fixture/fixture.php.inc',
|
||||
__DIR__ . '/Fixture/skip.php.inc',
|
||||
__DIR__ . '/Fixture/entity.php.inc',
|
||||
]);
|
||||
}
|
||||
|
||||
protected function getRectorClass(): string
|
||||
{
|
||||
return FinalizeClassesWithoutChildrenRector::class;
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\SOLID\Tests\Rector\Class_\FinalizeClassesWithoutChildrenRector\Fixture;
|
||||
|
||||
/**
|
||||
* @ORM\Entity
|
||||
*/
|
||||
class Product
|
||||
{
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\SOLID\Tests\Rector\Class_\FinalizeClassesWithoutChildrenRector\Fixture;
|
||||
|
||||
class FirstClass
|
||||
{
|
||||
}
|
||||
|
||||
class SecondClass
|
||||
{
|
||||
}
|
||||
|
||||
class ThirdClass extends SecondClass
|
||||
{
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\SOLID\Tests\Rector\Class_\FinalizeClassesWithoutChildrenRector\Fixture;
|
||||
|
||||
final class FirstClass
|
||||
{
|
||||
}
|
||||
|
||||
class SecondClass
|
||||
{
|
||||
}
|
||||
|
||||
final class ThirdClass extends SecondClass
|
||||
{
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\SOLID\Tests\Rector\Class_\FinalizeClassesWithoutChildrenRector\Fixture;
|
||||
|
||||
abstract class SkipAbstractClass
|
||||
{
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user