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
40 changes: 38 additions & 2 deletions docs/rector_rules_overview.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# All 494 Rectors Overview
# All 495 Rectors Overview

- [Projects](#projects)
- [General](#general)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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,
],
],
];
}
}
Original file line number Diff line number Diff line change
@@ -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());
}
}

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

declare(strict_types=1);

namespace Rector\Restoration\Tests\Rector\New_\CompleteMissingDependencyInNewRector\Source;

final class RandomDependency
{
}
Original file line number Diff line number Diff line change
@@ -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)
{
}
}