mirror of
https://github.com/rectorphp/rector.git
synced 2024-06-28 21:53:31 +00:00
Remove unused ClassLikeParentResolver (#385)
This commit is contained in:
parent
5f43d6b712
commit
0a616c462d
|
@ -48,10 +48,11 @@
|
|||
"symplify/smart-file-system": "^9.4.4",
|
||||
"symplify/symfony-php-config": "^9.4.4",
|
||||
"tracy/tracy": "^2.8",
|
||||
"webmozart/assert": "^1.10"
|
||||
"webmozart/assert": "^1.10",
|
||||
"cweagans/composer-patches": "^1.7",
|
||||
"symplify/vendor-patches": "^9.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"cweagans/composer-patches": "^1.7",
|
||||
"phpstan/extension-installer": "^1.1",
|
||||
"phpstan/phpstan-nette": "^0.12.19",
|
||||
"phpunit/phpunit": "^9.5",
|
||||
|
@ -64,7 +65,6 @@
|
|||
"symplify/phpstan-extensions": "^9.4.4",
|
||||
"symplify/phpstan-rules": "^9.4.4",
|
||||
"symplify/rule-doc-generator": "^9.4.4",
|
||||
"symplify/vendor-patches": "^9.4",
|
||||
"timeweb/phpstan-enum": "^2.3"
|
||||
},
|
||||
"replace": {
|
||||
|
|
|
@ -107,16 +107,6 @@ final class NodeRepository
|
|||
return $this->parsedNodeCollector->findClass($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use static reflection instead
|
||||
*
|
||||
* @param class-string $name
|
||||
*/
|
||||
public function findTrait(string $name): ?Trait_
|
||||
{
|
||||
return $this->parsedNodeCollector->findTrait($name);
|
||||
}
|
||||
|
||||
private function isChildOrEqualClassLike(string $desiredClass, ?string $currentClassName): bool
|
||||
{
|
||||
if ($currentClassName === null) {
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\Fixture;
|
||||
|
||||
use Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\Source\ClassWithParent;
|
||||
|
||||
abstract class AbstractParentClassWithParents
|
||||
{
|
||||
/**
|
||||
* @var ClassWithParent
|
||||
*/
|
||||
private $implement;
|
||||
|
||||
public function __construct(ClassWithParent $implement)
|
||||
{
|
||||
$this->implement = $implement;
|
||||
}
|
||||
}
|
||||
|
||||
class FirstChildClassWithParent extends AbstractParentClassWithParents
|
||||
{
|
||||
public function __construct(ClassWithParent $firstImplementer)
|
||||
{
|
||||
parent::__construct($firstImplementer);
|
||||
}
|
||||
}
|
||||
|
||||
class SecondChildClassWithParent extends AbstractParentClassWithParents
|
||||
{
|
||||
public function __construct(ClassWithParent $secondImplementer)
|
||||
{
|
||||
parent::__construct($secondImplementer);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\Fixture;
|
||||
|
||||
use Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\Source\ClassWithParent;
|
||||
|
||||
abstract class AbstractParentClassWithParents
|
||||
{
|
||||
/**
|
||||
* @var ClassWithParent
|
||||
*/
|
||||
private $implement;
|
||||
|
||||
public function injectAbstractParentClassWithParents(\Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\Source\ClassWithParent $classWithParent)
|
||||
{
|
||||
$this->classWithParent = $classWithParent;
|
||||
}
|
||||
}
|
||||
|
||||
class FirstChildClassWithParent extends AbstractParentClassWithParents
|
||||
{
|
||||
}
|
||||
|
||||
class SecondChildClassWithParent extends AbstractParentClassWithParents
|
||||
{
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,82 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\Fixture;
|
||||
|
||||
use Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\Source\AnotherDependency;
|
||||
use Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\Source\SomeDependency;
|
||||
|
||||
abstract class AbstractParentClassWithExtraDependency
|
||||
{
|
||||
/**
|
||||
* @var SomeDependency
|
||||
*/
|
||||
private $someDependency;
|
||||
|
||||
public function __construct(SomeDependency $someDependency)
|
||||
{
|
||||
$this->someDependency = $someDependency;
|
||||
}
|
||||
}
|
||||
|
||||
class FirstChildWithExtraDependency extends AbstractParentClassWithExtraDependency
|
||||
{
|
||||
/**
|
||||
* @var AnotherDependency
|
||||
*/
|
||||
private $anotherDependency;
|
||||
|
||||
public function __construct(SomeDependency $someDependency, AnotherDependency $anotherDependency)
|
||||
{
|
||||
parent::__construct($someDependency);
|
||||
$this->anotherDependency = $anotherDependency;
|
||||
}
|
||||
}
|
||||
|
||||
class SecondChildWithExtraDependency extends AbstractParentClassWithExtraDependency
|
||||
{
|
||||
public function __construct(SomeDependency $someDependency)
|
||||
{
|
||||
parent::__construct($someDependency);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\Fixture;
|
||||
|
||||
use Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\Source\AnotherDependency;
|
||||
use Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\Source\SomeDependency;
|
||||
|
||||
abstract class AbstractParentClassWithExtraDependency
|
||||
{
|
||||
/**
|
||||
* @var SomeDependency
|
||||
*/
|
||||
private $someDependency;
|
||||
|
||||
public function injectAbstractParentClassWithExtraDependency(\Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\Source\SomeDependency $someDependency)
|
||||
{
|
||||
$this->someDependency = $someDependency;
|
||||
}
|
||||
}
|
||||
|
||||
class FirstChildWithExtraDependency extends AbstractParentClassWithExtraDependency
|
||||
{
|
||||
/**
|
||||
* @var AnotherDependency
|
||||
*/
|
||||
private $anotherDependency;
|
||||
|
||||
public function __construct(AnotherDependency $anotherDependency)
|
||||
{
|
||||
$this->anotherDependency = $anotherDependency;
|
||||
}
|
||||
}
|
||||
|
||||
class SecondChildWithExtraDependency extends AbstractParentClassWithExtraDependency
|
||||
{
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,65 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\Fixture;
|
||||
|
||||
use Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\Source\SomeDependency;
|
||||
|
||||
abstract class AbstractParentClass
|
||||
{
|
||||
/**
|
||||
* @var SomeDependency
|
||||
*/
|
||||
private $someDependency;
|
||||
|
||||
public function __construct(SomeDependency $someDependency)
|
||||
{
|
||||
$this->someDependency = $someDependency;
|
||||
}
|
||||
}
|
||||
|
||||
class FirstChild extends AbstractParentClass
|
||||
{
|
||||
public function __construct(SomeDependency $someDependency)
|
||||
{
|
||||
parent::__construct($someDependency);
|
||||
}
|
||||
}
|
||||
|
||||
class SecondChild extends AbstractParentClass
|
||||
{
|
||||
public function __construct(SomeDependency $someDependency)
|
||||
{
|
||||
parent::__construct($someDependency);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\Fixture;
|
||||
|
||||
use Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\Source\SomeDependency;
|
||||
|
||||
abstract class AbstractParentClass
|
||||
{
|
||||
/**
|
||||
* @var SomeDependency
|
||||
*/
|
||||
private $someDependency;
|
||||
|
||||
public function injectAbstractParentClass(\Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\Source\SomeDependency $someDependency)
|
||||
{
|
||||
$this->someDependency = $someDependency;
|
||||
}
|
||||
}
|
||||
|
||||
class FirstChild extends AbstractParentClass
|
||||
{
|
||||
}
|
||||
|
||||
class SecondChild extends AbstractParentClass
|
||||
{
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,36 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\Fixture;
|
||||
|
||||
use Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\Source\FirstImplementer;
|
||||
use Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\Source\ImplementInterface;
|
||||
use Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\Source\SecondImplementer;
|
||||
|
||||
abstract class AbstractParentClassSkipDifferentImplementations
|
||||
{
|
||||
/**
|
||||
* @var ImplementInterface
|
||||
*/
|
||||
private $implement;
|
||||
|
||||
public function __construct(ImplementInterface $implement)
|
||||
{
|
||||
$this->implement = $implement;
|
||||
}
|
||||
}
|
||||
|
||||
class FirstChildDifferentImplementations extends AbstractParentClassSkipDifferentImplementations
|
||||
{
|
||||
public function __construct(FirstImplementer $firstImplementer)
|
||||
{
|
||||
parent::__construct($firstImplementer);
|
||||
}
|
||||
}
|
||||
|
||||
class SecondChildDifferentImplementations extends AbstractParentClassSkipDifferentImplementations
|
||||
{
|
||||
public function __construct(SecondImplementer $secondImplementer)
|
||||
{
|
||||
parent::__construct($secondImplementer);
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\Fixture;
|
||||
|
||||
use Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\Source\AnotherDependency;
|
||||
use Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\Source\SomeDependency;
|
||||
|
||||
abstract class AbstractParentClassSkipDifferent
|
||||
{
|
||||
/**
|
||||
* @var SomeDependency
|
||||
*/
|
||||
private $someDependency;
|
||||
|
||||
public function __construct(SomeDependency $someDependency)
|
||||
{
|
||||
$this->someDependency = $someDependency;
|
||||
}
|
||||
}
|
||||
|
||||
class FirstChildDifferentTypes extends AbstractParentClassSkipDifferent
|
||||
{
|
||||
private $anotherDependency;
|
||||
public function __construct(AnotherDependency $anotherDependency)
|
||||
{
|
||||
$this->anotherDependency = $anotherDependency;
|
||||
}
|
||||
}
|
||||
|
||||
class SecondChildDifferentTypes extends AbstractParentClassSkipDifferent
|
||||
{
|
||||
private $anotherDependency;
|
||||
public function __construct(AnotherDependency $anotherDependency)
|
||||
{
|
||||
$this->anotherDependency = $anotherDependency;
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\Fixture;
|
||||
|
||||
use Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\Source\SomeDependency;
|
||||
|
||||
abstract class AbstractParentClassSkipEmptyConstructor
|
||||
{
|
||||
/**
|
||||
* @var SomeDependency
|
||||
*/
|
||||
private $someDependency;
|
||||
|
||||
public function __construct(SomeDependency $someDependency)
|
||||
{
|
||||
$this->someDependency = $someDependency;
|
||||
}
|
||||
}
|
||||
|
||||
class FirstChildSkipEmptyConstructor extends AbstractParentClassSkipEmptyConstructor
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$value = 5;
|
||||
}
|
||||
}
|
||||
|
||||
class SecondChildSkipEmptyConstructor extends AbstractParentClassSkipEmptyConstructor
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$value = 15;
|
||||
}
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\FixtureSymfony;
|
||||
|
||||
use Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\Source\SomeDependency;
|
||||
|
||||
abstract class AbstractParentClass
|
||||
{
|
||||
/**
|
||||
* @var SomeDependency
|
||||
*/
|
||||
private $someDependency;
|
||||
|
||||
public function __construct(SomeDependency $someDependency)
|
||||
{
|
||||
$this->someDependency = $someDependency;
|
||||
}
|
||||
}
|
||||
|
||||
class FirstChild extends AbstractParentClass
|
||||
{
|
||||
public function __construct(SomeDependency $someDependency)
|
||||
{
|
||||
parent::__construct($someDependency);
|
||||
}
|
||||
}
|
||||
|
||||
class SecondChild extends AbstractParentClass
|
||||
{
|
||||
public function __construct(SomeDependency $someDependency)
|
||||
{
|
||||
parent::__construct($someDependency);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\FixtureSymfony;
|
||||
|
||||
use Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\Source\SomeDependency;
|
||||
|
||||
abstract class AbstractParentClass
|
||||
{
|
||||
/**
|
||||
* @var SomeDependency
|
||||
*/
|
||||
private $someDependency;
|
||||
|
||||
/**
|
||||
* @required
|
||||
*/
|
||||
public function injectAbstractParentClass(\Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\Source\SomeDependency $someDependency)
|
||||
{
|
||||
$this->someDependency = $someDependency;
|
||||
}
|
||||
}
|
||||
|
||||
class FirstChild extends AbstractParentClass
|
||||
{
|
||||
}
|
||||
|
||||
class SecondChild extends AbstractParentClass
|
||||
{
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,33 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector;
|
||||
|
||||
use Iterator;
|
||||
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
|
||||
final class MultiParentingToAbstractDependencyRectorTest extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider provideData()
|
||||
*/
|
||||
public function test(SmartFileInfo $fileInfo): void
|
||||
{
|
||||
$this->doTestFileInfo($fileInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Iterator<SmartFileInfo>
|
||||
*/
|
||||
public function provideData(): Iterator
|
||||
{
|
||||
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
|
||||
}
|
||||
|
||||
public function provideConfigFilePath(): string
|
||||
{
|
||||
return __DIR__ . '/config/nette_config.php';
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\Source;
|
||||
|
||||
abstract class AbstractSomeParent
|
||||
{
|
||||
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\Source;
|
||||
|
||||
final class AnotherDependency
|
||||
{
|
||||
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\Source;
|
||||
|
||||
final class ClassWithParent extends AbstractSomeParent
|
||||
{
|
||||
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\Source;
|
||||
|
||||
class FirstImplementer implements ImplementInterface
|
||||
{
|
||||
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\Source;
|
||||
|
||||
interface ImplementInterface
|
||||
{
|
||||
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\Source;
|
||||
|
||||
class SecondImplementer implements ImplementInterface
|
||||
{
|
||||
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\Source;
|
||||
|
||||
final class SomeDependency
|
||||
{
|
||||
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector;
|
||||
|
||||
use Iterator;
|
||||
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
|
||||
final class SymfonyMultiParentingToAbstractDependencyRectorTest extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider provideData()
|
||||
*/
|
||||
public function test(SmartFileInfo $fileInfo): void
|
||||
{
|
||||
$this->doTestFileInfo($fileInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Iterator<SmartFileInfo>
|
||||
*/
|
||||
public function provideData(): Iterator
|
||||
{
|
||||
return $this->yieldFilesFromDirectory(__DIR__ . '/FixtureSymfony');
|
||||
}
|
||||
|
||||
public function provideConfigFilePath(): string
|
||||
{
|
||||
return __DIR__ . '/config/symfony_config.php';
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Rector\Core\ValueObject\FrameworkName;
|
||||
use Rector\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
|
||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services = $containerConfigurator->services();
|
||||
$services->set(MultiParentingToAbstractDependencyRector::class)
|
||||
->call('configure', [[
|
||||
MultiParentingToAbstractDependencyRector::FRAMEWORK => FrameworkName::NETTE,
|
||||
]]);
|
||||
};
|
|
@ -1,15 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Rector\Core\ValueObject\FrameworkName;
|
||||
use Rector\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
|
||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services = $containerConfigurator->services();
|
||||
$services->set(MultiParentingToAbstractDependencyRector::class)
|
||||
->call('configure', [[
|
||||
MultiParentingToAbstractDependencyRector::FRAMEWORK => FrameworkName::SYMFONY,
|
||||
]]);
|
||||
};
|
|
@ -1,276 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\DependencyInjection\Rector\Class_;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PHPStan\Type\ObjectType;
|
||||
use PHPStan\Type\Type;
|
||||
use PHPStan\Type\UnionType;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
|
||||
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
|
||||
use Rector\Core\NodeManipulator\ClassInsertManipulator;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Core\ValueObject\FrameworkName;
|
||||
use Rector\Core\ValueObject\MethodName;
|
||||
use Rector\DependencyInjection\NodeFactory\InjectMethodFactory;
|
||||
use Rector\DependencyInjection\NodeRemover\ClassMethodNodeRemover;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
|
||||
/**
|
||||
* @see \Rector\Tests\DependencyInjection\Rector\Class_\MultiParentingToAbstractDependencyRector\MultiParentingToAbstractDependencyRectorTest
|
||||
*/
|
||||
final class MultiParentingToAbstractDependencyRector extends AbstractRector implements ConfigurableRectorInterface
|
||||
{
|
||||
/**
|
||||
* @api
|
||||
* @var string
|
||||
*/
|
||||
public const FRAMEWORK = 'framework';
|
||||
|
||||
private string $framework = FrameworkName::SYMFONY;
|
||||
|
||||
/**
|
||||
* @var ObjectType[]
|
||||
*/
|
||||
private array $injectObjectTypes = [];
|
||||
|
||||
public function __construct(
|
||||
private ClassMethodNodeRemover $classMethodNodeRemover,
|
||||
private InjectMethodFactory $injectMethodFactory,
|
||||
PhpDocInfoFactory $phpDocInfoFactory,
|
||||
private ClassInsertManipulator $classInsertManipulator
|
||||
) {
|
||||
$this->phpDocInfoFactory = $phpDocInfoFactory;
|
||||
}
|
||||
|
||||
public function getRuleDefinition(): RuleDefinition
|
||||
{
|
||||
return new RuleDefinition(
|
||||
'Move dependency passed to all children to parent as @inject/@required dependency',
|
||||
[
|
||||
new ConfiguredCodeSample(
|
||||
<<<'CODE_SAMPLE'
|
||||
abstract class AbstractParentClass
|
||||
{
|
||||
private $someDependency;
|
||||
|
||||
public function __construct(SomeDependency $someDependency)
|
||||
{
|
||||
$this->someDependency = $someDependency;
|
||||
}
|
||||
}
|
||||
|
||||
class FirstChild extends AbstractParentClass
|
||||
{
|
||||
public function __construct(SomeDependency $someDependency)
|
||||
{
|
||||
parent::__construct($someDependency);
|
||||
}
|
||||
}
|
||||
|
||||
class SecondChild extends AbstractParentClass
|
||||
{
|
||||
public function __construct(SomeDependency $someDependency)
|
||||
{
|
||||
parent::__construct($someDependency);
|
||||
}
|
||||
}
|
||||
CODE_SAMPLE
|
||||
,
|
||||
<<<'CODE_SAMPLE'
|
||||
abstract class AbstractParentClass
|
||||
{
|
||||
/**
|
||||
* @inject
|
||||
* @var SomeDependency
|
||||
*/
|
||||
public $someDependency;
|
||||
}
|
||||
|
||||
class FirstChild extends AbstractParentClass
|
||||
{
|
||||
}
|
||||
|
||||
class SecondChild extends AbstractParentClass
|
||||
{
|
||||
}
|
||||
CODE_SAMPLE
|
||||
,
|
||||
[
|
||||
self::FRAMEWORK => FrameworkName::NETTE,
|
||||
]
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<class-string<Node>>
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [Class_::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Class_ $node
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
if (! $node->isAbstract()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @var string|null $className */
|
||||
$className = $node->getAttribute(AttributeKey::CLASS_NAME);
|
||||
if ($className === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$childrenClasses = $this->nodeRepository->findChildrenOfClass($className);
|
||||
if (count($childrenClasses) < 2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$classMethod = $node->getMethod(MethodName::CONSTRUCT);
|
||||
if (! $classMethod instanceof ClassMethod) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$abstractClassConstructorParamTypes = $this->resolveConstructorParamClassTypes($node);
|
||||
|
||||
// process
|
||||
$this->injectObjectTypes = [];
|
||||
|
||||
foreach ($childrenClasses as $childClass) {
|
||||
$constructorClassMethod = $childClass->getMethod(MethodName::CONSTRUCT);
|
||||
if (! $constructorClassMethod instanceof ClassMethod) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->refactorChildConstructorClassMethod($constructorClassMethod, $abstractClassConstructorParamTypes);
|
||||
|
||||
$this->classMethodNodeRemover->removeClassMethodIfUseless($constructorClassMethod);
|
||||
}
|
||||
|
||||
// 2. remove from abstract class
|
||||
$this->clearAbstractClassConstructor($classMethod);
|
||||
|
||||
// 3. add inject*/@required to abstract property
|
||||
$this->addInjectOrRequiredClassMethod($node);
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, string> $configuration
|
||||
*/
|
||||
public function configure(array $configuration): void
|
||||
{
|
||||
$this->framework = $configuration[self::FRAMEWORK] ?? FrameworkName::SYMFONY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ObjectType[]
|
||||
*/
|
||||
private function resolveConstructorParamClassTypes(Class_ $class): array
|
||||
{
|
||||
$constructorClassMethod = $class->getMethod(MethodName::CONSTRUCT);
|
||||
if (! $constructorClassMethod instanceof ClassMethod) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$objectTypes = [];
|
||||
foreach ($constructorClassMethod->getParams() as $param) {
|
||||
$paramType = $this->getObjectType($param);
|
||||
$paramType = $this->popFirstObjectTypeFromUnionType($paramType);
|
||||
|
||||
if (! $paramType instanceof ObjectType) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$objectTypes[] = $paramType;
|
||||
}
|
||||
|
||||
return $objectTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ObjectType[] $abstractClassConstructorParamTypes
|
||||
*/
|
||||
private function refactorChildConstructorClassMethod(
|
||||
ClassMethod $classMethod,
|
||||
array $abstractClassConstructorParamTypes
|
||||
): void {
|
||||
foreach ($classMethod->getParams() as $key => $param) {
|
||||
$paramType = $this->getStaticType($param);
|
||||
$paramType = $this->popFirstObjectTypeFromUnionType($paramType);
|
||||
|
||||
if (! $paramType instanceof ObjectType) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! $this->nodeTypeResolver->isSameObjectTypes($paramType, $abstractClassConstructorParamTypes)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->nodeRemover->removeParam($classMethod, $key);
|
||||
$this->classMethodNodeRemover->removeParamFromMethodBody($classMethod, $param);
|
||||
|
||||
$this->injectObjectTypes[] = $paramType;
|
||||
}
|
||||
}
|
||||
|
||||
private function clearAbstractClassConstructor(ClassMethod $classMethod): void
|
||||
{
|
||||
foreach ($classMethod->getParams() as $key => $param) {
|
||||
if (! $this->nodeTypeResolver->isObjectTypes($param, $this->injectObjectTypes)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
unset($classMethod->params[$key]);
|
||||
$this->classMethodNodeRemover->removeParamFromMethodBody($classMethod, $param);
|
||||
}
|
||||
|
||||
$this->classMethodNodeRemover->removeClassMethodIfUseless($classMethod);
|
||||
}
|
||||
|
||||
private function addInjectOrRequiredClassMethod(Class_ $class): void
|
||||
{
|
||||
/** @var string $className */
|
||||
$className = $class->getAttribute(AttributeKey::CLASS_NAME);
|
||||
|
||||
if ($this->injectObjectTypes === []) {
|
||||
return;
|
||||
}
|
||||
|
||||
$injectClassMethod = $this->injectMethodFactory->createFromTypes(
|
||||
$this->injectObjectTypes,
|
||||
$className,
|
||||
$this->framework
|
||||
);
|
||||
|
||||
$this->classInsertManipulator->addAsFirstMethod($class, $injectClassMethod);
|
||||
}
|
||||
|
||||
private function popFirstObjectTypeFromUnionType(Type $paramType): Type
|
||||
{
|
||||
if (! $paramType instanceof UnionType) {
|
||||
return $paramType;
|
||||
}
|
||||
|
||||
foreach ($paramType->getTypes() as $unionedType) {
|
||||
if ($unionedType instanceof ObjectType) {
|
||||
return $unionedType;
|
||||
}
|
||||
}
|
||||
|
||||
return $paramType;
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\DowngradePhp72\NodeAnalyzer;
|
||||
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\Interface_;
|
||||
use PHPStan\Reflection\ClassReflection;
|
||||
use Rector\NodeCollector\NodeCollector\NodeRepository;
|
||||
|
||||
final class ClassLikeParentResolver
|
||||
{
|
||||
public function __construct(
|
||||
private NodeRepository $nodeRepository
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<Class_|Interface_>
|
||||
*/
|
||||
public function resolveFromClassReflection(ClassReflection $classReflection): array
|
||||
{
|
||||
$parentClassLikes = [];
|
||||
|
||||
foreach ($classReflection->getAncestors() as $ancestorClassReflectoin) {
|
||||
$parentClass = $this->nodeRepository->findClass($ancestorClassReflectoin->getName());
|
||||
if ($parentClass instanceof Class_) {
|
||||
$parentClassLikes[] = $parentClass;
|
||||
}
|
||||
|
||||
$parentInterface = $this->nodeRepository->findInterface($ancestorClassReflectoin->getName());
|
||||
if ($parentInterface instanceof Interface_) {
|
||||
$parentClassLikes[] = $parentInterface;
|
||||
}
|
||||
}
|
||||
|
||||
return $parentClassLikes;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user