service entity repository combo (#3945)

* service entity repo combo

* apply cs, add tests, fixes

* update doc parser

* [Generic] Add RemoveAnnotationRector

* add nullsafe nodes to docs

* drop AddEmptyLineBetweenCallsInPhpConfigRector, not that useful

* namespace and phpstan fix

* [ci] merge PHPStan compat to one job, no gain split attention

* [rector] [ci] merge PHPStan compat to one job, no gain split attention

* [cs] [ci] merge PHPStan compat to one job, no gain split attention

Co-authored-by: Marek Šimeček <marek.simecek@footshop.cz>
Co-authored-by: rector-bot <tomas@getrector.org>
This commit is contained in:
Tomas Votruba 2020-08-12 11:44:34 +02:00 committed by GitHub
parent 26343461cd
commit 106fb1101a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
55 changed files with 1665 additions and 246 deletions

View File

@ -36,12 +36,10 @@ jobs:
run: bin/rector validate-sets --ansi
-
name: 'Validate PHPStan AttributeAware Doc Types'
run: bin/rector sync-types
-
name: 'Validate PHPStan Static Type Mappers'
run: bin/rector check-static-type-mappers
name: 'Validate PHPStan Compatibility'
run: |
bin/rector sync-types
bin/rector check-static-type-mappers
name: ${{ matrix.actions.name }}
runs-on: ubuntu-latest

View File

@ -13,7 +13,7 @@
"php": "^7.2.4",
"ext-json": "*",
"composer/xdebug-handler": "^1.4",
"doctrine/annotations": "^1.10.2",
"doctrine/annotations": "^1.10.4",
"doctrine/inflector": "^1.4|^2.0",
"jean85/pretty-package-versions": "^1.2",
"nette/robot-loader": "^3.2",

View File

@ -6,6 +6,13 @@ use Rector\Architecture\Rector\Class_\MoveRepositoryFromParentToConstructorRecto
use Rector\Architecture\Rector\MethodCall\ReplaceParentRepositoryCallsByRepositoryPropertyRector;
use Rector\Architecture\Rector\MethodCall\ServiceLocatorToDIRector;
use Rector\Doctrine\Rector\Class_\RemoveRepositoryFromEntityAnnotationRector;
use Rector\Generic\Rector\Class_\AddPropertyByParentRector;
use Rector\Generic\Rector\Class_\RemoveParentRector;
use Rector\Generic\Rector\ClassLike\RemoveAnnotationRector;
use Rector\Generic\Rector\ClassMethod\RemoveConstructorDependencyByParentRector;
use Rector\Generic\Rector\MethodCall\MethodCallToPropertyFetchRector;
use Rector\Generic\Rector\MethodCall\ReplaceParentCallByPropertyCallRector;
use Rector\Generic\Rector\StaticCall\RemoveParentCallByParentRector;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
/**
@ -16,13 +23,77 @@ return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
# order matters, this needs to be first to correctly detect parent repository
// covers "extends EntityRepository"
$services->set(MoveRepositoryFromParentToConstructorRector::class);
$services->set(ServiceLocatorToDIRector::class);
$services->set(ReplaceParentRepositoryCallsByRepositoryPropertyRector::class);
$services->set(RemoveRepositoryFromEntityAnnotationRector::class);
// covers "extends ServiceEntityRepository"
// @see https://github.com/doctrine/DoctrineBundle/pull/727/files
$services->set(RemoveAnnotationRector::class)
->call('configure', [[
RemoveAnnotationRector::ANNOTATIONS_TO_REMOVE => ['method'],
]]);
$services->set(AddPropertyByParentRector::class)
->call('configure', [[
AddPropertyByParentRector::PARENT_TYPES_TO_DEPENDENCIES => [
'Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository' => [
'Doctrine\ORM\EntityManagerInterface',
],
],
]]);
$services->set(ReplaceParentCallByPropertyCallRector::class)
->call('configure', [[
ReplaceParentCallByPropertyCallRector::PARENT_TYPE_TO_METHOD_NAME_TO_PROPERTY_FETCH => [
'Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository' => [
'createQueryBuilder' => 'entityRepository',
'createResultSetMappingBuilder' => 'entityRepository',
'clear' => 'entityRepository',
'find' => 'entityRepository',
'findBy' => 'entityRepository',
'findAll' => 'entityRepository',
'count' => 'entityRepository',
'getClassName' => 'entityRepository',
'matching' => 'entityRepository',
],
],
]]
);
$services->set(MethodCallToPropertyFetchRector::class)
->call('configure', [[
MethodCallToPropertyFetchRector::METHOD_CALL_TO_PROPERTY_FETCHES => [
'getEntityManager' => 'entityManager',
],
]]);
$services->set(RemoveParentCallByParentRector::class)
->call('configure', [[
RemoveParentCallByParentRector::PARENT_CLASSES => [
'Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository',
],
]]);
$services->set(RemoveConstructorDependencyByParentRector::class)
->call('configure', [[
RemoveConstructorDependencyByParentRector::PARENT_TYPE_TO_PARAM_TYPES_TO_REMOVE => [
'Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository' => [
'Doctrine\Common\Persistence\ManagerRegistry',
],
],
]]);
$services->set(RemoveParentRector::class)
->call('configure', [[
RemoveParentRector::PARENT_TYPES_TO_REMOVE => [
'Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository',
],
]]);
$services->set(RemoveRepositoryFromEntityAnnotationRector::class);
$services->set(ReplaceParentRepositoryCallsByRepositoryPropertyRector::class);
};

View File

@ -1,12 +0,0 @@
<?php
declare(strict_types=1);
use Rector\SymfonyPhpConfig\Rector\Closure\AddEmptyLineBetweenCallsInPhpConfigRector;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
$services->set(AddEmptyLineBetweenCallsInPhpConfigRector::class);
};

View File

@ -58,7 +58,7 @@ $someVariable[0]
#### Public Properties
* `$items` - `/** @var ArrayItem[] Items */`
* `$items` - `/** @var (ArrayItem|null)[] Items */`
<br>
### `PhpParser\Node\Expr\ArrowFunction`
@ -432,6 +432,41 @@ new class
* `$args` - `/** @var Node\Arg[] Arguments */`
<br>
### `PhpParser\Node\Expr\NullsafeMethodCall`
* requires arguments on construct
#### Example PHP Code
```php
$someVariable?->someMethod()
```
#### Public Properties
* `$var` - `/** @var Expr Variable holding object */`
* `$name` - `/** @var Identifier|Expr Method name */`
* `$args` - `/** @var Arg[] Arguments */`
<br>
### `PhpParser\Node\Expr\NullsafePropertyFetch`
* requires arguments on construct
#### Example PHP Code
```php
$someVariable?->somePropety
```
#### Public Properties
* `$var` - `/** @var Expr Variable holding object */`
* `$name` - `/** @var Identifier|Expr Property name */`
<br>
### `PhpParser\Node\Expr\PostDec`
* requires arguments on construct

View File

@ -1,4 +1,4 @@
# All 552 Rectors Overview
# All 558 Rectors Overview
- [Projects](#projects)
---
@ -19,7 +19,7 @@
- [Downgrade](#downgrade) (1)
- [DynamicTypeAnalysis](#dynamictypeanalysis) (3)
- [FileSystemRector](#filesystemrector) (1)
- [Generic](#generic) (42)
- [Generic](#generic) (49)
- [Guzzle](#guzzle) (1)
- [Injection](#injection) (1)
- [JMS](#jms) (2)
@ -69,7 +69,7 @@
- [Symfony](#symfony) (33)
- [SymfonyCodeQuality](#symfonycodequality) (1)
- [SymfonyPHPUnit](#symfonyphpunit) (1)
- [SymfonyPhpConfig](#symfonyphpconfig) (2)
- [SymfonyPhpConfig](#symfonyphpconfig) (1)
- [Twig](#twig) (1)
- [TypeDeclaration](#typedeclaration) (9)
@ -4474,6 +4474,45 @@ Add method parent call, in case new parent method is added
<br><br>
### `AddPropertyByParentRector`
- class: [`Rector\Generic\Rector\Class_\AddPropertyByParentRector`](/../master/rules/generic/src/Rector/Class_/AddPropertyByParentRector.php)
- [test fixtures](/../master/rules/generic/tests/Rector/Class_/AddPropertyByParentRector/Fixture)
Add dependency via constructor by parent class type
```php
<?php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Rector\Generic\Rector\Class_\AddPropertyByParentRector;
return function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->set(AddPropertyByParentRector::class)
->call('configure', [[AddPropertyByParentRector::PARENT_TYPES_TO_DEPENDENCIES, ['SomeParentClass' => ['SomeDependency']]]]);
};
```
```diff
final class SomeClass extends SomeParentClass
{
+ /**
+ * @var SomeDependency
+ */
+ private $someDependency;
+
+ public function __construct(SomeDependency $someDependency)
+ {
+ $this->someDependency = $someDependency;
+ }
}
```
<br><br>
### `AddReturnTypeDeclarationRector`
- class: [`Rector\Generic\Rector\ClassMethod\AddReturnTypeDeclarationRector`](/../master/rules/generic/src/Rector/ClassMethod/AddReturnTypeDeclarationRector.php)
@ -5051,6 +5090,41 @@ return function (ContainerConfigurator $containerConfigurator) : void {
<br><br>
### `MethodCallToPropertyFetchRector`
- class: [`Rector\Generic\Rector\MethodCall\MethodCallToPropertyFetchRector`](/../master/rules/generic/src/Rector/MethodCall/MethodCallToPropertyFetchRector.php)
- [test fixtures](/../master/rules/generic/tests/Rector/MethodCall/MethodCallToPropertyFetchRector/Fixture)
Turns method call "$this->something()" to property fetch "$this->something"
```php
<?php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Rector\Generic\Rector\MethodCall\MethodCallToPropertyFetchRector;
return function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->set(MethodCallToPropertyFetchRector::class)
->call('configure', [[MethodCallToPropertyFetchRector::METHOD_CALL_TO_PROPERTY_FETCHES, ['someMethod' => 'someProperty']]]);
};
```
```diff
class SomeClass
{
public function run()
{
- $this->someMethod();
+ $this->someProperty;
}
}
```
<br><br>
### `MethodCallToReturnRector`
- class: [`Rector\Generic\Rector\MethodCall\MethodCallToReturnRector`](/../master/rules/generic/src/Rector/MethodCall/MethodCallToReturnRector.php)
@ -5384,6 +5458,73 @@ return function (ContainerConfigurator $containerConfigurator) : void {
<br><br>
### `RemoveAnnotationRector`
- class: [`Rector\Generic\Rector\ClassLike\RemoveAnnotationRector`](/../master/rules/generic/src/Rector/ClassLike/RemoveAnnotationRector.php)
- [test fixtures](/../master/rules/generic/tests/Rector/ClassLike/RemoveAnnotationRector/Fixture)
Remove annotation by names
```php
<?php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Rector\Generic\Rector\ClassLike\RemoveAnnotationRector;
return function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->set(RemoveAnnotationRector::class)
->call('configure', [[RemoveAnnotationRector::ANNOTATIONS_TO_REMOVE, ['method']]]);
};
```
```diff
-/**
- * @method getName()
- */
final class SomeClass
{
}
```
<br><br>
### `RemoveConstructorDependencyByParentRector`
- class: [`Rector\Generic\Rector\ClassMethod\RemoveConstructorDependencyByParentRector`](/../master/rules/generic/src/Rector/ClassMethod/RemoveConstructorDependencyByParentRector.php)
- [test fixtures](/../master/rules/generic/tests/Rector/ClassMethod/RemoveConstructorDependencyByParentRector/Fixture)
Removes params in constructor by parent type and param names
```php
<?php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Rector\Generic\Rector\ClassMethod\RemoveConstructorDependencyByParentRector;
return function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->set(RemoveConstructorDependencyByParentRector::class)
->call('configure', [[RemoveConstructorDependencyByParentRector::PARENT_TYPE_TO_PARAM_TYPES_TO_REMOVE, ['SomeParentClass' => ['someType']]]]);
};
```
```diff
class SomeClass extends SomeParentClass
{
- public function __construct(SomeType $someType)
+ public function __construct()
{
}
}
```
<br><br>
### `RemoveFuncCallArgRector`
- class: [`Rector\Generic\Rector\FuncCall\RemoveFuncCallArgRector`](/../master/rules/generic/src/Rector/FuncCall/RemoveFuncCallArgRector.php)
@ -5473,6 +5614,71 @@ return function (ContainerConfigurator $containerConfigurator) : void {
<br><br>
### `RemoveParentCallByParentRector`
- class: [`Rector\Generic\Rector\StaticCall\RemoveParentCallByParentRector`](/../master/rules/generic/src/Rector/StaticCall/RemoveParentCallByParentRector.php)
- [test fixtures](/../master/rules/generic/tests/Rector/StaticCall/RemoveParentCallByParentRector/Fixture)
Remove parent call by parent class
```php
<?php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Rector\Generic\Rector\StaticCall\RemoveParentCallByParentRector;
return function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->set(RemoveParentCallByParentRector::class)
->call('configure', [[RemoveParentCallByParentRector::PARENT_CLASSES, ['SomeParentClass']]]);
};
```
```diff
final class SomeClass extends SomeParentClass
{
public function run()
{
- parent::someCall();
}
}
```
<br><br>
### `RemoveParentRector`
- class: [`Rector\Generic\Rector\Class_\RemoveParentRector`](/../master/rules/generic/src/Rector/Class_/RemoveParentRector.php)
- [test fixtures](/../master/rules/generic/tests/Rector/Class_/RemoveParentRector/Fixture)
Removes extends class by name
```php
<?php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Rector\Generic\Rector\Class_\RemoveParentRector;
return function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->set(RemoveParentRector::class)
->call('configure', [[RemoveParentRector::PARENT_TYPES_TO_REMOVE, ['SomeParentClass']]]);
};
```
```diff
-final class SomeClass extends SomeParentClass
+final class SomeClass
{
}
```
<br><br>
### `RemoveTraitRector`
- class: [`Rector\Generic\Rector\ClassLike\RemoveTraitRector`](/../master/rules/generic/src/Rector/ClassLike/RemoveTraitRector.php)
@ -5547,6 +5753,41 @@ return function (ContainerConfigurator $containerConfigurator) : void {
<br><br>
### `ReplaceParentCallByPropertyCallRector`
- class: [`Rector\Generic\Rector\MethodCall\ReplaceParentCallByPropertyCallRector`](/../master/rules/generic/src/Rector/MethodCall/ReplaceParentCallByPropertyCallRector.php)
- [test fixtures](/../master/rules/generic/tests/Rector/MethodCall/ReplaceParentCallByPropertyCallRector/Fixture)
Changes method calls in child of specific types to defined property method call
```php
<?php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Rector\Generic\Rector\MethodCall\ReplaceParentCallByPropertyCallRector;
return function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->set(ReplaceParentCallByPropertyCallRector::class)
->call('configure', [[ReplaceParentCallByPropertyCallRector::PARENT_TYPE_TO_METHOD_NAME_TO_PROPERTY_FETCH, ['SomeTypeToReplace' => ['someMethodCall' => 'someProperty']]]]);
};
```
```diff
final class SomeClass
{
public function run(SomeTypeToReplace $someTypeToReplace)
{
- $someTypeToReplace->someMethodCall();
+ $this->someProperty->someMethodCall();
}
}
```
<br><br>
### `ReplaceVariableByPropertyFetchRector`
- class: [`Rector\Generic\Rector\Architecture\DependencyInjection\ReplaceVariableByPropertyFetchRector`](/../master/rules/generic/src/Rector/Architecture/DependencyInjection/ReplaceVariableByPropertyFetchRector.php)
@ -13509,25 +13750,6 @@ Move self::$container service fetching from test methods up to setUp method
## SymfonyPhpConfig
### `AddEmptyLineBetweenCallsInPhpConfigRector`
- class: [`Rector\SymfonyPhpConfig\Rector\Closure\AddEmptyLineBetweenCallsInPhpConfigRector`](/../master/rules/symfony-php-config/src/Rector/Closure/AddEmptyLineBetweenCallsInPhpConfigRector.php)
- [test fixtures](/../master/rules/symfony-php-config/tests/Rector/Closure/AddEmptyLineBetweenCallsInPhpConfigRector/Fixture)
Make calls in PHP Symfony config separated by newline
```diff
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();
+
$parameters->set('key', 'value');
};
```
<br><br>
### `ChangeServiceArgumentsToMethodCallRector`
- class: [`Rector\SymfonyPhpConfig\Rector\MethodCall\ChangeServiceArgumentsToMethodCallRector`](/../master/rules/symfony-php-config/src/Rector/MethodCall/ChangeServiceArgumentsToMethodCallRector.php)

View File

@ -641,11 +641,6 @@ final class SetList
*/
public const SYMFONY_50_TYPES = __DIR__ . '/../../../../config/set/symfony50-types.php';
/**
* @var string
*/
public const SYMFONY_PHP_CONFIG = __DIR__ . '/../../../../config/set/symfony-php-config.php';
/**
* @var string
*/

View File

@ -68,7 +68,8 @@ parameters:
- tests
- compiler/src
- utils
- config
# this cannot be put it, because it wipes PHPStan cache on each run
#- config
excludes_analyse:
# iterable types

View File

@ -9,7 +9,6 @@ use Rector\Core\Configuration\Option;
use Rector\DeadCode\Rector\ClassConst\RemoveUnusedClassConstantRector;
use Rector\Php55\Rector\String_\StringClassNameToClassConstantRector;
use Rector\Set\ValueObject\SetList;
use Rector\SymfonyPhpConfig\Rector\Closure\AddEmptyLineBetweenCallsInPhpConfigRector;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
@ -23,8 +22,6 @@ return static function (ContainerConfigurator $containerConfigurator): void {
],
]);
$services->set(AddEmptyLineBetweenCallsInPhpConfigRector::class);
$parameters = $containerConfigurator->parameters();
$parameters->set(Option::SETS, [
@ -35,7 +32,6 @@ return static function (ContainerConfigurator $containerConfigurator): void {
SetList::SOLID,
SetList::PRIVATIZATION,
SetList::NAMING,
SetList::SYMFONY_PHP_CONFIG,
SetList::ORDER,
SetList::DEFLUENT,
]);

View File

@ -0,0 +1,97 @@
<?php
declare(strict_types=1);
namespace Rector\Generic\Rector\ClassLike;
use PhpParser\Node;
use PhpParser\Node\FunctionLike;
use PhpParser\Node\Stmt\ClassConst;
use PhpParser\Node\Stmt\ClassLike;
use PhpParser\Node\Stmt\Property;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\NodeTypeResolver\Node\AttributeKey;
/**
* @see \Rector\Generic\Tests\Rector\ClassLike\RemoveAnnotationRector\RemoveAnnotationRectorTest
*/
final class RemoveAnnotationRector extends AbstractRector implements ConfigurableRectorInterface
{
/**
* @var string
*/
public const ANNOTATIONS_TO_REMOVE = 'annotations_to_remove';
/**
* @var mixed[]
*/
private $annotationsToRemove = [];
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Remove annotation by names', [
new ConfiguredCodeSample(
<<<'PHP'
/**
* @method getName()
*/
final class SomeClass
{
}
PHP
,
<<<'PHP'
final class SomeClass
{
}
PHP
,
[
self::ANNOTATIONS_TO_REMOVE => ['method'],
]
),
]);
}
/**
* @return string[]
*/
public function getNodeTypes(): array
{
return [ClassLike::class, FunctionLike::class, Property::class, ClassConst::class];
}
/**
* @param ClassLike|FunctionLike|Property|ClassConst $node
*/
public function refactor(Node $node): ?Node
{
/** @var PhpDocInfo|null $phpDocInfo */
$phpDocInfo = $node->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($phpDocInfo === null) {
return null;
}
foreach ($this->annotationsToRemove as $annotationToRemove) {
if (! $phpDocInfo->hasByName($annotationToRemove)) {
continue;
}
$phpDocInfo->removeByName($annotationToRemove);
}
return $node;
}
/**
* @param mixed[] $configuration
*/
public function configure(array $configuration): void
{
$this->annotationsToRemove = $configuration[self::ANNOTATIONS_TO_REMOVE] ?? [];
}
}

View File

@ -0,0 +1,120 @@
<?php
declare(strict_types=1);
namespace Rector\Generic\Rector\ClassMethod;
use PhpParser\Node;
use PhpParser\Node\Stmt\ClassMethod;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\Core\ValueObject\MethodName;
use Rector\NodeTypeResolver\Node\AttributeKey;
/**
* @see \Rector\Generic\Tests\Rector\ClassMethod\RemoveConstructorDependencyByParentRector\RemoveConstructorDependencyByParentRectorTest
*/
final class RemoveConstructorDependencyByParentRector extends AbstractRector implements ConfigurableRectorInterface
{
/**
* @var string
* @api
*/
public const PARENT_TYPE_TO_PARAM_TYPES_TO_REMOVE = '$parentsDependenciesToRemove';
/**
* @var array<string, string[]>
*/
private $parentsDependenciesToRemove = [];
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Removes params in constructor by parent type and param names', [
new ConfiguredCodeSample(
<<<'PHP'
class SomeClass extends SomeParentClass
{
public function __construct(SomeType $someType)
{
}
}
PHP
,
<<<'PHP'
class SomeClass extends SomeParentClass
{
public function __construct()
{
}
}
PHP
, [
self::PARENT_TYPE_TO_PARAM_TYPES_TO_REMOVE => [
'SomeParentClass' => ['someType'],
],
]
),
]);
}
/**
* @return class-string[]
*/
public function getNodeTypes(): array
{
return [ClassMethod::class];
}
/**
* @param ClassMethod $node
*/
public function refactor(Node $node): ?Node
{
$parentClassName = $node->getAttribute(AttributeKey::PARENT_CLASS_NAME);
if ($parentClassName === null) {
return null;
}
if (! $this->isName($node, MethodName::CONSTRUCT)) {
return null;
}
foreach ($this->parentsDependenciesToRemove as $parentClass => $paramsToRemove) {
$parentClassName = $node->getAttribute(AttributeKey::PARENT_CLASS_NAME);
if ($parentClassName !== $parentClass) {
continue;
}
$this->removeClassMethodParameterByName($node, $paramsToRemove);
}
return $node;
}
public function configure(array $configuration): void
{
$this->parentsDependenciesToRemove = $configuration[self::PARENT_TYPE_TO_PARAM_TYPES_TO_REMOVE] ?? [];
}
/**
* @param string[] $paramNamesToRemove
*/
private function removeClassMethodParameterByName(ClassMethod $classMethod, array $paramNamesToRemove): void
{
foreach ($paramNamesToRemove as $paramNameToRemove) {
foreach ($classMethod->params as $param) {
if ($param->type === null) {
continue;
}
if (! $this->isName($param->type, $paramNameToRemove)) {
continue;
}
$this->removeNode($param);
}
}
}
}

View File

@ -56,7 +56,7 @@ class SomeClass implements SomeInterface
}
PHP
, [
'$interfaceByTrait' => [
self::INTERFACE_BY_TRAIT => [
'SomeTrait' => 'SomeInterface',
],
]),

View File

@ -0,0 +1,115 @@
<?php
declare(strict_types=1);
namespace Rector\Generic\Rector\Class_;
use PhpParser\Node;
use PhpParser\Node\Stmt\Class_;
use PHPStan\Type\ObjectType;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\Naming\Naming\PropertyNaming;
use Rector\NodeTypeResolver\Node\AttributeKey;
/**
* @see \Rector\Generic\Tests\Rector\Class_\AddPropertyByParentRector\AddPropertyByParentRectorTest
*/
final class AddPropertyByParentRector extends AbstractRector implements ConfigurableRectorInterface
{
/**
* @api
* @var string
*/
public const PARENT_TYPES_TO_DEPENDENCIES = 'parent_types_to_dependencies';
/**
* @var array<string, string[]>
*/
private $parentsDependenciesToAdd = [];
/**
* @var PropertyNaming
*/
private $propertyNaming;
public function __construct(PropertyNaming $propertyNaming)
{
$this->propertyNaming = $propertyNaming;
}
/**
* @return class-string[]
*/
public function getNodeTypes(): array
{
return [Class_::class];
}
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Add dependency via constructor by parent class type', [
new ConfiguredCodeSample(
<<<'CODE_SAMPLE'
final class SomeClass extends SomeParentClass
{
}
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
final class SomeClass extends SomeParentClass
{
/**
* @var SomeDependency
*/
private $someDependency;
public function __construct(SomeDependency $someDependency)
{
$this->someDependency = $someDependency;
}
}
CODE_SAMPLE
,
[
self::PARENT_TYPES_TO_DEPENDENCIES => [
'SomeParentClass' => ['SomeDependency'],
],
]
),
]);
}
/**
* @param Class_ $node
*/
public function refactor(Node $node): ?Node
{
if ($node->extends === null) {
return null;
}
$currentParentClassName = $node->getAttribute(AttributeKey::PARENT_CLASS_NAME);
foreach ($this->parentsDependenciesToAdd as $parentClass => $typesToAdd) {
if ($currentParentClassName !== $parentClass) {
continue;
}
foreach ($typesToAdd as $typeToAdd) {
$propertyType = new ObjectType($typeToAdd);
/** @var string $propertyName */
$propertyName = $this->propertyNaming->getExpectedNameFromType($propertyType);
$this->addPropertyToClass($node, $propertyType, $propertyName);
}
}
return $node;
}
public function configure(array $configuration): void
{
$this->parentsDependenciesToAdd = $configuration[self::PARENT_TYPES_TO_DEPENDENCIES] ?? [];
}
}

View File

@ -0,0 +1,89 @@
<?php
declare(strict_types=1);
namespace Rector\Generic\Rector\Class_;
use PhpParser\Node;
use PhpParser\Node\Stmt\Class_;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\NodeTypeResolver\Node\AttributeKey;
/**
* @see \Rector\Generic\Tests\Rector\Class_\RemoveParentRector\RemoveParentRectorTest
*/
final class RemoveParentRector extends AbstractRector implements ConfigurableRectorInterface
{
/**
* @api
* @var string
*/
public const PARENT_TYPES_TO_REMOVE = '$parentsToRemove';
/**
* @var string[]
*/
private $parentClassesToRemove = [];
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Removes extends class by name', [
new ConfiguredCodeSample(
<<<'PHP'
final class SomeClass extends SomeParentClass
{
}
PHP
,
<<<'PHP'
final class SomeClass
{
}
PHP
, [
self::PARENT_TYPES_TO_REMOVE => ['SomeParentClass'],
]
),
]);
}
/**
* @return class-string[]
*/
public function getNodeTypes(): array
{
return [Class_::class];
}
/**
* @param Class_ $node
*/
public function refactor(Node $node): ?Node
{
if ($node->extends === null) {
return null;
}
foreach ($this->parentClassesToRemove as $parentClassToRemove) {
$parentClassName = $node->getAttribute(AttributeKey::PARENT_CLASS_NAME);
if ($parentClassName !== $parentClassToRemove) {
continue;
}
// remove parent class
$node->extends = null;
return $node;
}
return null;
}
public function configure(array $configuration): void
{
$this->parentClassesToRemove = $configuration[self::PARENT_TYPES_TO_REMOVE] ?? [];
}
}

View File

@ -17,6 +17,7 @@ use Rector\Core\RectorDefinition\RectorDefinition;
final class MethodCallRemoverRector extends AbstractRector implements ConfigurableRectorInterface
{
/**
* @api
* @var string
*/
public const METHOD_CALL_REMOVER_ARGUMENT = '$methodCallRemoverArgument';

View File

@ -0,0 +1,96 @@
<?php
declare(strict_types=1);
namespace Rector\Generic\Rector\MethodCall;
use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\Variable;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
/**
* @see \Rector\Generic\Tests\Rector\MethodCall\MethodCallToPropertyFetchRector\MethodCallToPropertyFetchRectorTest
*/
final class MethodCallToPropertyFetchRector extends AbstractRector implements ConfigurableRectorInterface
{
/**
* @api
* @var string
*/
public const METHOD_CALL_TO_PROPERTY_FETCHES = '$methodCallToPropertyFetchCollection';
/**
* @var array<string, string>
*/
private $methodCallToPropertyFetchCollection = [];
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Turns method call "$this->something()" to property fetch "$this->something"', [
new ConfiguredCodeSample(
<<<'CODE_SAMPLE'
class SomeClass
{
public function run()
{
$this->someMethod();
}
}
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
class SomeClass
{
public function run()
{
$this->someProperty;
}
}
CODE_SAMPLE
,
[
self::METHOD_CALL_TO_PROPERTY_FETCHES => [
'someMethod' => 'someProperty',
],
]
),
]);
}
/**
* @return string[]
*/
public function getNodeTypes(): array
{
return [MethodCall::class];
}
/**
* @param MethodCall $node
*/
public function refactor(Node $node): ?Node
{
foreach ($this->methodCallToPropertyFetchCollection as $methodName => $propertyName) {
if (! $this->isName($node->name, $methodName)) {
continue;
}
if ($propertyName === null) {
return new Variable('this');
}
return $this->createPropertyFetch('this', $propertyName);
}
return null;
}
public function configure(array $configuration): void
{
$this->methodCallToPropertyFetchCollection = $configuration[self::METHOD_CALL_TO_PROPERTY_FETCHES] ?? [];
}
}

View File

@ -0,0 +1,102 @@
<?php
declare(strict_types=1);
namespace Rector\Generic\Rector\MethodCall;
use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
/**
* @see \Rector\Generic\Tests\Rector\MethodCall\ReplaceParentCallByPropertyCallRector\ReplaceParentCallByPropertyCallRectorTest
*/
final class ReplaceParentCallByPropertyCallRector extends AbstractRector implements ConfigurableRectorInterface
{
/**
* @var string
*/
public const PARENT_TYPE_TO_METHOD_NAME_TO_PROPERTY_FETCH = 'parnet_type_to_method_name_to_property_fetch';
/**
AddPropertyByParentRector.php:103
* @var array<string, array<string, string>>
*/
private $replaceParentCallByPropertyArguments = [];
public function getDefinition(): RectorDefinition
{
return new RectorDefinition(
'Changes method calls in child of specific types to defined property method call', [
new ConfiguredCodeSample(
<<<'CODE_SAMPLE'
final class SomeClass
{
public function run(SomeTypeToReplace $someTypeToReplace)
{
$someTypeToReplace->someMethodCall();
}
}
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
final class SomeClass
{
public function run(SomeTypeToReplace $someTypeToReplace)
{
$this->someProperty->someMethodCall();
}
}
CODE_SAMPLE
,
[
self::PARENT_TYPE_TO_METHOD_NAME_TO_PROPERTY_FETCH => [
'SomeTypeToReplace' => [
'someMethodCall' => 'someProperty',
],
],
]
),
]
);
}
/**
* @return string[]
*/
public function getNodeTypes(): array
{
return [MethodCall::class];
}
/**
* @param MethodCall $node
*/
public function refactor(Node $node): ?Node
{
foreach ($this->replaceParentCallByPropertyArguments as $type => $methodNamesToPropertyNames) {
if (! $this->isObjectType($node->var, $type)) {
continue;
}
foreach ($methodNamesToPropertyNames as $methodName => $propertyName) {
if (! $this->isName($node->name, $methodName)) {
continue;
}
$node->var = $this->createPropertyFetch('this', $propertyName);
return $node;
}
}
return null;
}
public function configure(array $configuration): void
{
$this->replaceParentCallByPropertyArguments = $configuration[self::PARENT_TYPE_TO_METHOD_NAME_TO_PROPERTY_FETCH] ?? [];
}
}

View File

@ -19,7 +19,6 @@ use Rector\Naming\Naming\PropertyNaming;
use Rector\NodeTypeResolver\Node\AttributeKey;
/**
* @see \Rector\Generic\Tests\Rector\MethodCall\ServiceGetterToConstructorInjectionRector\ServiceGetterToConstructorInjectionRectorTest
* @see \Rector\Generic\Tests\Rector\MethodCall\ServiceGetterToConstructorInjectionRector\ServiceGetterToConstructorInjectionRectorTest
*/
final class ServiceGetterToConstructorInjectionRector extends AbstractRector implements ConfigurableRectorInterface

View File

@ -0,0 +1,102 @@
<?php
declare(strict_types=1);
namespace Rector\Generic\Rector\StaticCall;
use PhpParser\Node;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Stmt\Class_;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\NodeTypeResolver\Node\AttributeKey;
/**
* @see \Rector\Generic\Tests\Rector\StaticCall\RemoveParentCallByParentRector\RemoveParentCallByParentRectorTest
*/
final class RemoveParentCallByParentRector extends AbstractRector implements ConfigurableRectorInterface
{
/**
* @api
* @var string
*/
public const PARENT_CLASSES = 'parent_classes';
/**
* @var string[]
*/
private $parentClasses = [];
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Remove parent call by parent class', [
new ConfiguredCodeSample(
<<<'CODE_SAMPLE'
final class SomeClass extends SomeParentClass
{
public function run()
{
parent::someCall();
}
}
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
final class SomeClass extends SomeParentClass
{
public function run()
{
}
}
CODE_SAMPLE
,
[
self::PARENT_CLASSES => ['SomeParentClass'],
]
),
]);
}
/**
* @return string[]
*/
public function getNodeTypes(): array
{
return [StaticCall::class];
}
/**
* @param StaticCall $node
*/
public function refactor(Node $node): ?Node
{
$classLike = $node->getAttribute(AttributeKey::CLASS_NODE);
if (! $classLike instanceof Class_) {
return null;
}
if (! $this->isName($node->class, 'parent')) {
return null;
}
$parentClassName = $node->getAttribute(AttributeKey::PARENT_CLASS_NAME);
foreach ($this->parentClasses as $parentClass) {
if ($parentClassName !== $parentClass) {
continue;
}
$this->removeNode($node);
return null;
}
return null;
}
public function configure(array $configuration): void
{
$this->parentClasses = $configuration[self::PARENT_CLASSES] ?? [];
}
}

View File

@ -0,0 +1,22 @@
<?php
namespace Rector\Generic\Tests\Rector\ClassLike\RemoveAnnotationRector\Fixture;
/**
* @method getName()
*/
final class SomeClass
{
}
?>
-----
<?php
namespace Rector\Generic\Tests\Rector\ClassLike\RemoveAnnotationRector\Fixture;
final class SomeClass
{
}
?>

View File

@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
namespace Rector\Generic\Tests\Rector\ClassLike\RemoveAnnotationRector;
use Iterator;
use Rector\Core\Testing\PHPUnit\AbstractRectorTestCase;
use Rector\Generic\Rector\ClassLike\RemoveAnnotationRector;
use Symplify\SmartFileSystem\SmartFileInfo;
final class RemoveAnnotationRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(SmartFileInfo $fileInfo): void
{
$this->doTestFileInfo($fileInfo);
}
public function provideData(): Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}
/**
* @return array<string, array<string, string[]>>
*/
protected function getRectorsWithConfiguration(): array
{
return [
RemoveAnnotationRector::class => [
RemoveAnnotationRector::ANNOTATIONS_TO_REMOVE => ['method'],
],
];
}
}

View File

@ -0,0 +1,43 @@
<?php
namespace Rector\Generic\Tests\Rector\ClassMethod\RemoveConstructorDependencyByParentRector\Fixture;
use Rector\Generic\Tests\Rector\ClassMethod\RemoveConstructorDependencyByParentRector\Source\ParentClassToRemoveConstructorParamsBy;
use Rector\Generic\Tests\Rector\ClassMethod\RemoveConstructorDependencyByParentRector\Source\SomeDependencyToBeRemoved;
final class ClassWithExternalConstant extends ParentClassToRemoveConstructorParamsBy
{
/**
* @var SomeDependencyToBeRemoved
*/
private $someDependencyToBeRemoved;
public function __construct(SomeDependencyToBeRemoved $someDependencyToBeRemoved)
{
$this->someDependencyToBeRemoved = $someDependencyToBeRemoved;
}
}
?>
-----
<?php
namespace Rector\Generic\Tests\Rector\ClassMethod\RemoveConstructorDependencyByParentRector\Fixture;
use Rector\Generic\Tests\Rector\ClassMethod\RemoveConstructorDependencyByParentRector\Source\ParentClassToRemoveConstructorParamsBy;
use Rector\Generic\Tests\Rector\ClassMethod\RemoveConstructorDependencyByParentRector\Source\SomeDependencyToBeRemoved;
final class ClassWithExternalConstant extends ParentClassToRemoveConstructorParamsBy
{
/**
* @var SomeDependencyToBeRemoved
*/
private $someDependencyToBeRemoved;
public function __construct()
{
$this->someDependencyToBeRemoved = $someDependencyToBeRemoved;
}
}
?>

View File

@ -0,0 +1,42 @@
<?php
declare(strict_types=1);
namespace Rector\Generic\Tests\Rector\ClassMethod\RemoveConstructorDependencyByParentRector;
use Iterator;
use Rector\Core\Testing\PHPUnit\AbstractRectorTestCase;
use Rector\Generic\Rector\ClassMethod\RemoveConstructorDependencyByParentRector;
use Rector\Generic\Tests\Rector\ClassMethod\RemoveConstructorDependencyByParentRector\Source\ParentClassToRemoveConstructorParamsBy;
use Rector\Generic\Tests\Rector\ClassMethod\RemoveConstructorDependencyByParentRector\Source\SomeDependencyToBeRemoved;
use Symplify\SmartFileSystem\SmartFileInfo;
final class RemoveConstructorDependencyByParentRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(SmartFileInfo $fileInfo): void
{
$this->doTestFileInfo($fileInfo);
}
public function provideData(): Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}
/**
* @return mixed[]
*/
protected function getRectorsWithConfiguration(): array
{
return [
RemoveConstructorDependencyByParentRector::class => [
RemoveConstructorDependencyByParentRector::PARENT_TYPE_TO_PARAM_TYPES_TO_REMOVE => [
ParentClassToRemoveConstructorParamsBy::class => [SomeDependencyToBeRemoved::class],
],
],
];
}
}

View File

@ -0,0 +1,10 @@
<?php
declare(strict_types=1);
namespace Rector\Generic\Tests\Rector\ClassMethod\RemoveConstructorDependencyByParentRector\Source;
abstract class ParentClassToRemoveConstructorParamsBy
{
}

View File

@ -0,0 +1,10 @@
<?php
declare(strict_types=1);
namespace Rector\Generic\Tests\Rector\ClassMethod\RemoveConstructorDependencyByParentRector\Source;
final class SomeDependencyToBeRemoved
{
}

View File

@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
namespace Rector\Generic\Tests\Rector\Class_\AddPropertyByParentRector;
use Iterator;
use Rector\Core\Testing\PHPUnit\AbstractRectorTestCase;
use Rector\Generic\Rector\Class_\AddPropertyByParentRector;
use Rector\Generic\Tests\Rector\Class_\AddPropertyByParentRector\Source\SomeParentClassToAddDependencyBy;
use Symplify\SmartFileSystem\SmartFileInfo;
final class AddPropertyByParentRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(SmartFileInfo $fileInfo): void
{
$this->doTestFileInfo($fileInfo);
}
public function provideData(): Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}
protected function getRectorsWithConfiguration(): array
{
return [
AddPropertyByParentRector::class => [
AddPropertyByParentRector::PARENT_TYPES_TO_DEPENDENCIES => [
SomeParentClassToAddDependencyBy::class => ['SomeDependency'],
],
],
];
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace Rector\Generic\Tests\Rector\Class_\AddPropertyByParentRector\Fixture;
use Rector\Generic\Tests\Rector\Class_\AddPropertyByParentRector\Source\SomeParentClassToAddDependencyBy;
final class SomeClass extends SomeParentClassToAddDependencyBy
{
}
?>
-----
<?php
namespace Rector\Generic\Tests\Rector\Class_\AddPropertyByParentRector\Fixture;
use Rector\Generic\Tests\Rector\Class_\AddPropertyByParentRector\Source\SomeParentClassToAddDependencyBy;
final class SomeClass extends SomeParentClassToAddDependencyBy
{
private \SomeDependency $someDependency;
public function __construct(\SomeDependency $someDependency)
{
$this->someDependency = $someDependency;
}
}
?>

View File

@ -0,0 +1,10 @@
<?php
declare(strict_types=1);
namespace Rector\Generic\Tests\Rector\Class_\AddPropertyByParentRector\Source;
abstract class SomeParentClassToAddDependencyBy
{
}

View File

@ -0,0 +1,23 @@
<?php
namespace Rector\Generic\Tests\Rector\Class_\RemoveParentRector\Fixture;
use Rector\Generic\Tests\Rector\Class_\RemoveParentRector\Source\ParentTypeToBeRemoved;
class SomeClass extends ParentTypeToBeRemoved
{
}
?>
-----
<?php
namespace Rector\Generic\Tests\Rector\Class_\RemoveParentRector\Fixture;
use Rector\Generic\Tests\Rector\Class_\RemoveParentRector\Source\ParentTypeToBeRemoved;
class SomeClass
{
}
?>

View File

@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
namespace Rector\Generic\Tests\Rector\Class_\RemoveParentRector;
use Iterator;
use Rector\Core\Testing\PHPUnit\AbstractRectorTestCase;
use Rector\Generic\Rector\Class_\RemoveParentRector;
use Rector\Generic\Tests\Rector\Class_\RemoveParentRector\Source\ParentTypeToBeRemoved;
use Symplify\SmartFileSystem\SmartFileInfo;
final class RemoveParentRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(SmartFileInfo $fileInfo): void
{
$this->doTestFileInfo($fileInfo);
}
public function provideData(): Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}
/**
* @return mixed[]
*/
protected function getRectorsWithConfiguration(): array
{
return [
RemoveParentRector::class => [
RemoveParentRector::PARENT_TYPES_TO_REMOVE => [ParentTypeToBeRemoved::class],
],
];
}
}

View File

@ -0,0 +1,10 @@
<?php
declare(strict_types=1);
namespace Rector\Generic\Tests\Rector\Class_\RemoveParentRector\Source;
abstract class ParentTypeToBeRemoved
{
}

View File

@ -0,0 +1,27 @@
<?php
namespace Rector\Generic\Tests\Rector\MethodCall\MethodCallToPropertyFetchRector\Fixture;
class SomeClass
{
public function run()
{
$entityManager = $this->getEntityManager();
}
}
?>
-----
<?php
namespace Rector\Generic\Tests\Rector\MethodCall\MethodCallToPropertyFetchRector\Fixture;
class SomeClass
{
public function run()
{
$entityManager = $this->entityManager;
}
}
?>

View File

@ -0,0 +1,40 @@
<?php
declare(strict_types=1);
namespace Rector\Generic\Tests\Rector\MethodCall\MethodCallToPropertyFetchRector;
use Iterator;
use Rector\Core\Testing\PHPUnit\AbstractRectorTestCase;
use Rector\Generic\Rector\MethodCall\MethodCallToPropertyFetchRector;
use Symplify\SmartFileSystem\SmartFileInfo;
final class MethodCallToPropertyFetchRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(SmartFileInfo $fileInfo): void
{
$this->doTestFileInfo($fileInfo);
}
public function provideData(): Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}
/**
* @return mixed[]
*/
protected function getRectorsWithConfiguration(): array
{
return [
MethodCallToPropertyFetchRector::class => [
MethodCallToPropertyFetchRector::METHOD_CALL_TO_PROPERTY_FETCHES => [
'getEntityManager' => 'entityManager',
],
],
];
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace Rector\Generic\Tests\Rector\MethodCall\ReplaceParentCallByPropertyCallRector\Fixture;
use Rector\Generic\Tests\Rector\MethodCall\ReplaceParentCallByPropertyCallRector\Source\TypeClassToReplaceMethodCallBy;
final class SomeClass
{
public function __construct(TypeClassToReplaceMethodCallBy $typeClassToReplaceMethodCallBy)
{
$typeClassToReplaceMethodCallBy->someMethod();
}
}
?>
-----
<?php
namespace Rector\Generic\Tests\Rector\MethodCall\ReplaceParentCallByPropertyCallRector\Fixture;
use Rector\Generic\Tests\Rector\MethodCall\ReplaceParentCallByPropertyCallRector\Source\TypeClassToReplaceMethodCallBy;
final class SomeClass
{
public function __construct(TypeClassToReplaceMethodCallBy $typeClassToReplaceMethodCallBy)
{
$this->someProperty->someMethod();
}
}
?>

View File

@ -0,0 +1,40 @@
<?php
declare(strict_types=1);
namespace Rector\Generic\Tests\Rector\MethodCall\ReplaceParentCallByPropertyCallRector;
use Iterator;
use Rector\Core\Testing\PHPUnit\AbstractRectorTestCase;
use Rector\Generic\Rector\MethodCall\ReplaceParentCallByPropertyCallRector;
use Rector\Generic\Tests\Rector\MethodCall\ReplaceParentCallByPropertyCallRector\Source\TypeClassToReplaceMethodCallBy;
use Symplify\SmartFileSystem\SmartFileInfo;
final class ReplaceParentCallByPropertyCallRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(SmartFileInfo $fileInfo): void
{
$this->doTestFileInfo($fileInfo);
}
public function provideData(): Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}
protected function getRectorsWithConfiguration(): array
{
return [
ReplaceParentCallByPropertyCallRector::class => [
ReplaceParentCallByPropertyCallRector::PARENT_TYPE_TO_METHOD_NAME_TO_PROPERTY_FETCH => [
TypeClassToReplaceMethodCallBy::class => [
'someMethod' => 'someProperty',
],
],
],
];
}
}

View File

@ -0,0 +1,10 @@
<?php
declare(strict_types=1);
namespace Rector\Generic\Tests\Rector\MethodCall\ReplaceParentCallByPropertyCallRector\Source;
abstract class TypeClassToReplaceMethodCallBy
{
}

View File

@ -0,0 +1,30 @@
<?php
namespace Rector\Generic\Tests\Rector\StaticCall\RemoveParentCallByParentRector\Fixture;
use Rector\Generic\Tests\Rector\StaticCall\RemoveParentCallByParentRector\Source\ParentClassToRemoveParentStaticCallBy;
final class SomeClass extends ParentClassToRemoveParentStaticCallBy
{
public function run()
{
parent::run();
}
}
?>
-----
<?php
namespace Rector\Generic\Tests\Rector\StaticCall\RemoveParentCallByParentRector\Fixture;
use Rector\Generic\Tests\Rector\StaticCall\RemoveParentCallByParentRector\Source\ParentClassToRemoveParentStaticCallBy;
final class SomeClass extends ParentClassToRemoveParentStaticCallBy
{
public function run()
{
}
}
?>

View File

@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
namespace Rector\Generic\Tests\Rector\StaticCall\RemoveParentCallByParentRector;
use Iterator;
use Rector\Core\Testing\PHPUnit\AbstractRectorTestCase;
use Rector\Generic\Rector\StaticCall\RemoveParentCallByParentRector;
use Rector\Generic\Tests\Rector\StaticCall\RemoveParentCallByParentRector\Source\ParentClassToRemoveParentStaticCallBy;
use Symplify\SmartFileSystem\SmartFileInfo;
final class RemoveParentCallByParentRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(SmartFileInfo $fileInfo): void
{
$this->doTestFileInfo($fileInfo);
}
public function provideData(): Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}
/**
* @return mixed[]
*/
protected function getRectorsWithConfiguration(): array
{
return [
RemoveParentCallByParentRector::class => [
RemoveParentCallByParentRector::PARENT_CLASSES => [ParentClassToRemoveParentStaticCallBy::class],
],
];
}
}

View File

@ -0,0 +1,10 @@
<?php
declare(strict_types=1);
namespace Rector\Generic\Tests\Rector\StaticCall\RemoveParentCallByParentRector\Source;
abstract class ParentClassToRemoveParentStaticCallBy
{
}

View File

@ -1,91 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\SymfonyPhpConfig\Rector\Closure;
use PhpParser\Node;
use PhpParser\Node\Expr\Closure;
use PhpParser\Node\Stmt\Nop;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\SymfonyPhpConfig\NodeAnalyzer\SymfonyPhpConfigClosureAnalyzer;
/**
* @see \Rector\SymfonyPhpConfig\Tests\Rector\Closure\AddEmptyLineBetweenCallsInPhpConfigRector\AddEmptyLineBetweenCallsInPhpConfigRectorTest
*/
final class AddEmptyLineBetweenCallsInPhpConfigRector extends AbstractRector
{
/**
* @var SymfonyPhpConfigClosureAnalyzer
*/
private $symfonyPhpConfigClosureAnalyzer;
public function __construct(SymfonyPhpConfigClosureAnalyzer $symfonyPhpConfigClosureAnalyzer)
{
$this->symfonyPhpConfigClosureAnalyzer = $symfonyPhpConfigClosureAnalyzer;
}
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Make calls in PHP Symfony config separated by newline', [
new CodeSample(
<<<'PHP'
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();
$parameters->set('key', 'value');
};
PHP
,
<<<'PHP'
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();
$parameters->set('key', 'value');
};
PHP
),
]);
}
/**
* @return string[]
*/
public function getNodeTypes(): array
{
return [Closure::class];
}
/**
* @param Closure $node
*/
public function refactor(Node $node): ?Node
{
if (! $this->symfonyPhpConfigClosureAnalyzer->isPhpConfigClosure($node)) {
return null;
}
$originalStmts = $node->stmts;
$newStmts = [];
$previousLine = null;
foreach ($originalStmts as $stmt) {
if ($previousLine !== null && $previousLine + 1 === $stmt->getEndLine()) {
$newStmts[] = new Nop();
}
$newStmts[] = $stmt;
$previousLine = $stmt->getEndLine();
}
$node->stmts = $newStmts;
return $node;
}
}

View File

@ -1,31 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\SymfonyPhpConfig\Tests\Rector\Closure\AddEmptyLineBetweenCallsInPhpConfigRector;
use Iterator;
use Rector\Core\Testing\PHPUnit\AbstractRectorTestCase;
use Rector\SymfonyPhpConfig\Rector\Closure\AddEmptyLineBetweenCallsInPhpConfigRector;
use Symplify\SmartFileSystem\SmartFileInfo;
final class AddEmptyLineBetweenCallsInPhpConfigRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(SmartFileInfo $fileInfo): void
{
$this->doTestFileInfo($fileInfo);
}
public function provideData(): Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}
protected function getRectorClass(): string
{
return AddEmptyLineBetweenCallsInPhpConfigRector::class;
}
}

View File

@ -1,26 +0,0 @@
<?php
namespace Rector\SymfonyPhpConfig\Tests\Rector\Closure\AddEmptyLineBetweenCallsInPhpConfigRector\Fixture;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();
$parameters->set('key', 'value');
};
?>
-----
<?php
namespace Rector\SymfonyPhpConfig\Tests\Rector\Closure\AddEmptyLineBetweenCallsInPhpConfigRector\Fixture;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();
$parameters->set('key', 'value');
};
?>

View File

@ -1,11 +0,0 @@
<?php
namespace Rector\SymfonyPhpConfig\Tests\Rector\Closure\AddEmptyLineBetweenCallsInPhpConfigRector\Fixture;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();
$parameters->set('key', 'value');
};

View File

@ -8,9 +8,9 @@ use Iterator;
use Rector\Core\Configuration\Option;
use Rector\Core\Testing\PHPUnit\AbstractRectorTestCase;
use Rector\Symfony\Rector\MethodCall\ContainerGetToConstructorInjectionRector;
use Rector\Symfony\Tests\MethodCall\ContainerGetToConstructorInjectionRector\Source\ContainerAwareParentClass;
use Rector\Symfony\Tests\MethodCall\ContainerGetToConstructorInjectionRector\Source\ContainerAwareParentCommand;
use Rector\Symfony\Tests\MethodCall\ContainerGetToConstructorInjectionRector\Source\ThisClassCallsMethodInConstructor;
use Rector\Symfony\Tests\Rector\MethodCall\ContainerGetToConstructorInjectionRector\Source\ContainerAwareParentClass;
use Rector\Symfony\Tests\Rector\MethodCall\ContainerGetToConstructorInjectionRector\Source\ContainerAwareParentCommand;
use Rector\Symfony\Tests\Rector\MethodCall\ContainerGetToConstructorInjectionRector\Source\ThisClassCallsMethodInConstructor;
use Symplify\SmartFileSystem\SmartFileInfo;
final class ContainerGetToConstructorInjectionRectorTest extends AbstractRectorTestCase

View File

@ -1,8 +1,8 @@
<?php
namespace Rector\Symfony\Tests\MethodCall\ContainerGetToConstructorInjectionRector\Fixture;
namespace Rector\Symfony\Tests\Rector\MethodCall\ContainerGetToConstructorInjectionRector\Fixture;
use Rector\Symfony\Tests\MethodCall\ContainerGetToConstructorInjectionRector\Source\ContainerAwareParentClass;
use Rector\Symfony\Tests\Rector\MethodCall\ContainerGetToConstructorInjectionRector\Source\ContainerAwareParentClass;
final class FirstClass extends ContainerAwareParentClass
{
@ -18,9 +18,9 @@ final class FirstClass extends ContainerAwareParentClass
-----
<?php
namespace Rector\Symfony\Tests\MethodCall\ContainerGetToConstructorInjectionRector\Fixture;
namespace Rector\Symfony\Tests\Rector\MethodCall\ContainerGetToConstructorInjectionRector\Fixture;
use Rector\Symfony\Tests\MethodCall\ContainerGetToConstructorInjectionRector\Source\ContainerAwareParentClass;
use Rector\Symfony\Tests\Rector\MethodCall\ContainerGetToConstructorInjectionRector\Source\ContainerAwareParentClass;
final class FirstClass extends ContainerAwareParentClass
{

View File

@ -1,8 +1,8 @@
<?php
namespace Rector\Symfony\Tests\MethodCall\ContainerGetToConstructorInjectionRector\Fixture;
namespace Rector\Symfony\Tests\Rector\MethodCall\ContainerGetToConstructorInjectionRector\Fixture;
use Rector\Symfony\Tests\MethodCall\ContainerGetToConstructorInjectionRector\Source\ContainerAwareParentCommand;
use Rector\Symfony\Tests\Rector\MethodCall\ContainerGetToConstructorInjectionRector\Source\ContainerAwareParentCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
@ -18,9 +18,9 @@ final class MyCommand extends ContainerAwareParentCommand
-----
<?php
namespace Rector\Symfony\Tests\MethodCall\ContainerGetToConstructorInjectionRector\Fixture;
namespace Rector\Symfony\Tests\Rector\MethodCall\ContainerGetToConstructorInjectionRector\Fixture;
use Rector\Symfony\Tests\MethodCall\ContainerGetToConstructorInjectionRector\Source\ContainerAwareParentCommand;
use Rector\Symfony\Tests\Rector\MethodCall\ContainerGetToConstructorInjectionRector\Source\ContainerAwareParentCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

View File

@ -1,8 +1,8 @@
<?php
namespace Rector\Symfony\Tests\MethodCall\ContainerGetToConstructorInjectionRector\Fixture;
namespace Rector\Symfony\Tests\Rector\MethodCall\ContainerGetToConstructorInjectionRector\Fixture;
use Rector\Symfony\Tests\MethodCall\ContainerGetToConstructorInjectionRector\Source\ThisClassCallsMethodInConstructor;
use Rector\Symfony\Tests\Rector\MethodCall\ContainerGetToConstructorInjectionRector\Source\ThisClassCallsMethodInConstructor;
final class ParentClassWithInConstructCall extends ThisClassCallsMethodInConstructor
{
@ -18,9 +18,9 @@ final class ParentClassWithInConstructCall extends ThisClassCallsMethodInConstru
-----
<?php
namespace Rector\Symfony\Tests\MethodCall\ContainerGetToConstructorInjectionRector\Fixture;
namespace Rector\Symfony\Tests\Rector\MethodCall\ContainerGetToConstructorInjectionRector\Fixture;
use Rector\Symfony\Tests\MethodCall\ContainerGetToConstructorInjectionRector\Source\ThisClassCallsMethodInConstructor;
use Rector\Symfony\Tests\Rector\MethodCall\ContainerGetToConstructorInjectionRector\Source\ThisClassCallsMethodInConstructor;
final class ParentClassWithInConstructCall extends ThisClassCallsMethodInConstructor
{

View File

@ -1,6 +1,6 @@
<?php
use Rector\Symfony\Tests\MethodCall\ContainerGetToConstructorInjectionRector\Source\ContainerAwareParentClass;
use Rector\Symfony\Tests\Rector\MethodCall\ContainerGetToConstructorInjectionRector\Source\ContainerAwareParentClass;
final class SomeController extends ContainerAwareParentClass
{
@ -14,7 +14,7 @@ final class SomeController extends ContainerAwareParentClass
-----
<?php
use Rector\Symfony\Tests\MethodCall\ContainerGetToConstructorInjectionRector\Source\ContainerAwareParentClass;
use Rector\Symfony\Tests\Rector\MethodCall\ContainerGetToConstructorInjectionRector\Source\ContainerAwareParentClass;
final class SomeController extends ContainerAwareParentClass
{

View File

@ -2,7 +2,7 @@
declare(strict_types=1);
namespace Rector\Symfony\Tests\MethodCall\ContainerGetToConstructorInjectionRector\Source;
namespace Rector\Symfony\Tests\Rector\MethodCall\ContainerGetToConstructorInjectionRector\Source;
use Symfony\Component\DependencyInjection\ContainerInterface;

View File

@ -2,7 +2,7 @@
declare(strict_types=1);
namespace Rector\Symfony\Tests\MethodCall\ContainerGetToConstructorInjectionRector\Source;
namespace Rector\Symfony\Tests\Rector\MethodCall\ContainerGetToConstructorInjectionRector\Source;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\DependencyInjection\ContainerInterface;

View File

@ -2,7 +2,7 @@
declare(strict_types=1);
namespace Rector\Symfony\Tests\MethodCall\ContainerGetToConstructorInjectionRector\Source;
namespace Rector\Symfony\Tests\Rector\MethodCall\ContainerGetToConstructorInjectionRector\Source;
use Symfony\Component\DependencyInjection\ContainerInterface;

View File

@ -1,7 +1,7 @@
parameters:
kernel_class: 'Rector\Symfony\Tests\MethodCall\AbstractToConstructorInjectionRectorSource\SomeKernelClass'
kernel_class: 'Rector\Symfony\Tests\Rector\MethodCall\AbstractToConstructorInjectionRectorSource\SomeKernelClass'
services:
Rector\Symfony\Rector\FrameworkBundle\ContainerGetToConstructorInjectionRector:
$containerAwareParentTypes:
- 'Rector\Symfony\Tests\MethodCall\ContainerGetToConstructorInjectionRector\Source\ContainerAwareParentClass'
- 'Rector\Symfony\Tests\Rector\MethodCall\ContainerGetToConstructorInjectionRector\Source\ContainerAwareParentClass'

View File

@ -1,6 +1,6 @@
<?php
namespace Rector\Symfony\Tests\MethodCall\OptionNameRector\Fixture;
namespace Rector\Symfony\Tests\Rector\MethodCall\OptionNameRector\Fixture;
use Rector\Symfony\Tests\Rector\MethodCall\OptionNameRector\Source\AbstractType;
use Symfony\Component\Form\FormBuilder;
@ -20,7 +20,7 @@ class RegistrationFormType2 extends AbstractType
-----
<?php
namespace Rector\Symfony\Tests\MethodCall\OptionNameRector\Fixture;
namespace Rector\Symfony\Tests\Rector\MethodCall\OptionNameRector\Fixture;
use Rector\Symfony\Tests\Rector\MethodCall\OptionNameRector\Source\AbstractType;
use Symfony\Component\Form\FormBuilder;

View File

@ -195,13 +195,13 @@ trait NodeTypeResolverTrait
}
if ($node instanceof ClassMethod) {
/** @var Class_|null $class */
$class = $node->getAttribute(AttributeKey::CLASS_NODE);
if ($class === null) {
/** @var Class_|null $classLike */
$classLike = $node->getAttribute(AttributeKey::CLASS_NODE);
if ($classLike === null) {
return false;
}
return $this->isObjectType($class, $type);
return $this->isObjectType($classLike, $type);
}
return false;

View File

@ -34,6 +34,8 @@ use PhpParser\Node\Expr\List_;
use PhpParser\Node\Expr\Match_;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Expr\NullsafeMethodCall;
use PhpParser\Node\Expr\NullsafePropertyFetch;
use PhpParser\Node\Expr\PostDec;
use PhpParser\Node\Expr\PostInc;
use PhpParser\Node\Expr\PreDec;
@ -139,6 +141,11 @@ final class DumpNodesCommand extends AbstractCommand
*/
private const SOME_CLASS = 'SomeClass';
/**
* @var string
*/
private const SOME_METHOD = 'someMethod';
/**
* @var BetterStandardPrinter
*/
@ -293,7 +300,7 @@ final class DumpNodesCommand extends AbstractCommand
} elseif ($nodeClass === Function_::class) {
$node = new Function_('some_function');
} elseif ($nodeClass === ClassMethod::class) {
$node = new ClassMethod('someMethod');
$node = new ClassMethod(self::SOME_METHOD);
$node->flags |= Class_::MODIFIER_PUBLIC;
} elseif ($nodeClass === Case_::class) {
$node = new Case_(new ConstFetch(new Name('true')));
@ -322,7 +329,7 @@ final class DumpNodesCommand extends AbstractCommand
} elseif ($nodeClass === Global_::class) {
$node = new Global_([new Variable('globalVariable')]);
} elseif ($nodeClass === Precedence::class) {
$node = new Precedence(new Name('SomeTrait'), 'someMethod', [new Name('overriddenTrait')]);
$node = new Precedence(new Name('SomeTrait'), self::SOME_METHOD, [new Name('overriddenTrait')]);
} elseif ($nodeClass === Alias::class) {
$node = new Alias(new Name('SomeTrait'), 'method', Class_::MODIFIER_PUBLIC, 'aliasedMethod');
} elseif ($nodeClass === Throw_::class) {
@ -423,6 +430,10 @@ final class DumpNodesCommand extends AbstractCommand
$node = new Arg($someVariableNode);
} elseif ($nodeClass === UnionType::class) {
$node = new UnionType([new Identifier(self::STRING), new Identifier('null')]);
} elseif ($nodeClass === NullsafeMethodCall::class) {
$node = new NullsafeMethodCall($someVariableNode, new Identifier(self::SOME_METHOD));
} elseif ($nodeClass === NullsafePropertyFetch::class) {
$node = new NullsafePropertyFetch($someVariableNode, new Identifier('somePropety'));
} else {
throw new ShouldNotHappenException(sprintf(
'Implement a new printer for "%s" node in "%s"',