mirror of
https://github.com/rectorphp/rector.git
synced 2025-03-14 04:19:44 +01:00
[Restoration] Add CompleteMissingDependencyInNewRector
This commit is contained in:
parent
ad7d8bda36
commit
f534eabd24
@ -1,4 +1,4 @@
|
||||
# All 494 Rectors Overview
|
||||
# All 495 Rectors Overview
|
||||
|
||||
- [Projects](#projects)
|
||||
- [General](#general)
|
||||
@ -55,7 +55,7 @@
|
||||
- [Refactoring](#refactoring) (2)
|
||||
- [RemovingStatic](#removingstatic) (4)
|
||||
- [Renaming](#renaming) (10)
|
||||
- [Restoration](#restoration) (3)
|
||||
- [Restoration](#restoration) (4)
|
||||
- [SOLID](#solid) (12)
|
||||
- [Sensio](#sensio) (1)
|
||||
- [StrictCodeQuality](#strictcodequality) (1)
|
||||
@ -9091,6 +9091,42 @@ services:
|
||||
|
||||
<br>
|
||||
|
||||
### `CompleteMissingDependencyInNewRector`
|
||||
|
||||
- class: [`Rector\Restoration\Rector\New_\CompleteMissingDependencyInNewRector`](/../master/rules/restoration/src/Rector/New_/CompleteMissingDependencyInNewRector.php)
|
||||
- [test fixtures](/../master/rules/restoration/tests/Rector/New_/CompleteMissingDependencyInNewRector/Fixture)
|
||||
|
||||
Complete missing constructor dependency instance by type
|
||||
|
||||
```yaml
|
||||
services:
|
||||
Rector\Restoration\Rector\New_\CompleteMissingDependencyInNewRector:
|
||||
$classToInstantiateByType:
|
||||
RandomDependency: RandomDependency
|
||||
```
|
||||
|
||||
↓
|
||||
|
||||
```diff
|
||||
final class SomeClass
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
- $valueObject = new RandomValueObject();
|
||||
+ $valueObject = new RandomValueObject(new RandomDependency());
|
||||
}
|
||||
}
|
||||
|
||||
class RandomValueObject
|
||||
{
|
||||
public function __construct(RandomDependency $randomDependency)
|
||||
{
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### `MissingClassConstantReferenceToStringRector`
|
||||
|
||||
- class: [`Rector\Restoration\Rector\ClassConstFetch\MissingClassConstantReferenceToStringRector`](/../master/rules/restoration/src/Rector/ClassConstFetch/MissingClassConstantReferenceToStringRector.php)
|
||||
|
@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Restoration\Rector\New_;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Arg;
|
||||
use PhpParser\Node\Expr\New_;
|
||||
use PhpParser\Node\Name\FullyQualified;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
|
||||
use Rector\Core\RectorDefinition\RectorDefinition;
|
||||
use ReflectionClass;
|
||||
use ReflectionMethod;
|
||||
use ReflectionParameter;
|
||||
|
||||
/**
|
||||
* @see \Rector\Restoration\Tests\Rector\New_\CompleteMissingDependencyInNewRector\CompleteMissingDependencyInNewRectorTest
|
||||
*/
|
||||
final class CompleteMissingDependencyInNewRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private $classToInstantiateByType = [];
|
||||
|
||||
/**
|
||||
* @param string[] $classToInstantiateByType
|
||||
*/
|
||||
public function __construct(array $classToInstantiateByType = [])
|
||||
{
|
||||
$this->classToInstantiateByType = $classToInstantiateByType;
|
||||
}
|
||||
|
||||
public function getDefinition(): RectorDefinition
|
||||
{
|
||||
return new RectorDefinition('Complete missing constructor dependency instance by type', [
|
||||
new ConfiguredCodeSample(
|
||||
<<<'PHP'
|
||||
final class SomeClass
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$valueObject = new RandomValueObject();
|
||||
}
|
||||
}
|
||||
|
||||
class RandomValueObject
|
||||
{
|
||||
public function __construct(RandomDependency $randomDependency)
|
||||
{
|
||||
}
|
||||
}
|
||||
PHP
|
||||
,
|
||||
<<<'PHP'
|
||||
final class SomeClass
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$valueObject = new RandomValueObject(new RandomDependency());
|
||||
}
|
||||
}
|
||||
|
||||
class RandomValueObject
|
||||
{
|
||||
public function __construct(RandomDependency $randomDependency)
|
||||
{
|
||||
}
|
||||
}
|
||||
PHP
|
||||
, [
|
||||
'$classToInstantiateByType' => [
|
||||
'RandomDependency' => 'RandomDependency',
|
||||
],
|
||||
]
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [New_::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param New_ $node
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
if ($this->shouldSkipNew($node)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @var ReflectionMethod $constructorMethodReflection */
|
||||
$constructorMethodReflection = $this->getNewNodeClassConstructorMethodReflection($node);
|
||||
|
||||
foreach ($constructorMethodReflection->getParameters() as $position => $parameterReflection) {
|
||||
// argument is already set
|
||||
if (isset($node->args[$position])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$classToInstantiate = $this->resolveClassToInstantiateByParameterReflection($parameterReflection);
|
||||
if ($classToInstantiate === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$new = new New_(new FullyQualified($classToInstantiate));
|
||||
$node->args[$position] = new Arg($new);
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
private function shouldSkipNew(New_ $new): bool
|
||||
{
|
||||
$constructorMethodReflection = $this->getNewNodeClassConstructorMethodReflection($new);
|
||||
if ($constructorMethodReflection === null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $constructorMethodReflection->getNumberOfRequiredParameters() <= count($new->args);
|
||||
}
|
||||
|
||||
private function getNewNodeClassConstructorMethodReflection(New_ $new): ?ReflectionMethod
|
||||
{
|
||||
$className = $this->getName($new->class);
|
||||
if ($className === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! class_exists($className)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$reflectionClass = new ReflectionClass($className);
|
||||
|
||||
return $reflectionClass->getConstructor();
|
||||
}
|
||||
|
||||
private function resolveClassToInstantiateByParameterReflection(ReflectionParameter $reflectionParameter): ?string
|
||||
{
|
||||
$parameterType = $reflectionParameter->getType();
|
||||
if ($parameterType === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$requiredType = (string) $parameterType;
|
||||
|
||||
return $this->classToInstantiateByType[$requiredType] ?? null;
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Restoration\Tests\Rector\New_\CompleteMissingDependencyInNewRector;
|
||||
|
||||
use Iterator;
|
||||
use Rector\Core\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
use Rector\Restoration\Rector\New_\CompleteMissingDependencyInNewRector;
|
||||
use Rector\Restoration\Tests\Rector\New_\CompleteMissingDependencyInNewRector\Source\RandomDependency;
|
||||
|
||||
final class CompleteMissingDependencyInNewRectorTest extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider provideData()
|
||||
*/
|
||||
public function test(string $file): void
|
||||
{
|
||||
$this->doTestFile($file);
|
||||
}
|
||||
|
||||
public function provideData(): Iterator
|
||||
{
|
||||
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
|
||||
}
|
||||
|
||||
protected function getRectorsWithConfiguration(): array
|
||||
{
|
||||
return [
|
||||
CompleteMissingDependencyInNewRector::class => [
|
||||
'$classToInstantiateByType' => [
|
||||
RandomDependency::class => RandomDependency::class,
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Restoration\Tests\Rector\New_\CompleteMissingDependencyInNewRector\Fixture;
|
||||
|
||||
use Rector\Restoration\Tests\Rector\New_\CompleteMissingDependencyInNewRector\Source\RandomValueObject;
|
||||
|
||||
final class SomeClass
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$valueObject = new RandomValueObject();
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Restoration\Tests\Rector\New_\CompleteMissingDependencyInNewRector\Fixture;
|
||||
|
||||
use Rector\Restoration\Tests\Rector\New_\CompleteMissingDependencyInNewRector\Source\RandomValueObject;
|
||||
|
||||
final class SomeClass
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$valueObject = new RandomValueObject(new \Rector\Restoration\Tests\Rector\New_\CompleteMissingDependencyInNewRector\Source\RandomDependency());
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Restoration\Tests\Rector\New_\CompleteMissingDependencyInNewRector\Source;
|
||||
|
||||
final class RandomDependency
|
||||
{
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Restoration\Tests\Rector\New_\CompleteMissingDependencyInNewRector\Source;
|
||||
|
||||
final class RandomValueObject
|
||||
{
|
||||
public function __construct(RandomDependency $randomDependency)
|
||||
{
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user