[DX] Configurable rule must have configure code sample, and vice versa (#4174)

* [DX] Configurable rule must have configure code sample, and vice versa

* Add ConfiguredCodeSample

* heredocs

* code sample

* fix class

* drop AbstractConfigurableMatchTypeRector

Co-authored-by: TomasVotruba <tomas.vot@gmail.com>
This commit is contained in:
dobryy 2020-09-11 11:21:48 +02:00 committed by GitHub
parent 59c5a5e5ba
commit a6444fb801
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
45 changed files with 1061 additions and 135 deletions

View File

@ -2,7 +2,6 @@
declare(strict_types=1);
use GuzzleHttp\Cookie\SetCookie;
use Rector\MagicDisclosure\Rector\MethodCall\FluentChainMethodCallToNormalMethodCallRector;
use Rector\Renaming\Rector\MethodCall\RenameMethodRector;
use Rector\Renaming\ValueObject\MethodCallRename;
@ -14,22 +13,11 @@ use Rector\Transform\ValueObject\StaticCallToFuncCall;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();
$parameters->set(
'classes_to_defluent',
['GuzzleHttp\Collection', 'GuzzleHttp\Url', 'GuzzleHttp\Query', 'GuzzleHttp\Post\PostBody', SetCookie::class]
);
$services = $containerConfigurator->services();
# both uses "%classes_to_defluent%
#diff-810cdcfdd8a6b9e1fc0d1e96d7786874
$services->set(FluentChainMethodCallToNormalMethodCallRector::class)
->call(
'configure',
[[FluentChainMethodCallToNormalMethodCallRector::TYPES_TO_MATCH => '%classes_to_defluent%']]
);
$services->set(FluentChainMethodCallToNormalMethodCallRector::class);
$configuration = [
new FuncNameToMethodCallName('GuzzleHttp\json_decode', 'GuzzleHttp\Utils', 'jsonDecode'),

View File

@ -219,6 +219,31 @@ return function (ContainerConfigurator $containerConfigurator) : void {
Move value object to ValueObject namespace/directory
```php
<?php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Rector\Autodiscovery\Rector\FileSystem\MoveValueObjectsToValueObjectDirectoryRector;
return function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->set(MoveValueObjectsToValueObjectDirectoryRector::class)
->call('configure', [[
MoveValueObjectsToValueObjectDirectoryRector::TYPES => [
'ValueObjectInterfaceClassName']
]])
->call('configure', [[
MoveValueObjectsToValueObjectDirectoryRector::SUFFIXES => [
'Search']
]])
->call('configure', [[
MoveValueObjectsToValueObjectDirectoryRector::ENABLE_VALUE_OBJECT_GUESSING => true
]]);
};
```
```diff
-// app/Exception/Name.php
+// app/ValueObject/Name.php
@ -1795,6 +1820,23 @@ Changes various `implode` forms to consistent one
Replace PREG delimiter with configured one
```php
<?php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Rector\CodingStyle\Rector\FuncCall\ConsistentPregDelimiterRector;
return function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->set(ConsistentPregDelimiterRector::class)
->call('configure', [[
ConsistentPregDelimiterRector::DELIMITER => '#'
]]);
};
```
```diff
class SomeClass
{
@ -1857,6 +1899,24 @@ include/require should be followed by absolute path
Changes use of function calls to use constants
```php
<?php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Rector\CodingStyle\Rector\FuncCall\FunctionCallToConstantRector;
return function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->set(FunctionCallToConstantRector::class)
->call('configure', [[
FunctionCallToConstantRector::FUNCTIONS_TO_CONSTANTS => [
'php_sapi_name' => 'PHP_SAPI']
]]);
};
```
```diff
class SomeClass
{
@ -1868,6 +1928,24 @@ Changes use of function calls to use constants
}
```
```php
<?php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Rector\CodingStyle\Rector\FuncCall\FunctionCallToConstantRector;
return function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->set(FunctionCallToConstantRector::class)
->call('configure', [[
FunctionCallToConstantRector::FUNCTIONS_TO_CONSTANTS => [
'pi' => 'M_PI']
]]);
};
```
```diff
class SomeClass
{
@ -3736,6 +3814,24 @@ Change param type of `setId()` to uuid interface
Replaces doctrine alias with class.
```php
<?php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Rector\Doctrine\Rector\MethodCall\EntityAliasToClassConstantReferenceRector;
return function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->set(EntityAliasToClassConstantReferenceRector::class)
->call('configure', [[
EntityAliasToClassConstantReferenceRector::ALIASES_TO_NAMESPACES => [
'App' => 'App\Entity']
]]);
};
```
```diff
$entityManager = new Doctrine\ORM\EntityManager();
-$entityManager->getRepository("AppBundle:Post");
@ -4492,6 +4588,23 @@ Change Tree from gedmo/doctrine-extensions to knplabs/doctrine-behaviors
Remove the 'object' param type, add a @param tag instead
```php
<?php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Rector\DowngradePhp72\Rector\FunctionLike\DowngradeParamObjectTypeDeclarationRector;
return function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->set(DowngradeParamObjectTypeDeclarationRector::class)
->call('configure', [[
DowngradeParamObjectTypeDeclarationRector::ADD_DOC_BLOCK => true
]]);
};
```
```diff
<?php
@ -4516,6 +4629,23 @@ Remove the 'object' param type, add a @param tag instead
Remove the 'object' function type, add a @return tag instead
```php
<?php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Rector\DowngradePhp72\Rector\FunctionLike\DowngradeReturnObjectTypeDeclarationRector;
return function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->set(DowngradeReturnObjectTypeDeclarationRector::class)
->call('configure', [[
DowngradeReturnObjectTypeDeclarationRector::ADD_DOC_BLOCK => true
]]);
};
```
```diff
<?php
@ -4581,6 +4711,23 @@ Remove null coalescing operator ??=
Changes property type definition from type definitions to `@var` annotations.
```php
<?php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Rector\DowngradePhp74\Rector\Property\DowngradeTypedPropertyRector;
return function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->set(DowngradeTypedPropertyRector::class)
->call('configure', [[
DowngradeTypedPropertyRector::ADD_DOC_BLOCK => true
]]);
};
```
```diff
class SomeClass
{
@ -4603,6 +4750,23 @@ Changes property type definition from type definitions to `@var` annotations.
Remove the 'mixed' param type, add a @param tag instead
```php
<?php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Rector\DowngradePhp80\Rector\FunctionLike\DowngradeParamMixedTypeDeclarationRector;
return function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->set(DowngradeParamMixedTypeDeclarationRector::class)
->call('configure', [[
DowngradeParamMixedTypeDeclarationRector::ADD_DOC_BLOCK => true
]]);
};
```
```diff
<?php
@ -4627,6 +4791,23 @@ Remove the 'mixed' param type, add a @param tag instead
Remove the 'mixed' function type, add a @return tag instead
```php
<?php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Rector\DowngradePhp80\Rector\FunctionLike\DowngradeReturnMixedTypeDeclarationRector;
return function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->set(DowngradeReturnMixedTypeDeclarationRector::class)
->call('configure', [[
DowngradeReturnMixedTypeDeclarationRector::ADD_DOC_BLOCK => true
]]);
};
```
```diff
<?php
@ -4655,6 +4836,23 @@ Remove the 'mixed' function type, add a @return tag instead
Remove the 'static' function type, add a @return tag instead
```php
<?php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Rector\DowngradePhp80\Rector\FunctionLike\DowngradeReturnStaticTypeDeclarationRector;
return function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->set(DowngradeReturnStaticTypeDeclarationRector::class)
->call('configure', [[
DowngradeReturnStaticTypeDeclarationRector::ADD_DOC_BLOCK => true
]]);
};
```
```diff
<?php
@ -4680,6 +4878,23 @@ Remove the 'static' function type, add a @return tag instead
Remove the union type params, add @param tags instead
```php
<?php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Rector\DowngradePhp80\Rector\FunctionLike\DowngradeUnionTypeParamDeclarationRector;
return function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->set(DowngradeUnionTypeParamDeclarationRector::class)
->call('configure', [[
DowngradeUnionTypeParamDeclarationRector::ADD_DOC_BLOCK => true
]]);
};
```
```diff
<?php
@ -4705,6 +4920,23 @@ Remove the union type params, add @param tags instead
Remove returning union types, add a @return tag instead
```php
<?php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Rector\DowngradePhp80\Rector\FunctionLike\DowngradeUnionTypeReturnDeclarationRector;
return function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->set(DowngradeUnionTypeReturnDeclarationRector::class)
->call('configure', [[
DowngradeUnionTypeReturnDeclarationRector::ADD_DOC_BLOCK => true
]]);
};
```
```diff
<?php
@ -4733,6 +4965,23 @@ Remove returning union types, add a @return tag instead
Removes union type property type definition, adding `@var` annotations instead.
```php
<?php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Rector\DowngradePhp80\Rector\Property\DowngradeUnionTypeTypedPropertyRector;
return function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->set(DowngradeUnionTypeTypedPropertyRector::class)
->call('configure', [[
DowngradeUnionTypeTypedPropertyRector::ADD_DOC_BLOCK => true
]]);
};
```
```diff
class SomeClass
{
@ -4815,6 +5064,24 @@ Clean up probe that records argument types
Remove file relative to project directory
```php
<?php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Rector\FileSystemRector\Rector\Removing\RemoveProjectFileRector;
return function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->set(RemoveProjectFileRector::class)
->call('configure', [[
RemoveProjectFileRector::FILE_PATHS_TO_REMOVE => [
'someFile/ToBeRemoved.txt']
]]);
};
```
```diff
-// someFile/ToBeRemoved.txt
```
@ -5356,6 +5623,25 @@ Change null in argument, that is now not nullable anymore
Change configured function calls to new Instance
```php
<?php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Rector\Generic\Rector\FuncCall\FuncCallToNewRector;
return function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->set(FuncCallToNewRector::class)
->call('configure', [[
FuncCallToNewRector::FUNCTION_TO_NEW => [
'collection' => [
'Collection']]
]]);
};
```
```diff
class SomeClass
{
@ -5882,6 +6168,24 @@ return function (ContainerConfigurator $containerConfigurator) : void {
Remove specific traits from code
```php
<?php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Rector\Generic\Rector\Class_\RemoveTraitRector;
return function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->set(RemoveTraitRector::class)
->call('configure', [[
RemoveTraitRector::TRAITS_TO_REMOVE => [
'TraitNameToRemove']
]]);
};
```
```diff
class SomeClass
{
@ -6299,6 +6603,27 @@ Change static `validate()` method to `$request->validate()`
Adds an include file at the top of matching files, except class definitions
```php
<?php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Rector\Legacy\Rector\Include_\AddTopIncludeRector;
return function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->set(AddTopIncludeRector::class)
->call('configure', [[
AddTopIncludeRector::AUTOLOAD_FILE_PATH => '/../autoloader.php'
]])
->call('configure', [[
AddTopIncludeRector::PATTERNS => [
'pat*/*/?ame.php', 'somepath/?ame.php']
]]);
};
```
```diff
+require_once __DIR__ . '/../autoloader.php';
+
@ -8070,6 +8395,24 @@ Orders constants by visibility
Order __constructor dependencies by type A-Z
```php
<?php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Rector\Order\Rector\ClassMethod\OrderConstructorDependenciesByTypeAlphabeticallyRector;
return function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->set(OrderConstructorDependenciesByTypeAlphabeticallyRector::class)
->call('configure', [[
OrderConstructorDependenciesByTypeAlphabeticallyRector::SKIP_PATTERNS => [
'Cla*ame', 'Ano?herClassName']
]]);
};
```
```diff
class SomeClass
{
@ -9946,6 +10289,24 @@ The /e modifier is no longer supported, use `preg_replace_callback` instead
Replace string class names by <class>::class constant
```php
<?php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Rector\Php55\Rector\String_\StringClassNameToClassConstantRector;
return function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->set(StringClassNameToClassConstantRector::class)
->call('configure', [[
StringClassNameToClassConstantRector::CLASSES_TO_SKIP => [
'ClassName', 'AnotherClassName']
]]);
};
```
```diff
class AnotherClass
{
@ -10496,6 +10857,24 @@ Remove extra parameters
Changes reserved "Object" name to "<Smart>Object" where <Smart> can be configured
```php
<?php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Rector\Php71\Rector\Name\ReservedObjectRector;
return function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->set(ReservedObjectRector::class)
->call('configure', [[
ReservedObjectRector::RESERVED_KEYWORDS_TO_REPLACEMENTS => [
'ReservedObject' => 'SmartObject', 'Object' => 'AnotherSmartObject']
]]);
};
```
```diff
-class Object
+class SmartObject
@ -11130,6 +11509,24 @@ Change deprecated (real) to (float)
Change `fn()` function name, since it will be reserved keyword
```php
<?php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Rector\Php74\Rector\Function_\ReservedFnFunctionRector;
return function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->set(ReservedFnFunctionRector::class)
->call('configure', [[
ReservedFnFunctionRector::RESERVED_NAMES_TO_NEW_ONES => [
'fn' => 'someFunctionName']
]]);
};
```
```diff
class SomeClass
{
@ -11173,6 +11570,23 @@ Add null default to properties with PHP 7.4 property nullable type
Changes property `@var` annotations from annotation to type.
```php
<?php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Rector\Php74\Rector\Property\TypedPropertyRector;
return function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->set(TypedPropertyRector::class)
->call('configure', [[
TypedPropertyRector::CLASS_LIKE_TYPE_ONLY => false
]]);
};
```
```diff
final class SomeClass
{
@ -11996,6 +12410,24 @@ Change static method and local-only calls to non-static
Convert new X to new factories
```php
<?php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Rector\RemovingStatic\Rector\Class_\NewUniqueObjectToEntityFactoryRector;
return function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->set(NewUniqueObjectToEntityFactoryRector::class)
->call('configure', [[
NewUniqueObjectToEntityFactoryRector::TYPES_TO_SERVICES => [
'ClassName']
]]);
};
```
```diff
-<?php
-
@ -12332,6 +12764,24 @@ return function (ContainerConfigurator $containerConfigurator) : void {
Replace constant by new ones
```php
<?php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Rector\Renaming\Rector\ConstFetch\RenameConstantRector;
return function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->set(RenameConstantRector::class)
->call('configure', [[
RenameConstantRector::OLD_TO_NEW_CONSTANTS => [
'MYSQL_ASSOC' => 'MYSQLI_ASSOC', 'OLD_CONSTANT' => 'NEW_CONSTANT']
]]);
};
```
```diff
final class SomeClass
{
@ -13406,6 +13856,24 @@ Turns old default value to parameter in `ContainerBuilder->build()` method in DI
Turns fetching of dependencies via `$container->get()` in ContainerAware to constructor injection in Command and Controller in Symfony
```php
<?php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Rector\Symfony\Rector\MethodCall\ContainerGetToConstructorInjectionRector;
return function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->set(ContainerGetToConstructorInjectionRector::class)
->call('configure', [[
ContainerGetToConstructorInjectionRector::CONTAINER_AWARE_PARENT_TYPES => [
'ContainerAwareParentClassName', 'ContainerAwareParentCommandClassName', 'ThisClassCallsMethodInConstructorClassName']
]]);
};
```
```diff
-final class SomeCommand extends ContainerAwareCommand
+final class SomeCommand extends Command
@ -13556,6 +14024,24 @@ Turns fetching of dependencies via `$this->get()` to constructor injection in Co
Turns fetching of dependencies via `$this->get()` to constructor injection in Command and Controller in Symfony
```php
<?php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Rector\Symfony\Rector\MethodCall\GetToConstructorInjectionRector;
return function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->set(GetToConstructorInjectionRector::class)
->call('configure', [[
GetToConstructorInjectionRector::GET_METHOD_AWARE_TYPES => [
'SymfonyControllerClassName', 'GetTraitClassName']
]]);
};
```
```diff
-class MyCommand extends ContainerAwareCommand
+class MyCommand extends Command

View File

@ -6,7 +6,7 @@ namespace Rector\FileSystemRector\Rector\Removing;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\FileSystemRector\Configuration\Option;
use Rector\FileSystemRector\Rector\AbstractFileSystemRector;
@ -47,13 +47,18 @@ final class RemoveProjectFileRector extends AbstractFileSystemRector implements
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Remove file relative to project directory', [
new CodeSample(
new ConfiguredCodeSample(
<<<'CODE_SAMPLE'
// someFile/ToBeRemoved.txt
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
CODE_SAMPLE
,
[
self::FILE_PATHS_TO_REMOVE => ['someFile/ToBeRemoved.txt'],
]
),
]);
}

View File

@ -8,7 +8,7 @@ use Nette\Utils\Strings;
use PhpParser\Node\Stmt\Class_;
use Rector\Autodiscovery\Analyzer\ClassAnalyzer;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\FileSystemRector\Rector\AbstractFileMovingFileSystemRector;
use Rector\NodeTypeResolver\Node\AttributeKey;
@ -75,7 +75,7 @@ final class MoveValueObjectsToValueObjectDirectoryRector extends AbstractFileMov
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Move value object to ValueObject namespace/directory', [
new CodeSample(
new ConfiguredCodeSample(
<<<'CODE_SAMPLE'
// app/Exception/Name.php
class Name
@ -111,6 +111,12 @@ class Name
}
}
CODE_SAMPLE
,
[
self::TYPES => ['ValueObjectInterfaceClassName'],
self::SUFFIXES => ['Search'],
self::ENABLE_VALUE_OBJECT_GUESSING => true,
]
),
]);
}

View File

@ -12,7 +12,7 @@ use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Scalar\String_;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
/**
@ -68,7 +68,7 @@ final class ConsistentPregDelimiterRector extends AbstractRector implements Conf
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Replace PREG delimiter with configured one', [
new CodeSample(
new ConfiguredCodeSample(
<<<'PHP'
class SomeClass
{
@ -90,6 +90,10 @@ class SomeClass
}
}
PHP
,
[
self::DELIMITER => '#',
]
),
]);
}

View File

@ -10,7 +10,7 @@ use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Name;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
/**
@ -31,8 +31,8 @@ final class FunctionCallToConstantRector extends AbstractRector implements Confi
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Changes use of function calls to use constants', [
new CodeSample(
<<<'EOS'
new ConfiguredCodeSample(
<<<'CODE_SAMPLE'
class SomeClass
{
public function run()
@ -40,9 +40,9 @@ class SomeClass
$value = php_sapi_name();
}
}
EOS
CODE_SAMPLE
,
<<<'EOS'
<<<'CODE_SAMPLE'
class SomeClass
{
public function run()
@ -50,10 +50,16 @@ class SomeClass
$value = PHP_SAPI;
}
}
EOS
CODE_SAMPLE
,
[
self::FUNCTIONS_TO_CONSTANTS => [
'php_sapi_name' => 'PHP_SAPI',
],
]
),
new CodeSample(
<<<'EOS'
new ConfiguredCodeSample(
<<<'CODE_SAMPLE'
class SomeClass
{
public function run()
@ -61,9 +67,9 @@ class SomeClass
$value = pi();
}
}
EOS
CODE_SAMPLE
,
<<<'EOS'
<<<'CODE_SAMPLE'
class SomeClass
{
public function run()
@ -71,7 +77,13 @@ class SomeClass
$value = M_PI;
}
}
EOS
CODE_SAMPLE
,
[
self::FUNCTIONS_TO_CONSTANTS => [
'pi' => 'M_PI',
],
]
),
]);
}

View File

@ -52,7 +52,7 @@ final class VersionCompareFuncCallToConstantRector extends AbstractRector
{
return new RectorDefinition('Changes use of call to version compare function to use of PHP version constant', [
new CodeSample(
<<<'EOS'
<<<'CODE_SAMPLE'
class SomeClass
{
public function run()
@ -60,9 +60,9 @@ class SomeClass
version_compare(PHP_VERSION, '5.3.0', '<');
}
}
EOS
CODE_SAMPLE
,
<<<'EOS'
<<<'CODE_SAMPLE'
class SomeClass
{
public function run()
@ -70,7 +70,7 @@ class SomeClass
PHP_VERSION_ID < 50300;
}
}
EOS
CODE_SAMPLE
),
]);
}

View File

@ -15,7 +15,7 @@ use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Scalar\String_;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
/**
@ -48,7 +48,7 @@ final class EntityAliasToClassConstantReferenceRector extends AbstractRector imp
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Replaces doctrine alias with class.', [
new CodeSample(
new ConfiguredCodeSample(
<<<'PHP'
$entityManager = new Doctrine\ORM\EntityManager();
$entityManager->getRepository("AppBundle:Post");
@ -58,6 +58,12 @@ PHP
$entityManager = new Doctrine\ORM\EntityManager();
$entityManager->getRepository(\App\Entity\Post::class);
PHP
,
[
self::ALIASES_TO_NAMESPACES => [
'App' => 'App\Entity',
],
]
),
]);
}

View File

@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Rector\DowngradePhp72\Rector\FunctionLike;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
/**
@ -17,7 +17,7 @@ final class DowngradeParamObjectTypeDeclarationRector extends AbstractDowngradeP
return new RectorDefinition(
$this->getRectorDefinitionDescription(),
[
new CodeSample(
new ConfiguredCodeSample(
<<<'PHP'
<?php
@ -42,6 +42,10 @@ class SomeClass
}
}
PHP
,
[
self::ADD_DOC_BLOCK => true,
]
),
]
);

View File

@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Rector\DowngradePhp72\Rector\FunctionLike;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
/**
@ -17,7 +17,7 @@ final class DowngradeReturnObjectTypeDeclarationRector extends AbstractDowngrade
return new RectorDefinition(
$this->getRectorDefinitionDescription(),
[
new CodeSample(
new ConfiguredCodeSample(
<<<'PHP'
<?php
@ -44,6 +44,10 @@ class SomeClass
}
}
PHP
,
[
self::ADD_DOC_BLOCK => true,
]
),
]
);

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
namespace Rector\DowngradePhp74\Rector\Property;
use PhpParser\Node\Stmt\Property;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
/**
@ -17,7 +17,7 @@ final class DowngradeTypedPropertyRector extends AbstractDowngradeTypedPropertyR
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Changes property type definition from type definitions to `@var` annotations.', [
new CodeSample(
new ConfiguredCodeSample(
<<<'PHP'
class SomeClass
{
@ -34,6 +34,10 @@ class SomeClass
private $property;
}
PHP
,
[
self::ADD_DOC_BLOCK => true,
]
),
]);
}

View File

@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Rector\DowngradePhp80\Rector\FunctionLike;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\DowngradePhp72\Rector\FunctionLike\AbstractDowngradeParamTypeDeclarationRector;
@ -18,7 +18,7 @@ final class DowngradeParamMixedTypeDeclarationRector extends AbstractDowngradePa
return new RectorDefinition(
$this->getRectorDefinitionDescription(),
[
new CodeSample(
new ConfiguredCodeSample(
<<<'PHP'
<?php
@ -43,6 +43,10 @@ class SomeClass
}
}
PHP
,
[
self::ADD_DOC_BLOCK => true,
]
),
]
);

View File

@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Rector\DowngradePhp80\Rector\FunctionLike;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\DowngradePhp72\Rector\FunctionLike\AbstractDowngradeReturnTypeDeclarationRector;
@ -18,7 +18,7 @@ final class DowngradeReturnMixedTypeDeclarationRector extends AbstractDowngradeR
return new RectorDefinition(
$this->getRectorDefinitionDescription(),
[
new CodeSample(
new ConfiguredCodeSample(
<<<'PHP'
<?php
@ -51,6 +51,10 @@ class SomeClass
}
}
PHP
,
[
self::ADD_DOC_BLOCK => true,
]
),
]
);

View File

@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Rector\DowngradePhp80\Rector\FunctionLike;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\DowngradePhp72\Rector\FunctionLike\AbstractDowngradeReturnTypeDeclarationRector;
@ -18,7 +18,7 @@ final class DowngradeReturnStaticTypeDeclarationRector extends AbstractDowngrade
return new RectorDefinition(
$this->getRectorDefinitionDescription(),
[
new CodeSample(
new ConfiguredCodeSample(
<<<'PHP'
<?php
@ -45,6 +45,10 @@ class SomeClass
}
}
PHP
,
[
self::ADD_DOC_BLOCK => true,
]
),
]
);

View File

@ -6,7 +6,7 @@ namespace Rector\DowngradePhp80\Rector\FunctionLike;
use PhpParser\Node\Param;
use PhpParser\Node\UnionType;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\DowngradePhp72\Rector\FunctionLike\AbstractDowngradeParamDeclarationRector;
@ -20,7 +20,7 @@ final class DowngradeUnionTypeParamDeclarationRector extends AbstractDowngradePa
return new RectorDefinition(
'Remove the union type params, add @param tags instead',
[
new CodeSample(
new ConfiguredCodeSample(
<<<'PHP'
<?php
@ -47,6 +47,10 @@ class SomeClass
}
}
PHP
,
[
self::ADD_DOC_BLOCK => true,
]
),
]
);

View File

@ -8,7 +8,7 @@ use PhpParser\Node\FunctionLike;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Function_;
use PhpParser\Node\UnionType;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\DowngradePhp72\Rector\FunctionLike\AbstractDowngradeReturnDeclarationRector;
@ -22,7 +22,7 @@ final class DowngradeUnionTypeReturnDeclarationRector extends AbstractDowngradeR
return new RectorDefinition(
'Remove returning union types, add a @return tag instead',
[
new CodeSample(
new ConfiguredCodeSample(
<<<'PHP'
<?php
@ -55,6 +55,10 @@ class SomeClass
}
}
PHP
,
[
self::ADD_DOC_BLOCK => true,
]
),
]
);

View File

@ -6,7 +6,7 @@ namespace Rector\DowngradePhp80\Rector\Property;
use PhpParser\Node\Stmt\Property;
use PhpParser\Node\UnionType;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\DowngradePhp74\Rector\Property\AbstractDowngradeTypedPropertyRector;
@ -18,7 +18,7 @@ final class DowngradeUnionTypeTypedPropertyRector extends AbstractDowngradeTyped
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Removes union type property type definition, adding `@var` annotations instead.', [
new CodeSample(
new ConfiguredCodeSample(
<<<'PHP'
class SomeClass
{
@ -35,6 +35,10 @@ class SomeClass
private $property;
}
PHP
,
[
self::ADD_DOC_BLOCK => true,
]
),
]);
}

View File

@ -11,7 +11,7 @@ use PhpParser\Node\Stmt\Trait_;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\PhpParser\Node\Manipulator\ClassManipulator;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\NodeTypeResolver\Node\AttributeKey;
@ -48,7 +48,7 @@ final class RemoveTraitRector extends AbstractRector implements ConfigurableRect
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Remove specific traits from code', [
new CodeSample(
new ConfiguredCodeSample(
<<<'PHP'
class SomeClass
{
@ -61,6 +61,10 @@ class SomeClass
{
}
PHP
,
[
self::TRAITS_TO_REMOVE => ['TraitNameToRemove'],
]
),
]);
}

View File

@ -10,7 +10,7 @@ use PhpParser\Node\Expr\New_;
use PhpParser\Node\Name\FullyQualified;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
/**
@ -31,7 +31,7 @@ final class FuncCallToNewRector extends AbstractRector implements ConfigurableRe
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Change configured function calls to new Instance', [
new CodeSample(
new ConfiguredCodeSample(
<<<'PHP'
class SomeClass
{
@ -51,6 +51,12 @@ class SomeClass
}
}
PHP
,
[
self::FUNCTION_TO_NEW => [
'collection' => ['Collection'],
],
]
),
]);
}

View File

@ -12,7 +12,7 @@ use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\Expression;
use PhpParser\Node\Stmt\Nop;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\FileSystemRector\Rector\AbstractFileSystemRector;
use Symplify\SmartFileSystem\SmartFileInfo;
@ -49,12 +49,13 @@ final class AddTopIncludeRector extends AbstractFileSystemRector implements Conf
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Adds an include file at the top of matching files, except class definitions', [
new CodeSample(
new ConfiguredCodeSample(
<<<'PHP'
if (isset($_POST['csrf'])) {
processPost($_POST);
}
PHP,
PHP
,
<<<'PHP'
require_once __DIR__ . '/../autoloader.php';
@ -62,6 +63,11 @@ if (isset($_POST['csrf'])) {
processPost($_POST);
}
PHP
,
[
self::AUTOLOAD_FILE_PATH => '/../autoloader.php',
self::PATTERNS => ['pat*/*/?ame.php', 'somepath/?ame.php'],
]
),
]);
}

View File

@ -1,48 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\MagicDisclosure\Rector\AbstractRector;
use Rector\Core\Rector\AbstractRector;
abstract class AbstractConfigurableMatchTypeRector extends AbstractRector
{
/**
* @api
* @var string
*/
public const TYPES_TO_MATCH = 'types_to_match';
/**
* @var string[]
*/
private $typesToMatch = [];
/**
* @param string[][] $configuration
*/
public function configure(array $configuration): void
{
$this->typesToMatch = $configuration[self::TYPES_TO_MATCH] ?? [];
}
protected function isMatchedType(string $currentType): bool
{
if ($this->typesToMatch === []) {
return true;
}
foreach ($this->typesToMatch as $typeToMatch) {
if (fnmatch($typeToMatch, $currentType, FNM_NOESCAPE)) {
return true;
}
if (is_a($currentType, $typeToMatch, true)) {
return true;
}
}
return false;
}
}

View File

@ -5,16 +5,15 @@ declare(strict_types=1);
namespace Rector\MagicDisclosure\Rector\MethodCall;
use PhpParser\Node\Expr\MethodCall;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\Rector\AbstractRector;
use Rector\MagicDisclosure\NodeAnalyzer\ChainCallsStaticTypeResolver;
use Rector\MagicDisclosure\NodeAnalyzer\FluentChainMethodCallNodeAnalyzer;
use Rector\MagicDisclosure\NodeFactory\NonFluentChainMethodCallFactory;
use Rector\MagicDisclosure\NodeManipulator\FluentChainMethodCallRootExtractor;
use Rector\MagicDisclosure\Rector\AbstractRector\AbstractConfigurableMatchTypeRector;
use Rector\MagicDisclosure\ValueObject\AssignAndRootExpr;
use Rector\MagicDisclosure\ValueObject\AssignAndRootExprAndNodesToAdd;
abstract class AbstractFluentChainMethodCallRector extends AbstractConfigurableMatchTypeRector implements ConfigurableRectorInterface
abstract class AbstractFluentChainMethodCallRector extends AbstractRector
{
/**
* Skip query and builder

View File

@ -24,17 +24,21 @@ final class FluentChainMethodCallToNormalMethodCallRector extends AbstractFluent
{
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Turns fluent interface calls to classic ones.', [new CodeSample(<<<'PHP'
return new RectorDefinition('Turns fluent interface calls to classic ones.', [
new CodeSample(
<<<'PHP'
$someClass = new SomeClass();
$someClass->someFunction()
->otherFunction();
PHP
, <<<'PHP'
,
<<<'PHP'
$someClass = new SomeClass();
$someClass->someFunction();
$someClass->otherFunction();
PHP
)]);
),
]);
}
/**

View File

@ -59,7 +59,8 @@ final class MockeryCreateMockToProphizeRector extends AbstractPHPUnitRector
$mock = \Mockery::mock(\'MyClass\');
$service = new Service();
$service->injectDependency($mock);
PHP,
PHP
,
<<<'PHP'
$mock = $this->prophesize(\'MyClass\');

View File

@ -52,7 +52,8 @@ public function tearDown() : void
{
\Mockery::close();
}
PHP,
PHP
,
<<<'PHP'
public function tearDown() : void
{

View File

@ -13,7 +13,7 @@ use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\UnionType;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\Core\ValueObject\MethodName;
use Rector\NodeTypeResolver\Node\AttributeKey;
@ -38,7 +38,7 @@ final class OrderConstructorDependenciesByTypeAlphabeticallyRector extends Abstr
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Order __constructor dependencies by type A-Z', [
new CodeSample(
new ConfiguredCodeSample(
<<<'PHP'
class SomeClass
{
@ -64,6 +64,10 @@ class SomeClass
}
}
PHP
,
[
self::SKIP_PATTERNS => ['Cla*ame', 'Ano?herClassName'],
]
),
]);
}

View File

@ -10,7 +10,7 @@ use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Scalar\String_;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\Core\Util\StaticRectorStrings;
use Rector\Core\ValueObject\PhpVersionFeature;
@ -54,7 +54,7 @@ final class StringClassNameToClassConstantRector extends AbstractRector implemen
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Replace string class names by <class>::class constant', [
new CodeSample(
new ConfiguredCodeSample(
<<<'PHP'
class AnotherClass
{
@ -82,6 +82,10 @@ class SomeClass
}
}
PHP
,
[
self::CLASSES_TO_SKIP => ['ClassName', 'AnotherClassName'],
]
),
]);
}

View File

@ -10,7 +10,7 @@ use PhpParser\Node\Name;
use PhpParser\Node\Stmt\Namespace_;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\NodeTypeResolver\Node\AttributeKey;
@ -35,7 +35,7 @@ final class ReservedObjectRector extends AbstractRector implements ConfigurableR
{
return new RectorDefinition(
'Changes reserved "Object" name to "<Smart>Object" where <Smart> can be configured',
[new CodeSample(<<<'PHP'
[new ConfiguredCodeSample(<<<'PHP'
class Object
{
}
@ -45,6 +45,13 @@ class SmartObject
{
}
PHP
,
[
self::RESERVED_KEYWORDS_TO_REPLACEMENTS => [
'ReservedObject' => 'SmartObject',
'Object' => 'AnotherSmartObject',
],
]
)]
);
}

View File

@ -11,7 +11,7 @@ use PhpParser\Node\Name;
use PhpParser\Node\Stmt\Function_;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
/**
@ -34,7 +34,7 @@ final class ReservedFnFunctionRector extends AbstractRector implements Configura
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Change fn() function name, since it will be reserved keyword', [
new CodeSample(
new ConfiguredCodeSample(
<<<'PHP'
class SomeClass
{
@ -64,6 +64,12 @@ class SomeClass
}
}
PHP
,
[
self::RESERVED_NAMES_TO_NEW_ONES => [
'fn' => 'someFunctionName',
],
]
),
]);
}

View File

@ -20,7 +20,7 @@ use Rector\AttributeAwarePhpDoc\Ast\Type\AttributeAwareArrayTypeNode;
use Rector\AttributeAwarePhpDoc\Ast\Type\AttributeAwareUnionTypeNode;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\Core\ValueObject\PhpVersionFeature;
use Rector\NodeTypeResolver\ClassExistenceStaticHelper;
@ -82,7 +82,7 @@ final class TypedPropertyRector extends AbstractRector implements ConfigurableRe
return new RectorDefinition(
'Changes property `@var` annotations from annotation to type.',
[
new CodeSample(
new ConfiguredCodeSample(
<<<'PHP'
final class SomeClass
{
@ -99,6 +99,10 @@ final class SomeClass
private int count;
}
PHP
,
[
self::CLASS_LIKE_TYPE_ONLY => false,
]
),
]
);

View File

@ -14,7 +14,7 @@ use PHPStan\Type\ObjectType;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\Naming\Naming\PropertyNaming;
use Rector\PHPStan\Type\FullyQualifiedObjectType;
@ -72,7 +72,7 @@ final class NewUniqueObjectToEntityFactoryRector extends AbstractRector implemen
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Convert new X to new factories', [
new CodeSample(
new ConfiguredCodeSample(
<<<'PHP'
<?php
@ -115,6 +115,10 @@ class AnotherClass
}
}
PHP
,
[
self::TYPES_TO_SERVICES => ['ClassName'],
]
), ]);
}

View File

@ -9,7 +9,7 @@ use PhpParser\Node\Expr\ConstFetch;
use PhpParser\Node\Name;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
/**
@ -30,7 +30,7 @@ final class RenameConstantRector extends AbstractRector implements ConfigurableR
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Replace constant by new ones', [
new CodeSample(
new ConfiguredCodeSample(
<<<'PHP'
final class SomeClass
{
@ -50,6 +50,13 @@ final class SomeClass
}
}
PHP
,
[
self::OLD_TO_NEW_CONSTANTS => [
'MYSQL_ASSOC' => 'MYSQLI_ASSOC',
'OLD_CONSTANT' => 'NEW_CONSTANT',
],
]
),
]);
}

View File

@ -7,7 +7,7 @@ namespace Rector\Symfony\Rector\MethodCall;
use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\NodeTypeResolver\Node\AttributeKey;
@ -36,7 +36,7 @@ final class ContainerGetToConstructorInjectionRector extends AbstractToConstruct
return new RectorDefinition(
'Turns fetching of dependencies via `$container->get()` in ContainerAware to constructor injection in Command and Controller in Symfony',
[
new CodeSample(
new ConfiguredCodeSample(
<<<'PHP'
final class SomeCommand extends ContainerAwareCommand
{
@ -65,6 +65,14 @@ final class SomeCommand extends Command
}
}
PHP
,
[
self::CONTAINER_AWARE_PARENT_TYPES => [
'ContainerAwareParentClassName',
'ContainerAwareParentCommandClassName',
'ThisClassCallsMethodInConstructorClassName',
],
]
),
]
);

View File

@ -7,7 +7,7 @@ namespace Rector\Symfony\Rector\MethodCall;
use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
/**
@ -33,7 +33,7 @@ final class GetToConstructorInjectionRector extends AbstractToConstructorInjecti
return new RectorDefinition(
'Turns fetching of dependencies via `$this->get()` to constructor injection in Command and Controller in Symfony',
[
new CodeSample(
new ConfiguredCodeSample(
<<<'PHP'
class MyCommand extends ContainerAwareCommand
{
@ -59,6 +59,10 @@ class MyCommand extends Command
}
}
PHP
,
[
self::GET_METHOD_AWARE_TYPES => ['SymfonyControllerClassName', 'GetTraitClassName'],
]
),
]
);

View File

@ -15,6 +15,10 @@ services:
class: Rector\PHPStanExtensions\Rule\CheckNotTestsNamespaceOutsideTestsDirectoryRule
tags: [phpstan.rules.rule]
-
class: Rector\PHPStanExtensions\Rule\ConfigurableRectorRule
tags: [phpstan.rules.rule]
- Rector\PHPStanExtensions\Utils\PHPStanValueResolver
# $node->getAttribute($1) => Type|null by $1

View File

@ -0,0 +1,115 @@
<?php
declare(strict_types=1);
namespace Rector\PHPStanExtensions\Rule;
use Nette\Utils\Strings;
use PhpParser\Node;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Name;
use PhpParser\Node\Stmt\Class_;
use PhpParser\NodeFinder;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
/**
* @see \Rector\PHPStanExtensions\Tests\Rule\ConfigurableRectorRule\ConfigurableRectorRuleTest
*/
final class ConfigurableRectorRule implements Rule
{
/**
* @var string
*/
public const ERROR_NO_CONFIGURED_CODE_SAMPLE = 'Configurable rules must have configure code sample';
/**
* @var string
*/
public const ERROR_NOT_IMPLEMENTS_INTERFACE = 'Configurable code sample is used but interface is not implemented';
public function getNodeType(): string
{
return Class_::class;
}
/**
* @param Class_ $node
* @return string[]
*/
public function processNode(Node $node, Scope $scope): array
{
if (! $this->hasRectorInClassName($node)) {
return [];
}
if ($node->isAbstract()) {
return [];
}
if (! $this->implementsConfigurableInterface($node)) {
if ($this->hasConfiguredCodeSample($node)) {
return [self::ERROR_NOT_IMPLEMENTS_INTERFACE];
}
return [];
}
if ($this->hasConfiguredCodeSample($node)) {
return [];
}
return [self::ERROR_NO_CONFIGURED_CODE_SAMPLE];
}
private function hasRectorInClassName(Class_ $class): bool
{
if ($class->name === null) {
return false;
}
return Strings::match($class->name->toString(), '#Rector$#') !== null;
}
private function implementsConfigurableInterface(Class_ $class): bool
{
if ($class->namespacedName === null) {
return false;
}
return is_a($class->namespacedName->toString(), ConfigurableRectorInterface::class, true);
}
private function hasConfiguredCodeSample(Class_ $class): bool
{
$classMethod = $class->getMethod('getDefinition');
if ($classMethod === null) {
return false;
}
if ($classMethod->stmts === null) {
return false;
}
$nodeFinder = new NodeFinder();
$nodes = $nodeFinder->find($classMethod->stmts, function (Node $node): ?New_ {
if (! $node instanceof New_) {
return null;
}
$className = $node->class;
if (! $className instanceof Name) {
return null;
}
if (is_a($className->toString(), ConfiguredCodeSample::class, true)) {
return $node;
}
return null;
});
return $nodes !== [];
}
}

View File

@ -0,0 +1,49 @@
<?php
declare(strict_types=1);
namespace Rector\PHPStanExtensions\Tests\Rule\ConfigurableRectorRule;
use Iterator;
use PHPStan\Rules\Rule;
use PHPStan\Testing\RuleTestCase;
use Rector\PHPStanExtensions\Rule\ConfigurableRectorRule;
final class ConfigurableRectorRuleTest extends RuleTestCase
{
/**
* @dataProvider provideData()
*/
public function testRule(string $filePath, array $expectedErrorsWithLines): void
{
$this->analyse([$filePath], $expectedErrorsWithLines);
}
public function provideData(): Iterator
{
yield [__DIR__ . '/Fixture/ImplementsAndHasConfiguredCodeSampleRector.php', []];
yield [
__DIR__ . '/Fixture/ImplementsAndHasNoConfiguredCodeSampleRector.php',
[[ConfigurableRectorRule::ERROR_NO_CONFIGURED_CODE_SAMPLE, 13]],
];
yield [
__DIR__ . '/Fixture/NotImplementsAndHasConfiguredCodeSampleRector.php',
[[ConfigurableRectorRule::ERROR_NOT_IMPLEMENTS_INTERFACE, 12]],
];
yield [__DIR__ . '/Fixture/NotImplementsAndHasNoConfiguredCodeSampleRector.php', []];
yield [__DIR__ . '/Fixture/ImplementsThroughAbstractClassRector.php', []];
yield [__DIR__ . '/Fixture/SkipClassNamesWithoutRectorSuffix.php', []];
yield [__DIR__ . '/Fixture/SkipAbstractRector.php', []];
}
protected function getRule(): Rule
{
return new ConfigurableRectorRule();
}
}

View File

@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
namespace Rector\PHPStanExtensions\Tests\Rule\ConfigurableRectorRule\Fixture;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\Transform\ValueObject\StaticCallToFuncCall;
final class ImplementsAndHasConfiguredCodeSampleRector implements ConfigurableRectorInterface
{
/**
* @var string
*/
public const STATIC_CALLS_TO_FUNCTIONS = 'static_calls_to_functions';
public function configure(array $configuration): void
{
// TODO: Implement configure() method.
}
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Turns static call to function call.', [
new ConfiguredCodeSample(
'OldClass::oldMethod("args");',
'new_function("args");',
[
self::STATIC_CALLS_TO_FUNCTIONS => [
new StaticCallToFuncCall('OldClass', 'oldMethod', 'new_function'),
],
]
),
]);
}
}

View File

@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
namespace Rector\PHPStanExtensions\Tests\Rule\ConfigurableRectorRule\Fixture;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\Transform\ValueObject\StaticCallToFuncCall;
final class ImplementsAndHasNoConfiguredCodeSampleRector implements ConfigurableRectorInterface
{
public function configure(array $configuration): void
{
// TODO: Implement configure() method.
}
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Turns static call to function call.', [
new CodeSample(
'OldClass::oldMethod("args");',
'new_function("args");'
),
]);
}
}

View File

@ -0,0 +1,36 @@
<?php
namespace Rector\PHPStanExtensions\Tests\Rule\ConfigurableRectorRule\Fixture;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\PHPStanExtensions\Tests\Rule\ConfigurableRectorRule\Source\AbstractClassImplementsConfigurableInterface;
use Rector\Transform\ValueObject\StaticCallToFuncCall;
class ImplementsThroughAbstractClassRector extends AbstractClassImplementsConfigurableInterface
{
/**
* @var string
*/
public const STATIC_CALLS_TO_FUNCTIONS = 'static_calls_to_functions';
public function configure(array $configuration): void
{
// TODO: Implement configure() method.
}
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Turns static call to function call.', [
new ConfiguredCodeSample(
'OldClass::oldMethod("args");',
'new_function("args");',
[
self::STATIC_CALLS_TO_FUNCTIONS => [
new StaticCallToFuncCall('OldClass', 'oldMethod', 'new_function'),
],
]
),
]);
}
}

View File

@ -0,0 +1,33 @@
<?php
declare(strict_types=1);
namespace Rector\PHPStanExtensions\Tests\Rule\ConfigurableRectorRule\Fixture;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\Transform\ValueObject\StaticCallToFuncCall;
final class NotImplementsAndHasConfiguredCodeSampleRector
{
/**
* @var string
*/
public const STATIC_CALLS_TO_FUNCTIONS = 'static_calls_to_functions';
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Turns static call to function call.', [
new ConfiguredCodeSample(
'OldClass::oldMethod("args");',
'new_function("args");',
[
self::STATIC_CALLS_TO_FUNCTIONS => [
new StaticCallToFuncCall('OldClass', 'oldMethod', 'new_function'),
],
]
),
]);
}
}

View File

@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
namespace Rector\PHPStanExtensions\Tests\Rule\ConfigurableRectorRule\Fixture;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\Transform\ValueObject\StaticCallToFuncCall;
final class NotImplementsAndHasNoConfiguredCodeSampleRector
{
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Turns static call to function call.', [
new CodeSample(
'OldClass::oldMethod("args");',
'new_function("args");'
),
]);
}
}

View File

@ -0,0 +1,12 @@
<?php
namespace Rector\PHPStanExtensions\Tests\Rule\ConfigurableRectorRule\Fixture;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
abstract class SkipAbstractRector implements ConfigurableRectorInterface
{
}

View File

@ -0,0 +1,10 @@
<?php
declare(strict_types=1);
namespace Rector\PHPStanExtensions\Tests\Rule\ConfigurableRectorRule\Fixture;
final class SkipClassNamesWithoutRectorSuffix
{
}

View File

@ -0,0 +1,12 @@
<?php
namespace Rector\PHPStanExtensions\Tests\Rule\ConfigurableRectorRule\Source;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
abstract class AbstractClassImplementsConfigurableInterface implements ConfigurableRectorInterface
{
}