Updated Rector to commit 21f8014b30f4a4230f787ca1698a2c53d6d5f18a

21f8014b30 [DI] Autowire annotation to attribute mapper via tags (#4190)
This commit is contained in:
Tomas Votruba 2023-06-12 10:45:32 +00:00
parent 1b3ee4f289
commit ff28aaca4c
48 changed files with 99 additions and 2436 deletions

View File

@ -63,6 +63,8 @@ use Rector\NodeTypeResolver\PHPStan\Scope\PHPStanNodeScopeResolver;
use Rector\NodeTypeResolver\Reflection\BetterReflection\SourceLocator\IntermediateSourceLocator;
use Rector\NodeTypeResolver\Reflection\BetterReflection\SourceLocatorProvider\DynamicSourceLocatorProvider;
use Rector\Parallel\WorkerRunner;
use Rector\PhpAttribute\AnnotationToAttributeMapper;
use Rector\PhpAttribute\Contract\AnnotationToAttributeMapperInterface;
use Rector\PhpDocParser\NodeTraverser\SimpleCallableNodeTraverser;
use Rector\PhpDocParser\PhpParser\SmartPhpParser;
use Rector\PhpDocParser\PhpParser\SmartPhpParserFactory;
@ -202,4 +204,5 @@ return static function (RectorConfig $rectorConfig) : void {
$services->set(ApplicationFileProcessor::class)->arg('$fileProcessors', tagged_iterator(FileProcessorInterface::class));
$services->set(FileFactory::class)->arg('$fileProcessors', tagged_iterator(FileProcessorInterface::class));
$services->set(WorkerRunner::class)->arg('$fileProcessors', tagged_iterator(FileProcessorInterface::class));
$services->set(AnnotationToAttributeMapper::class)->arg('$annotationToAttributeMappers', tagged_iterator(AnnotationToAttributeMapperInterface::class));
};

View File

@ -1,41 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\Defluent\NodeAnalyzer;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Name;
/**
* Utils for chain of MethodCall Node:
* "$this->methodCall()->chainedMethodCall()"
*/
final class FluentChainMethodCallNodeAnalyzer
{
/**
* @api doctrine
*/
public function resolveRootMethodCall(MethodCall $methodCall) : ?MethodCall
{
$callerNode = $methodCall->var;
while ($callerNode instanceof MethodCall && $callerNode->var instanceof MethodCall) {
$callerNode = $callerNode->var;
}
if ($callerNode instanceof MethodCall) {
return $callerNode;
}
return null;
}
/**
* @return \PhpParser\Node\Expr|\PhpParser\Node\Name
*/
public function resolveRootExpr(MethodCall $methodCall)
{
$callerNode = $methodCall->var;
while ($callerNode instanceof MethodCall || $callerNode instanceof StaticCall) {
$callerNode = $callerNode instanceof StaticCall ? $callerNode->class : $callerNode->var;
}
return $callerNode;
}
}

View File

@ -10,16 +10,9 @@ use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode;
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
use Rector\BetterPhpDocParser\PhpDoc\StringNode;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\PhpAttribute\AnnotationToAttributeMapper\ArrayAnnotationToAttributeMapper;
use Rector\PhpAttribute\AnnotationToAttributeMapper\ArrayItemNodeAnnotationToAttributeMapper;
use Rector\PhpAttribute\AnnotationToAttributeMapper\ClassConstFetchAnnotationToAttributeMapper;
use Rector\PhpAttribute\AnnotationToAttributeMapper\ConstExprNodeAnnotationToAttributeMapper;
use Rector\PhpAttribute\AnnotationToAttributeMapper\CurlyListNodeAnnotationToAttributeMapper;
use Rector\PhpAttribute\AnnotationToAttributeMapper\DoctrineAnnotationAnnotationToAttributeMapper;
use Rector\PhpAttribute\AnnotationToAttributeMapper\StringAnnotationToAttributeMapper;
use Rector\PhpAttribute\AnnotationToAttributeMapper\StringNodeAnnotationToAttributeMapper;
use Rector\PhpAttribute\Contract\AnnotationToAttributeMapperInterface;
use Rector\PhpAttribute\Enum\DocTagNodeState;
use RectorPrefix202306\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
/**
* @see \Rector\Tests\PhpAttribute\AnnotationToAttributeMapper\AnnotationToAttributeMapperTest
*/
@ -29,19 +22,12 @@ final class AnnotationToAttributeMapper
* @var AnnotationToAttributeMapperInterface[]
*/
private $annotationToAttributeMappers = [];
public function __construct(
// private readonly array $annotationToAttributeMappers,
ArrayAnnotationToAttributeMapper $arrayAnnotationToAttributeMapper,
ArrayItemNodeAnnotationToAttributeMapper $arrayItemNodeAnnotationToAttributeMapper,
ClassConstFetchAnnotationToAttributeMapper $classConstFetchAnnotationToAttributeMapper,
ConstExprNodeAnnotationToAttributeMapper $constExprNodeAnnotationToAttributeMapper,
CurlyListNodeAnnotationToAttributeMapper $curlyListNodeAnnotationToAttributeMapper,
DoctrineAnnotationAnnotationToAttributeMapper $doctrineAnnotationAnnotationToAttributeMapper,
StringAnnotationToAttributeMapper $stringAnnotationToAttributeMapper,
StringNodeAnnotationToAttributeMapper $stringNodeAnnotationToAttributeMapper
)
/**
* @param RewindableGenerator<AnnotationToAttributeMapperInterface> $annotationToAttributeMappers
*/
public function __construct(iterable $annotationToAttributeMappers)
{
$this->annotationToAttributeMappers = [$arrayAnnotationToAttributeMapper, $arrayItemNodeAnnotationToAttributeMapper, $classConstFetchAnnotationToAttributeMapper, $constExprNodeAnnotationToAttributeMapper, $curlyListNodeAnnotationToAttributeMapper, $doctrineAnnotationAnnotationToAttributeMapper, $stringAnnotationToAttributeMapper, $stringNodeAnnotationToAttributeMapper];
$this->annotationToAttributeMappers = \iterator_to_array($annotationToAttributeMappers->getIterator());
}
/**
* @return Expr|DocTagNodeState::REMOVE_ARRAY

View File

@ -4,8 +4,7 @@ declare (strict_types=1);
namespace Rector\Php80\AttributeDecorator;
use PhpParser\Node\Attribute;
use Rector\Php80\Contract\AttributeDecoratorInterface;
final class SensioParamConverterAttributeDecorator implements AttributeDecoratorInterface
final class SensioParamConverterAttributeDecorator
{
public function getAttributeName() : string
{

View File

@ -1,11 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\Php80\Contract;
use PhpParser\Node\Attribute;
interface AttributeDecoratorInterface
{
public function getAttributeName() : string;
public function decorate(Attribute $attribute) : void;
}

View File

@ -6,16 +6,16 @@ namespace Rector\Php80\NodeManipulator;
use PhpParser\Node\AttributeGroup;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\Php80\AttributeDecorator\SensioParamConverterAttributeDecorator;
use Rector\Php80\Contract\AttributeDecoratorInterface;
final class AttributeGroupNamedArgumentManipulator
{
/**
* @var AttributeDecoratorInterface[]
* @readonly
* @var \Rector\Php80\AttributeDecorator\SensioParamConverterAttributeDecorator
*/
private $attributeDecorators = [];
private $sensioParamConverterAttributeDecorator;
public function __construct(SensioParamConverterAttributeDecorator $sensioParamConverterAttributeDecorator)
{
$this->attributeDecorators[] = $sensioParamConverterAttributeDecorator;
$this->sensioParamConverterAttributeDecorator = $sensioParamConverterAttributeDecorator;
}
/**
* @param AttributeGroup[] $attributeGroups
@ -25,12 +25,10 @@ final class AttributeGroupNamedArgumentManipulator
foreach ($attributeGroups as $attributeGroup) {
foreach ($attributeGroup->attrs as $attr) {
$phpAttributeName = $attr->name->getAttribute(AttributeKey::PHP_ATTRIBUTE_NAME);
foreach ($this->attributeDecorators as $attributeDecorator) {
if ($attributeDecorator->getAttributeName() !== $phpAttributeName) {
continue;
}
$attributeDecorator->decorate($attr);
if ($this->sensioParamConverterAttributeDecorator->getAttributeName() !== $phpAttributeName) {
continue;
}
$this->sensioParamConverterAttributeDecorator->decorate($attr);
}
}
}

View File

@ -19,12 +19,12 @@ final class VersionResolver
* @api
* @var string
*/
public const PACKAGE_VERSION = '7a61135453ff9fa595966f0265cb2a3c28c13656';
public const PACKAGE_VERSION = '21f8014b30f4a4230f787ca1698a2c53d6d5f18a';
/**
* @api
* @var string
*/
public const RELEASE_DATE = '2023-06-12 10:14:34';
public const RELEASE_DATE = '2023-06-12 10:40:54';
/**
* @var int
*/

View File

@ -15,6 +15,7 @@ use Rector\Core\Contract\Rector\RectorInterface;
use Rector\NodeNameResolver\Contract\NodeNameResolverInterface;
use Rector\NodeTypeResolver\Contract\NodeTypeResolverInterface;
use Rector\NodeTypeResolver\PHPStan\Scope\Contract\NodeVisitor\ScopeResolverNodeVisitorInterface;
use Rector\PhpAttribute\Contract\AnnotationToAttributeMapperInterface;
use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface;
use Rector\StaticTypeMapper\Contract\PhpDocParser\PhpDocTypeMapperInterface;
use Rector\StaticTypeMapper\Contract\PhpParser\PhpParserNodeMapperInterface;
@ -31,7 +32,7 @@ final class ContainerBuilderFactory
/**
* @var array<class-string>
*/
private const TYPES_TO_TAG_AUTOCONFIGURE = [BasePhpDocNodeVisitorInterface::class, PhpDocNodeDecoratorInterface::class, NodeTypeResolverInterface::class, ScopeResolverNodeVisitorInterface::class, TypeMapperInterface::class, PhpParserNodeMapperInterface::class, PhpDocTypeMapperInterface::class, ClassNameImportSkipVoterInterface::class, RectorInterface::class, RectorInterface::class, OutputFormatterInterface::class, NonPhpRectorInterface::class, PhpRectorInterface::class, NodeNameResolverInterface::class, FileProcessorInterface::class];
private const TYPES_TO_TAG_AUTOCONFIGURE = [BasePhpDocNodeVisitorInterface::class, PhpDocNodeDecoratorInterface::class, NodeTypeResolverInterface::class, ScopeResolverNodeVisitorInterface::class, TypeMapperInterface::class, PhpParserNodeMapperInterface::class, PhpDocTypeMapperInterface::class, ClassNameImportSkipVoterInterface::class, RectorInterface::class, RectorInterface::class, OutputFormatterInterface::class, NonPhpRectorInterface::class, PhpRectorInterface::class, NodeNameResolverInterface::class, FileProcessorInterface::class, AnnotationToAttributeMapperInterface::class];
public function __construct(ConfigureCallMergingLoaderFactory $configureCallMergingLoaderFactory)
{
$this->configureCallMergingLoaderFactory = $configureCallMergingLoaderFactory;

View File

@ -15,7 +15,7 @@ final class RectorKernel
/**
* @var string
*/
private const CACHE_KEY = 'v107';
private const CACHE_KEY = 'v109';
/**
* @var \Symfony\Component\DependencyInjection\ContainerInterface|null
*/

View File

@ -1,79 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\Core\NodeManipulator;
use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Stmt\ClassMethod;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\Defluent\NodeAnalyzer\FluentChainMethodCallNodeAnalyzer;
use Rector\NodeNameResolver\NodeNameResolver;
final class MethodCallManipulator
{
/**
* @readonly
* @var \Rector\Core\PhpParser\Node\BetterNodeFinder
*/
private $betterNodeFinder;
/**
* @readonly
* @var \Rector\NodeNameResolver\NodeNameResolver
*/
private $nodeNameResolver;
/**
* @readonly
* @var \Rector\Defluent\NodeAnalyzer\FluentChainMethodCallNodeAnalyzer
*/
private $fluentChainMethodCallNodeAnalyzer;
public function __construct(BetterNodeFinder $betterNodeFinder, NodeNameResolver $nodeNameResolver, FluentChainMethodCallNodeAnalyzer $fluentChainMethodCallNodeAnalyzer)
{
$this->betterNodeFinder = $betterNodeFinder;
$this->nodeNameResolver = $nodeNameResolver;
$this->fluentChainMethodCallNodeAnalyzer = $fluentChainMethodCallNodeAnalyzer;
}
/**
* @api
* @return string[]
*/
public function findMethodCallNamesOnVariable(Variable $variable) : array
{
$methodCallsOnVariable = $this->findMethodCallsOnVariable($variable);
$methodCallNamesOnVariable = [];
foreach ($methodCallsOnVariable as $methodCallOnVariable) {
$methodName = $this->nodeNameResolver->getName($methodCallOnVariable->name);
if ($methodName === null) {
continue;
}
$methodCallNamesOnVariable[] = $methodName;
}
return \array_unique($methodCallNamesOnVariable);
}
/**
* @return MethodCall[]
*/
private function findMethodCallsOnVariable(Variable $variable) : array
{
// get scope node, e.g. parent function call, method call or anonymous function
$classMethod = $this->betterNodeFinder->findParentType($variable, ClassMethod::class);
if (!$classMethod instanceof ClassMethod) {
return [];
}
$variableName = $this->nodeNameResolver->getName($variable);
if ($variableName === null) {
return [];
}
return $this->betterNodeFinder->find((array) $classMethod->stmts, function (Node $node) use($variableName) : bool {
if (!$node instanceof MethodCall) {
return \false;
}
// cover fluent interfaces too
$callerNode = $this->fluentChainMethodCallNodeAnalyzer->resolveRootExpr($node);
if (!$callerNode instanceof Variable) {
return \false;
}
return $this->nodeNameResolver->isName($callerNode, $variableName);
});
}
}

2
vendor/autoload.php vendored
View File

@ -22,4 +22,4 @@ if (PHP_VERSION_ID < 50600) {
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit28417dad196a8217aba102ccaeda9de9::getLoader();
return ComposerAutoloaderInit3fab6f3576c517f4a735d8e59230bb55::getLoader();

View File

@ -1607,7 +1607,6 @@ return array(
'Rector\\Core\\NodeManipulator\\FuncCallManipulator' => $baseDir . '/src/NodeManipulator/FuncCallManipulator.php',
'Rector\\Core\\NodeManipulator\\FunctionLikeManipulator' => $baseDir . '/src/NodeManipulator/FunctionLikeManipulator.php',
'Rector\\Core\\NodeManipulator\\IfManipulator' => $baseDir . '/src/NodeManipulator/IfManipulator.php',
'Rector\\Core\\NodeManipulator\\MethodCallManipulator' => $baseDir . '/src/NodeManipulator/MethodCallManipulator.php',
'Rector\\Core\\NodeManipulator\\PropertyFetchAssignManipulator' => $baseDir . '/src/NodeManipulator/PropertyFetchAssignManipulator.php',
'Rector\\Core\\NodeManipulator\\PropertyManipulator' => $baseDir . '/src/NodeManipulator/PropertyManipulator.php',
'Rector\\Core\\NodeManipulator\\StmtsManipulator' => $baseDir . '/src/NodeManipulator/StmtsManipulator.php',
@ -1745,7 +1744,6 @@ return array(
'Rector\\DeadCode\\ValueObject\\BinaryToVersionCompareCondition' => $baseDir . '/rules/DeadCode/ValueObject/BinaryToVersionCompareCondition.php',
'Rector\\DeadCode\\ValueObject\\VariableAndPropertyFetchAssign' => $baseDir . '/rules/DeadCode/ValueObject/VariableAndPropertyFetchAssign.php',
'Rector\\DeadCode\\ValueObject\\VersionCompareCondition' => $baseDir . '/rules/DeadCode/ValueObject/VersionCompareCondition.php',
'Rector\\Defluent\\NodeAnalyzer\\FluentChainMethodCallNodeAnalyzer' => $baseDir . '/packages/Defluent/NodeAnalyzer/FluentChainMethodCallNodeAnalyzer.php',
'Rector\\DependencyInjection\\Rector\\ClassMethod\\AddMethodParentCallRector' => $baseDir . '/rules/DependencyInjection/Rector/ClassMethod/AddMethodParentCallRector.php',
'Rector\\Doctrine\\NodeAnalyzer\\AssignPropertyFetchAnalyzer' => $vendorDir . '/rector/rector-doctrine/src/NodeAnalyzer/AssignPropertyFetchAnalyzer.php',
'Rector\\Doctrine\\NodeAnalyzer\\AttributeCleaner' => $vendorDir . '/rector/rector-doctrine/src/NodeAnalyzer/AttributeCleaner.php',
@ -1809,26 +1807,6 @@ return array(
'Rector\\Doctrine\\ValueObject\\ArgName' => $vendorDir . '/rector/rector-doctrine/src/ValueObject/ArgName.php',
'Rector\\Doctrine\\ValueObject\\AssignToPropertyFetch' => $vendorDir . '/rector/rector-doctrine/src/ValueObject/AssignToPropertyFetch.php',
'Rector\\Doctrine\\ValueObject\\DefaultAnnotationArgValue' => $vendorDir . '/rector/rector-doctrine/src/ValueObject/DefaultAnnotationArgValue.php',
'Rector\\DowngradePhp70\\NodeFactory\\ClassFromAnonymousFactory' => $vendorDir . '/rector/rector-downgrade-php/rules/DowngradePhp70/NodeFactory/ClassFromAnonymousFactory.php',
'Rector\\DowngradePhp70\\Rector\\ClassMethod\\DowngradeParentTypeDeclarationRector' => $vendorDir . '/rector/rector-downgrade-php/rules/DowngradePhp70/Rector/ClassMethod/DowngradeParentTypeDeclarationRector.php',
'Rector\\DowngradePhp70\\Rector\\ClassMethod\\DowngradeSelfTypeDeclarationRector' => $vendorDir . '/rector/rector-downgrade-php/rules/DowngradePhp70/Rector/ClassMethod/DowngradeSelfTypeDeclarationRector.php',
'Rector\\DowngradePhp70\\Rector\\Coalesce\\DowngradeNullCoalesceRector' => $vendorDir . '/rector/rector-downgrade-php/rules/DowngradePhp70/Rector/Coalesce/DowngradeNullCoalesceRector.php',
'Rector\\DowngradePhp70\\Rector\\Declare_\\DowngradeStrictTypeDeclarationRector' => $vendorDir . '/rector/rector-downgrade-php/rules/DowngradePhp70/Rector/Declare_/DowngradeStrictTypeDeclarationRector.php',
'Rector\\DowngradePhp70\\Rector\\Expr\\DowngradeUnnecessarilyParenthesizedExpressionRector' => $vendorDir . '/rector/rector-downgrade-php/rules/DowngradePhp70/Rector/Expr/DowngradeUnnecessarilyParenthesizedExpressionRector.php',
'Rector\\DowngradePhp70\\Rector\\Expression\\DowngradeDefineArrayConstantRector' => $vendorDir . '/rector/rector-downgrade-php/rules/DowngradePhp70/Rector/Expression/DowngradeDefineArrayConstantRector.php',
'Rector\\DowngradePhp70\\Rector\\FuncCall\\DowngradeDirnameLevelsRector' => $vendorDir . '/rector/rector-downgrade-php/rules/DowngradePhp70/Rector/FuncCall/DowngradeDirnameLevelsRector.php',
'Rector\\DowngradePhp70\\Rector\\FuncCall\\DowngradeSessionStartArrayOptionsRector' => $vendorDir . '/rector/rector-downgrade-php/rules/DowngradePhp70/Rector/FuncCall/DowngradeSessionStartArrayOptionsRector.php',
'Rector\\DowngradePhp70\\Rector\\FuncCall\\DowngradeUncallableValueCallToCallUserFuncRector' => $vendorDir . '/rector/rector-downgrade-php/rules/DowngradePhp70/Rector/FuncCall/DowngradeUncallableValueCallToCallUserFuncRector.php',
'Rector\\DowngradePhp70\\Rector\\FunctionLike\\DowngradeScalarTypeDeclarationRector' => $vendorDir . '/rector/rector-downgrade-php/rules/DowngradePhp70/Rector/FunctionLike/DowngradeScalarTypeDeclarationRector.php',
'Rector\\DowngradePhp70\\Rector\\FunctionLike\\DowngradeThrowableTypeDeclarationRector' => $vendorDir . '/rector/rector-downgrade-php/rules/DowngradePhp70/Rector/FunctionLike/DowngradeThrowableTypeDeclarationRector.php',
'Rector\\DowngradePhp70\\Rector\\GroupUse\\SplitGroupedUseImportsRector' => $vendorDir . '/rector/rector-downgrade-php/rules/DowngradePhp70/Rector/GroupUse/SplitGroupedUseImportsRector.php',
'Rector\\DowngradePhp70\\Rector\\Instanceof_\\DowngradeInstanceofThrowableRector' => $vendorDir . '/rector/rector-downgrade-php/rules/DowngradePhp70/Rector/Instanceof_/DowngradeInstanceofThrowableRector.php',
'Rector\\DowngradePhp70\\Rector\\MethodCall\\DowngradeClosureCallRector' => $vendorDir . '/rector/rector-downgrade-php/rules/DowngradePhp70/Rector/MethodCall/DowngradeClosureCallRector.php',
'Rector\\DowngradePhp70\\Rector\\MethodCall\\DowngradeMethodCallOnCloneRector' => $vendorDir . '/rector/rector-downgrade-php/rules/DowngradePhp70/Rector/MethodCall/DowngradeMethodCallOnCloneRector.php',
'Rector\\DowngradePhp70\\Rector\\New_\\DowngradeAnonymousClassRector' => $vendorDir . '/rector/rector-downgrade-php/rules/DowngradePhp70/Rector/New_/DowngradeAnonymousClassRector.php',
'Rector\\DowngradePhp70\\Rector\\Spaceship\\DowngradeSpaceshipRector' => $vendorDir . '/rector/rector-downgrade-php/rules/DowngradePhp70/Rector/Spaceship/DowngradeSpaceshipRector.php',
'Rector\\DowngradePhp70\\Rector\\TryCatch\\DowngradeCatchThrowableRector' => $vendorDir . '/rector/rector-downgrade-php/rules/DowngradePhp70/Rector/TryCatch/DowngradeCatchThrowableRector.php',
'Rector\\DowngradePhp70\\Tokenizer\\WrappedInParenthesesAnalyzer' => $vendorDir . '/rector/rector-downgrade-php/rules/DowngradePhp70/Tokenizer/WrappedInParenthesesAnalyzer.php',
'Rector\\DowngradePhp71\\Rector\\Array_\\SymmetricArrayDestructuringToListRector' => $vendorDir . '/rector/rector-downgrade-php/rules/DowngradePhp71/Rector/Array_/SymmetricArrayDestructuringToListRector.php',
'Rector\\DowngradePhp71\\Rector\\ClassConst\\DowngradeClassConstantVisibilityRector' => $vendorDir . '/rector/rector-downgrade-php/rules/DowngradePhp71/Rector/ClassConst/DowngradeClassConstantVisibilityRector.php',
'Rector\\DowngradePhp71\\Rector\\ConstFetch\\DowngradePhp71JsonConstRector' => $vendorDir . '/rector/rector-downgrade-php/rules/DowngradePhp71/Rector/ConstFetch/DowngradePhp71JsonConstRector.php',
@ -1999,7 +1977,6 @@ return array(
'Rector\\NodeAnalyzer\\CoalesceAnalyzer' => $vendorDir . '/rector/rector-downgrade-php/src/NodeAnalyzer/CoalesceAnalyzer.php',
'Rector\\NodeAnalyzer\\DefineFuncCallAnalyzer' => $vendorDir . '/rector/rector-downgrade-php/src/NodeAnalyzer/DefineFuncCallAnalyzer.php',
'Rector\\NodeAnalyzer\\ExprInTopStmtMatcher' => $vendorDir . '/rector/rector-downgrade-php/src/NodeAnalyzer/ExprInTopStmtMatcher.php',
'Rector\\NodeAnalyzer\\MethodCallTypeAnalyzer' => $vendorDir . '/rector/rector-downgrade-php/src/NodeAnalyzer/MethodCallTypeAnalyzer.php',
'Rector\\NodeCollector\\BinaryOpConditionsCollector' => $baseDir . '/packages/NodeCollector/BinaryOpConditionsCollector.php',
'Rector\\NodeCollector\\NodeAnalyzer\\ArrayCallableMethodMatcher' => $baseDir . '/packages/NodeCollector/NodeAnalyzer/ArrayCallableMethodMatcher.php',
'Rector\\NodeCollector\\ScopeResolver\\ParentClassScopeResolver' => $baseDir . '/packages/NodeCollector/ScopeResolver/ParentClassScopeResolver.php',
@ -2009,7 +1986,6 @@ return array(
'Rector\\NodeFactory\\ClassFromEnumFactory' => $vendorDir . '/rector/rector-downgrade-php/src/NodeFactory/ClassFromEnumFactory.php',
'Rector\\NodeFactory\\DoctrineAnnotationFactory' => $vendorDir . '/rector/rector-downgrade-php/src/NodeFactory/DoctrineAnnotationFactory.php',
'Rector\\NodeFactory\\NamedVariableFactory' => $vendorDir . '/rector/rector-downgrade-php/src/NodeFactory/NamedVariableFactory.php',
'Rector\\NodeManipulator\\NamespacedNameDecorator' => $vendorDir . '/rector/rector-downgrade-php/src/NodeManipulator/NamespacedNameDecorator.php',
'Rector\\NodeManipulator\\PropertyDecorator' => $vendorDir . '/rector/rector-downgrade-php/src/NodeManipulator/PropertyDecorator.php',
'Rector\\NodeNameResolver\\Contract\\NodeNameResolverInterface' => $baseDir . '/packages/NodeNameResolver/Contract/NodeNameResolverInterface.php',
'Rector\\NodeNameResolver\\NodeNameResolver' => $baseDir . '/packages/NodeNameResolver/NodeNameResolver.php',
@ -2302,7 +2278,6 @@ return array(
'Rector\\Php74\\Rector\\Ternary\\ParenthesizeNestedTernaryRector' => $baseDir . '/rules/Php74/Rector/Ternary/ParenthesizeNestedTernaryRector.php',
'Rector\\Php74\\Tokenizer\\ParenthesizedNestedTernaryAnalyzer' => $baseDir . '/rules/Php74/Tokenizer/ParenthesizedNestedTernaryAnalyzer.php',
'Rector\\Php80\\AttributeDecorator\\SensioParamConverterAttributeDecorator' => $baseDir . '/rules/Php80/AttributeDecorator/SensioParamConverterAttributeDecorator.php',
'Rector\\Php80\\Contract\\AttributeDecoratorInterface' => $baseDir . '/rules/Php80/Contract/AttributeDecoratorInterface.php',
'Rector\\Php80\\Contract\\StrStartWithMatchAndRefactorInterface' => $baseDir . '/rules/Php80/Contract/StrStartWithMatchAndRefactorInterface.php',
'Rector\\Php80\\Contract\\ValueObject\\AnnotationToAttributeInterface' => $baseDir . '/rules/Php80/Contract/ValueObject/AnnotationToAttributeInterface.php',
'Rector\\Php80\\Enum\\MatchKind' => $baseDir . '/rules/Php80/Enum/MatchKind.php',

View File

@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit28417dad196a8217aba102ccaeda9de9
class ComposerAutoloaderInit3fab6f3576c517f4a735d8e59230bb55
{
private static $loader;
@ -22,17 +22,17 @@ class ComposerAutoloaderInit28417dad196a8217aba102ccaeda9de9
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInit28417dad196a8217aba102ccaeda9de9', 'loadClassLoader'), true, true);
spl_autoload_register(array('ComposerAutoloaderInit3fab6f3576c517f4a735d8e59230bb55', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
spl_autoload_unregister(array('ComposerAutoloaderInit28417dad196a8217aba102ccaeda9de9', 'loadClassLoader'));
spl_autoload_unregister(array('ComposerAutoloaderInit3fab6f3576c517f4a735d8e59230bb55', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit28417dad196a8217aba102ccaeda9de9::getInitializer($loader));
call_user_func(\Composer\Autoload\ComposerStaticInit3fab6f3576c517f4a735d8e59230bb55::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
$filesToLoad = \Composer\Autoload\ComposerStaticInit28417dad196a8217aba102ccaeda9de9::$files;
$filesToLoad = \Composer\Autoload\ComposerStaticInit3fab6f3576c517f4a735d8e59230bb55::$files;
$requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;

View File

@ -4,7 +4,7 @@
namespace Composer\Autoload;
class ComposerStaticInit28417dad196a8217aba102ccaeda9de9
class ComposerStaticInit3fab6f3576c517f4a735d8e59230bb55
{
public static $files = array (
'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php',
@ -1858,7 +1858,6 @@ class ComposerStaticInit28417dad196a8217aba102ccaeda9de9
'Rector\\Core\\NodeManipulator\\FuncCallManipulator' => __DIR__ . '/../..' . '/src/NodeManipulator/FuncCallManipulator.php',
'Rector\\Core\\NodeManipulator\\FunctionLikeManipulator' => __DIR__ . '/../..' . '/src/NodeManipulator/FunctionLikeManipulator.php',
'Rector\\Core\\NodeManipulator\\IfManipulator' => __DIR__ . '/../..' . '/src/NodeManipulator/IfManipulator.php',
'Rector\\Core\\NodeManipulator\\MethodCallManipulator' => __DIR__ . '/../..' . '/src/NodeManipulator/MethodCallManipulator.php',
'Rector\\Core\\NodeManipulator\\PropertyFetchAssignManipulator' => __DIR__ . '/../..' . '/src/NodeManipulator/PropertyFetchAssignManipulator.php',
'Rector\\Core\\NodeManipulator\\PropertyManipulator' => __DIR__ . '/../..' . '/src/NodeManipulator/PropertyManipulator.php',
'Rector\\Core\\NodeManipulator\\StmtsManipulator' => __DIR__ . '/../..' . '/src/NodeManipulator/StmtsManipulator.php',
@ -1996,7 +1995,6 @@ class ComposerStaticInit28417dad196a8217aba102ccaeda9de9
'Rector\\DeadCode\\ValueObject\\BinaryToVersionCompareCondition' => __DIR__ . '/../..' . '/rules/DeadCode/ValueObject/BinaryToVersionCompareCondition.php',
'Rector\\DeadCode\\ValueObject\\VariableAndPropertyFetchAssign' => __DIR__ . '/../..' . '/rules/DeadCode/ValueObject/VariableAndPropertyFetchAssign.php',
'Rector\\DeadCode\\ValueObject\\VersionCompareCondition' => __DIR__ . '/../..' . '/rules/DeadCode/ValueObject/VersionCompareCondition.php',
'Rector\\Defluent\\NodeAnalyzer\\FluentChainMethodCallNodeAnalyzer' => __DIR__ . '/../..' . '/packages/Defluent/NodeAnalyzer/FluentChainMethodCallNodeAnalyzer.php',
'Rector\\DependencyInjection\\Rector\\ClassMethod\\AddMethodParentCallRector' => __DIR__ . '/../..' . '/rules/DependencyInjection/Rector/ClassMethod/AddMethodParentCallRector.php',
'Rector\\Doctrine\\NodeAnalyzer\\AssignPropertyFetchAnalyzer' => __DIR__ . '/..' . '/rector/rector-doctrine/src/NodeAnalyzer/AssignPropertyFetchAnalyzer.php',
'Rector\\Doctrine\\NodeAnalyzer\\AttributeCleaner' => __DIR__ . '/..' . '/rector/rector-doctrine/src/NodeAnalyzer/AttributeCleaner.php',
@ -2060,26 +2058,6 @@ class ComposerStaticInit28417dad196a8217aba102ccaeda9de9
'Rector\\Doctrine\\ValueObject\\ArgName' => __DIR__ . '/..' . '/rector/rector-doctrine/src/ValueObject/ArgName.php',
'Rector\\Doctrine\\ValueObject\\AssignToPropertyFetch' => __DIR__ . '/..' . '/rector/rector-doctrine/src/ValueObject/AssignToPropertyFetch.php',
'Rector\\Doctrine\\ValueObject\\DefaultAnnotationArgValue' => __DIR__ . '/..' . '/rector/rector-doctrine/src/ValueObject/DefaultAnnotationArgValue.php',
'Rector\\DowngradePhp70\\NodeFactory\\ClassFromAnonymousFactory' => __DIR__ . '/..' . '/rector/rector-downgrade-php/rules/DowngradePhp70/NodeFactory/ClassFromAnonymousFactory.php',
'Rector\\DowngradePhp70\\Rector\\ClassMethod\\DowngradeParentTypeDeclarationRector' => __DIR__ . '/..' . '/rector/rector-downgrade-php/rules/DowngradePhp70/Rector/ClassMethod/DowngradeParentTypeDeclarationRector.php',
'Rector\\DowngradePhp70\\Rector\\ClassMethod\\DowngradeSelfTypeDeclarationRector' => __DIR__ . '/..' . '/rector/rector-downgrade-php/rules/DowngradePhp70/Rector/ClassMethod/DowngradeSelfTypeDeclarationRector.php',
'Rector\\DowngradePhp70\\Rector\\Coalesce\\DowngradeNullCoalesceRector' => __DIR__ . '/..' . '/rector/rector-downgrade-php/rules/DowngradePhp70/Rector/Coalesce/DowngradeNullCoalesceRector.php',
'Rector\\DowngradePhp70\\Rector\\Declare_\\DowngradeStrictTypeDeclarationRector' => __DIR__ . '/..' . '/rector/rector-downgrade-php/rules/DowngradePhp70/Rector/Declare_/DowngradeStrictTypeDeclarationRector.php',
'Rector\\DowngradePhp70\\Rector\\Expr\\DowngradeUnnecessarilyParenthesizedExpressionRector' => __DIR__ . '/..' . '/rector/rector-downgrade-php/rules/DowngradePhp70/Rector/Expr/DowngradeUnnecessarilyParenthesizedExpressionRector.php',
'Rector\\DowngradePhp70\\Rector\\Expression\\DowngradeDefineArrayConstantRector' => __DIR__ . '/..' . '/rector/rector-downgrade-php/rules/DowngradePhp70/Rector/Expression/DowngradeDefineArrayConstantRector.php',
'Rector\\DowngradePhp70\\Rector\\FuncCall\\DowngradeDirnameLevelsRector' => __DIR__ . '/..' . '/rector/rector-downgrade-php/rules/DowngradePhp70/Rector/FuncCall/DowngradeDirnameLevelsRector.php',
'Rector\\DowngradePhp70\\Rector\\FuncCall\\DowngradeSessionStartArrayOptionsRector' => __DIR__ . '/..' . '/rector/rector-downgrade-php/rules/DowngradePhp70/Rector/FuncCall/DowngradeSessionStartArrayOptionsRector.php',
'Rector\\DowngradePhp70\\Rector\\FuncCall\\DowngradeUncallableValueCallToCallUserFuncRector' => __DIR__ . '/..' . '/rector/rector-downgrade-php/rules/DowngradePhp70/Rector/FuncCall/DowngradeUncallableValueCallToCallUserFuncRector.php',
'Rector\\DowngradePhp70\\Rector\\FunctionLike\\DowngradeScalarTypeDeclarationRector' => __DIR__ . '/..' . '/rector/rector-downgrade-php/rules/DowngradePhp70/Rector/FunctionLike/DowngradeScalarTypeDeclarationRector.php',
'Rector\\DowngradePhp70\\Rector\\FunctionLike\\DowngradeThrowableTypeDeclarationRector' => __DIR__ . '/..' . '/rector/rector-downgrade-php/rules/DowngradePhp70/Rector/FunctionLike/DowngradeThrowableTypeDeclarationRector.php',
'Rector\\DowngradePhp70\\Rector\\GroupUse\\SplitGroupedUseImportsRector' => __DIR__ . '/..' . '/rector/rector-downgrade-php/rules/DowngradePhp70/Rector/GroupUse/SplitGroupedUseImportsRector.php',
'Rector\\DowngradePhp70\\Rector\\Instanceof_\\DowngradeInstanceofThrowableRector' => __DIR__ . '/..' . '/rector/rector-downgrade-php/rules/DowngradePhp70/Rector/Instanceof_/DowngradeInstanceofThrowableRector.php',
'Rector\\DowngradePhp70\\Rector\\MethodCall\\DowngradeClosureCallRector' => __DIR__ . '/..' . '/rector/rector-downgrade-php/rules/DowngradePhp70/Rector/MethodCall/DowngradeClosureCallRector.php',
'Rector\\DowngradePhp70\\Rector\\MethodCall\\DowngradeMethodCallOnCloneRector' => __DIR__ . '/..' . '/rector/rector-downgrade-php/rules/DowngradePhp70/Rector/MethodCall/DowngradeMethodCallOnCloneRector.php',
'Rector\\DowngradePhp70\\Rector\\New_\\DowngradeAnonymousClassRector' => __DIR__ . '/..' . '/rector/rector-downgrade-php/rules/DowngradePhp70/Rector/New_/DowngradeAnonymousClassRector.php',
'Rector\\DowngradePhp70\\Rector\\Spaceship\\DowngradeSpaceshipRector' => __DIR__ . '/..' . '/rector/rector-downgrade-php/rules/DowngradePhp70/Rector/Spaceship/DowngradeSpaceshipRector.php',
'Rector\\DowngradePhp70\\Rector\\TryCatch\\DowngradeCatchThrowableRector' => __DIR__ . '/..' . '/rector/rector-downgrade-php/rules/DowngradePhp70/Rector/TryCatch/DowngradeCatchThrowableRector.php',
'Rector\\DowngradePhp70\\Tokenizer\\WrappedInParenthesesAnalyzer' => __DIR__ . '/..' . '/rector/rector-downgrade-php/rules/DowngradePhp70/Tokenizer/WrappedInParenthesesAnalyzer.php',
'Rector\\DowngradePhp71\\Rector\\Array_\\SymmetricArrayDestructuringToListRector' => __DIR__ . '/..' . '/rector/rector-downgrade-php/rules/DowngradePhp71/Rector/Array_/SymmetricArrayDestructuringToListRector.php',
'Rector\\DowngradePhp71\\Rector\\ClassConst\\DowngradeClassConstantVisibilityRector' => __DIR__ . '/..' . '/rector/rector-downgrade-php/rules/DowngradePhp71/Rector/ClassConst/DowngradeClassConstantVisibilityRector.php',
'Rector\\DowngradePhp71\\Rector\\ConstFetch\\DowngradePhp71JsonConstRector' => __DIR__ . '/..' . '/rector/rector-downgrade-php/rules/DowngradePhp71/Rector/ConstFetch/DowngradePhp71JsonConstRector.php',
@ -2250,7 +2228,6 @@ class ComposerStaticInit28417dad196a8217aba102ccaeda9de9
'Rector\\NodeAnalyzer\\CoalesceAnalyzer' => __DIR__ . '/..' . '/rector/rector-downgrade-php/src/NodeAnalyzer/CoalesceAnalyzer.php',
'Rector\\NodeAnalyzer\\DefineFuncCallAnalyzer' => __DIR__ . '/..' . '/rector/rector-downgrade-php/src/NodeAnalyzer/DefineFuncCallAnalyzer.php',
'Rector\\NodeAnalyzer\\ExprInTopStmtMatcher' => __DIR__ . '/..' . '/rector/rector-downgrade-php/src/NodeAnalyzer/ExprInTopStmtMatcher.php',
'Rector\\NodeAnalyzer\\MethodCallTypeAnalyzer' => __DIR__ . '/..' . '/rector/rector-downgrade-php/src/NodeAnalyzer/MethodCallTypeAnalyzer.php',
'Rector\\NodeCollector\\BinaryOpConditionsCollector' => __DIR__ . '/../..' . '/packages/NodeCollector/BinaryOpConditionsCollector.php',
'Rector\\NodeCollector\\NodeAnalyzer\\ArrayCallableMethodMatcher' => __DIR__ . '/../..' . '/packages/NodeCollector/NodeAnalyzer/ArrayCallableMethodMatcher.php',
'Rector\\NodeCollector\\ScopeResolver\\ParentClassScopeResolver' => __DIR__ . '/../..' . '/packages/NodeCollector/ScopeResolver/ParentClassScopeResolver.php',
@ -2260,7 +2237,6 @@ class ComposerStaticInit28417dad196a8217aba102ccaeda9de9
'Rector\\NodeFactory\\ClassFromEnumFactory' => __DIR__ . '/..' . '/rector/rector-downgrade-php/src/NodeFactory/ClassFromEnumFactory.php',
'Rector\\NodeFactory\\DoctrineAnnotationFactory' => __DIR__ . '/..' . '/rector/rector-downgrade-php/src/NodeFactory/DoctrineAnnotationFactory.php',
'Rector\\NodeFactory\\NamedVariableFactory' => __DIR__ . '/..' . '/rector/rector-downgrade-php/src/NodeFactory/NamedVariableFactory.php',
'Rector\\NodeManipulator\\NamespacedNameDecorator' => __DIR__ . '/..' . '/rector/rector-downgrade-php/src/NodeManipulator/NamespacedNameDecorator.php',
'Rector\\NodeManipulator\\PropertyDecorator' => __DIR__ . '/..' . '/rector/rector-downgrade-php/src/NodeManipulator/PropertyDecorator.php',
'Rector\\NodeNameResolver\\Contract\\NodeNameResolverInterface' => __DIR__ . '/../..' . '/packages/NodeNameResolver/Contract/NodeNameResolverInterface.php',
'Rector\\NodeNameResolver\\NodeNameResolver' => __DIR__ . '/../..' . '/packages/NodeNameResolver/NodeNameResolver.php',
@ -2553,7 +2529,6 @@ class ComposerStaticInit28417dad196a8217aba102ccaeda9de9
'Rector\\Php74\\Rector\\Ternary\\ParenthesizeNestedTernaryRector' => __DIR__ . '/../..' . '/rules/Php74/Rector/Ternary/ParenthesizeNestedTernaryRector.php',
'Rector\\Php74\\Tokenizer\\ParenthesizedNestedTernaryAnalyzer' => __DIR__ . '/../..' . '/rules/Php74/Tokenizer/ParenthesizedNestedTernaryAnalyzer.php',
'Rector\\Php80\\AttributeDecorator\\SensioParamConverterAttributeDecorator' => __DIR__ . '/../..' . '/rules/Php80/AttributeDecorator/SensioParamConverterAttributeDecorator.php',
'Rector\\Php80\\Contract\\AttributeDecoratorInterface' => __DIR__ . '/../..' . '/rules/Php80/Contract/AttributeDecoratorInterface.php',
'Rector\\Php80\\Contract\\StrStartWithMatchAndRefactorInterface' => __DIR__ . '/../..' . '/rules/Php80/Contract/StrStartWithMatchAndRefactorInterface.php',
'Rector\\Php80\\Contract\\ValueObject\\AnnotationToAttributeInterface' => __DIR__ . '/../..' . '/rules/Php80/Contract/ValueObject/AnnotationToAttributeInterface.php',
'Rector\\Php80\\Enum\\MatchKind' => __DIR__ . '/../..' . '/rules/Php80/Enum/MatchKind.php',
@ -3122,9 +3097,9 @@ class ComposerStaticInit28417dad196a8217aba102ccaeda9de9
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInit28417dad196a8217aba102ccaeda9de9::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit28417dad196a8217aba102ccaeda9de9::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit28417dad196a8217aba102ccaeda9de9::$classMap;
$loader->prefixLengthsPsr4 = ComposerStaticInit3fab6f3576c517f4a735d8e59230bb55::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit3fab6f3576c517f4a735d8e59230bb55::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit3fab6f3576c517f4a735d8e59230bb55::$classMap;
}, null, ClassLoader::class);
}

View File

@ -1921,12 +1921,12 @@
"source": {
"type": "git",
"url": "https:\/\/github.com\/rectorphp\/rector-doctrine.git",
"reference": "ca0179995eceabd2acae03c60665bc73494c36ec"
"reference": "9f8970b4078cc5a02daefa963c008463e29e81c7"
},
"dist": {
"type": "zip",
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-doctrine\/zipball\/ca0179995eceabd2acae03c60665bc73494c36ec",
"reference": "ca0179995eceabd2acae03c60665bc73494c36ec",
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-doctrine\/zipball\/9f8970b4078cc5a02daefa963c008463e29e81c7",
"reference": "9f8970b4078cc5a02daefa963c008463e29e81c7",
"shasum": ""
},
"require": {
@ -1951,7 +1951,7 @@
"tomasvotruba\/type-coverage": "^0.2",
"tomasvotruba\/unused-public": "^0.1"
},
"time": "2023-06-09T10:43:45+00:00",
"time": "2023-06-12T10:31:32+00:00",
"default-branch": true,
"type": "rector-extension",
"extra": {
@ -1986,12 +1986,12 @@
"source": {
"type": "git",
"url": "https:\/\/github.com\/rectorphp\/rector-downgrade-php.git",
"reference": "5d564602660473dc188850f1f7e5f84ec601c2c1"
"reference": "3a12c7f7b063aef7ff914dc4728f7e0e8920230a"
},
"dist": {
"type": "zip",
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-downgrade-php\/zipball\/5d564602660473dc188850f1f7e5f84ec601c2c1",
"reference": "5d564602660473dc188850f1f7e5f84ec601c2c1",
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-downgrade-php\/zipball\/3a12c7f7b063aef7ff914dc4728f7e0e8920230a",
"reference": "3a12c7f7b063aef7ff914dc4728f7e0e8920230a",
"shasum": ""
},
"require": {
@ -2015,7 +2015,7 @@
"tomasvotruba\/type-coverage": "^0.2",
"tomasvotruba\/unused-public": "^0.1"
},
"time": "2023-06-11T23:30:01+00:00",
"time": "2023-06-12T10:30:38+00:00",
"default-branch": true,
"type": "rector-extension",
"extra": {
@ -2125,12 +2125,12 @@
"source": {
"type": "git",
"url": "https:\/\/github.com\/rectorphp\/rector-symfony.git",
"reference": "6379aab278a0879a2eeedb27ea8ee1a99875ae4b"
"reference": "9d59fcc509159fdeca278c06df6d56891e71ef70"
},
"dist": {
"type": "zip",
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-symfony\/zipball\/6379aab278a0879a2eeedb27ea8ee1a99875ae4b",
"reference": "6379aab278a0879a2eeedb27ea8ee1a99875ae4b",
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-symfony\/zipball\/9d59fcc509159fdeca278c06df6d56891e71ef70",
"reference": "9d59fcc509159fdeca278c06df6d56891e71ef70",
"shasum": ""
},
"require": {
@ -2160,7 +2160,7 @@
"tomasvotruba\/type-coverage": "^0.2",
"tomasvotruba\/unused-public": "^0.1"
},
"time": "2023-06-12T10:03:47+00:00",
"time": "2023-06-12T10:36:57+00:00",
"default-branch": true,
"type": "rector-extension",
"extra": {

File diff suppressed because one or more lines are too long

View File

@ -9,7 +9,7 @@ namespace Rector\RectorInstaller;
*/
final class GeneratedConfig
{
public const EXTENSIONS = array('rector/rector-doctrine' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-doctrine', 'relative_install_path' => '../../rector-doctrine', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main ca01799'), 'rector/rector-downgrade-php' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-downgrade-php', 'relative_install_path' => '../../rector-downgrade-php', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 5d56460'), 'rector/rector-phpunit' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-phpunit', 'relative_install_path' => '../../rector-phpunit', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 8f78df1'), 'rector/rector-symfony' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-symfony', 'relative_install_path' => '../../rector-symfony', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 6379aab'));
public const EXTENSIONS = array('rector/rector-doctrine' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-doctrine', 'relative_install_path' => '../../rector-doctrine', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 9f8970b'), 'rector/rector-downgrade-php' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-downgrade-php', 'relative_install_path' => '../../rector-downgrade-php', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 3a12c7f'), 'rector/rector-phpunit' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-phpunit', 'relative_install_path' => '../../rector-phpunit', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 8f78df1'), 'rector/rector-symfony' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-symfony', 'relative_install_path' => '../../rector-symfony', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 9d59fcc'));
private function __construct()
{
}

View File

@ -101,7 +101,7 @@ Change CompositeExpression ->addMultiple($parts) to ->with(...$parts)
## ChangeSetParametersArrayToArrayCollectionRector
Change array to ArrayCollection in setParameters method of query builder
Change array to ArrayCollection in `setParameters()` method of query builder
- class: [`Rector\Doctrine\Rector\MethodCall\ChangeSetParametersArrayToArrayCollectionRector`](../src/Rector/MethodCall/ChangeSetParametersArrayToArrayCollectionRector.php)
@ -114,19 +114,15 @@ Change array to ArrayCollection in setParameters method of query builder
{
public function getSomething()
{
return $this
->createQueryBuilder('sm')
return $this->createQueryBuilder('sm')
->select('sm')
->where('sm.foo = :bar')
- ->setParameters([
- 'bar' => 'baz'
- ])
- ]);
+ ->setParameters(new ArrayCollection([
+ new Parameter('bar', 'baz'),
+ ]))
->getQuery()
->getResult()
;
+ ]));
}
}
```

View File

@ -11,11 +11,10 @@ use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Stmt\ClassLike;
use PhpParser\Node\Stmt\Class_;
use PHPStan\Type\ObjectType;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\Rector\AbstractRector;
use Rector\Defluent\NodeAnalyzer\FluentChainMethodCallNodeAnalyzer;
use Rector\NodeTypeResolver\TypeAnalyzer\ArrayTypeAnalyzer;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
@ -30,64 +29,69 @@ final class ChangeSetParametersArrayToArrayCollectionRector extends AbstractRect
* @var \Rector\NodeTypeResolver\TypeAnalyzer\ArrayTypeAnalyzer
*/
private $arrayTypeAnalyzer;
/**
* @readonly
* @var \Rector\Defluent\NodeAnalyzer\FluentChainMethodCallNodeAnalyzer
*/
private $fluentChainMethodCallNodeAnalyzer;
public function __construct(ArrayTypeAnalyzer $arrayTypeAnalyzer, FluentChainMethodCallNodeAnalyzer $fluentChainMethodCallNodeAnalyzer)
public function __construct(ArrayTypeAnalyzer $arrayTypeAnalyzer)
{
$this->arrayTypeAnalyzer = $arrayTypeAnalyzer;
$this->fluentChainMethodCallNodeAnalyzer = $fluentChainMethodCallNodeAnalyzer;
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes() : array
{
return [MethodCall::class];
return [Class_::class];
}
/**
* @param MethodCall $node
* @param Class_ $node
*/
public function refactor(Node $node) : ?Node
{
if ($this->shouldSkipMethodCall($node)) {
// one of the cases when we are in the repo and it's extended from EntityRepository
if (!$this->isObjectType($node, new ObjectType('Doctrine\\ORM\\EntityRepository'))) {
return null;
}
/** @var Arg[] $methodArguments */
$methodArguments = $node->args;
if (\count($methodArguments) !== 1) {
return null;
$hasChanged = \false;
$this->traverseNodesWithCallable($node->getMethods(), function (Node $node) use(&$hasChanged) : ?MethodCall {
if (!$node instanceof MethodCall) {
return null;
}
if (!$this->isName($node->name, 'setParameters')) {
return null;
}
/** @var Arg[] $methodArguments */
$methodArguments = $node->args;
if (\count($methodArguments) !== 1) {
return null;
}
$firstArgument = $methodArguments[0];
if (!$this->arrayTypeAnalyzer->isArrayType($firstArgument->value)) {
return null;
}
unset($node->args);
$new = $this->getNewArrayCollectionFromSetParametersArgument($firstArgument);
$hasChanged = \true;
$node->args = [new Arg($new)];
return $node;
});
if ($hasChanged) {
return $node;
}
$firstArgument = $methodArguments[0];
if (!$this->arrayTypeAnalyzer->isArrayType($firstArgument->value)) {
return null;
}
unset($node->args);
$new = $this->getNewArrayCollectionFromSetParametersArgument($firstArgument);
$node->args = [new Arg($new)];
return $node;
return null;
}
public function getRuleDefinition() : RuleDefinition
{
return new RuleDefinition('Change array to ArrayCollection in setParameters method of query builder', [new CodeSample(<<<'CODE_SAMPLE'
return new RuleDefinition('Change array to ArrayCollection in setParameters() method of query builder', [new CodeSample(<<<'CODE_SAMPLE'
use Doctrine\ORM\EntityRepository;
class SomeRepository extends EntityRepository
{
public function getSomething()
{
return $this
->createQueryBuilder('sm')
return $this->createQueryBuilder('sm')
->select('sm')
->where('sm.foo = :bar')
->setParameters([
'bar' => 'baz'
])
->getQuery()
->getResult()
;
]);
}
}
CODE_SAMPLE
@ -100,41 +104,17 @@ class SomeRepository extends EntityRepository
{
public function getSomething()
{
return $this
->createQueryBuilder('sm')
return $this->createQueryBuilder('sm')
->select('sm')
->where('sm.foo = :bar')
->setParameters(new ArrayCollection([
new Parameter('bar', 'baz'),
]))
->getQuery()
->getResult()
;
]));
}
}
CODE_SAMPLE
)]);
}
private function shouldSkipMethodCall(MethodCall $methodCall) : bool
{
$classLike = $this->betterNodeFinder->findParentType($methodCall, ClassLike::class);
if (!$classLike instanceof ClassLike) {
return \true;
}
// one of the cases when we are in the repo and it's extended from EntityRepository
if (!$this->isObjectType($classLike, new ObjectType('Doctrine\\ORM\\EntityRepository'))) {
return \true;
}
if (!$this->isName($methodCall->name, 'setParameters')) {
return \true;
}
// compare root variable
$rootExpr = $this->fluentChainMethodCallNodeAnalyzer->resolveRootMethodCall($methodCall);
if (!$rootExpr instanceof MethodCall) {
return \true;
}
return !$this->isObjectType($rootExpr, new ObjectType('Doctrine\\ORM\\QueryBuilder'));
}
private function getNewArrayCollectionFromSetParametersArgument(Arg $arg) : New_
{
/** @var Array_ $arrayExpression */

View File

@ -1,46 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202306;
use Rector\Config\RectorConfig;
use Rector\Core\ValueObject\PhpVersion;
use Rector\DowngradePhp70\Rector\ClassMethod\DowngradeParentTypeDeclarationRector;
use Rector\DowngradePhp70\Rector\ClassMethod\DowngradeSelfTypeDeclarationRector;
use Rector\DowngradePhp70\Rector\Coalesce\DowngradeNullCoalesceRector;
use Rector\DowngradePhp70\Rector\Declare_\DowngradeStrictTypeDeclarationRector;
use Rector\DowngradePhp70\Rector\Expr\DowngradeUnnecessarilyParenthesizedExpressionRector;
use Rector\DowngradePhp70\Rector\Expression\DowngradeDefineArrayConstantRector;
use Rector\DowngradePhp70\Rector\FuncCall\DowngradeDirnameLevelsRector;
use Rector\DowngradePhp70\Rector\FuncCall\DowngradeSessionStartArrayOptionsRector;
use Rector\DowngradePhp70\Rector\FuncCall\DowngradeUncallableValueCallToCallUserFuncRector;
use Rector\DowngradePhp70\Rector\FunctionLike\DowngradeScalarTypeDeclarationRector;
use Rector\DowngradePhp70\Rector\FunctionLike\DowngradeThrowableTypeDeclarationRector;
use Rector\DowngradePhp70\Rector\GroupUse\SplitGroupedUseImportsRector;
use Rector\DowngradePhp70\Rector\Instanceof_\DowngradeInstanceofThrowableRector;
use Rector\DowngradePhp70\Rector\MethodCall\DowngradeClosureCallRector;
use Rector\DowngradePhp70\Rector\MethodCall\DowngradeMethodCallOnCloneRector;
use Rector\DowngradePhp70\Rector\New_\DowngradeAnonymousClassRector;
use Rector\DowngradePhp70\Rector\Spaceship\DowngradeSpaceshipRector;
use Rector\DowngradePhp70\Rector\TryCatch\DowngradeCatchThrowableRector;
return static function (RectorConfig $rectorConfig) : void {
$rectorConfig->phpVersion(PhpVersion::PHP_56);
$rectorConfig->rule(DowngradeCatchThrowableRector::class);
$rectorConfig->rule(DowngradeInstanceofThrowableRector::class);
$rectorConfig->rule(DowngradeScalarTypeDeclarationRector::class);
$rectorConfig->rule(DowngradeThrowableTypeDeclarationRector::class);
$rectorConfig->rule(DowngradeStrictTypeDeclarationRector::class);
$rectorConfig->rule(DowngradeSelfTypeDeclarationRector::class);
$rectorConfig->rule(DowngradeAnonymousClassRector::class);
$rectorConfig->rule(DowngradeNullCoalesceRector::class);
$rectorConfig->rule(DowngradeSpaceshipRector::class);
$rectorConfig->rule(DowngradeDefineArrayConstantRector::class);
$rectorConfig->rule(DowngradeDirnameLevelsRector::class);
$rectorConfig->rule(DowngradeSessionStartArrayOptionsRector::class);
$rectorConfig->rule(DowngradeUncallableValueCallToCallUserFuncRector::class);
$rectorConfig->rule(SplitGroupedUseImportsRector::class);
$rectorConfig->rule(DowngradeClosureCallRector::class);
$rectorConfig->rule(DowngradeParentTypeDeclarationRector::class);
$rectorConfig->rule(DowngradeMethodCallOnCloneRector::class);
$rectorConfig->rule(DowngradeUnnecessarilyParenthesizedExpressionRector::class);
};

View File

@ -1,11 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202306;
use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\DowngradeLevelSetList;
use Rector\Set\ValueObject\DowngradeSetList;
return static function (RectorConfig $rectorConfig) : void {
$rectorConfig->sets([DowngradeLevelSetList::DOWN_TO_PHP_70, DowngradeSetList::PHP_70]);
};

View File

@ -1,4 +1,4 @@
# 97 Rules Overview
# 79 Rules Overview
## ArrowFunctionToAnonymousFunctionRector
@ -38,35 +38,6 @@ Remove "abstract" from private methods in traits and adds an empty function body
<br>
## DowngradeAnonymousClassRector
Remove anonymous class
- class: [`Rector\DowngradePhp70\Rector\New_\DowngradeAnonymousClassRector`](../rules/DowngradePhp70/Rector/New_/DowngradeAnonymousClassRector.php)
```diff
+class Anonymous
+{
+ public function execute()
+ {
+ }
+}
class SomeClass
{
public function run()
{
- return new class {
- public function execute()
- {
- }
- };
+ return new Anonymous();
}
}
```
<br>
## DowngradeArbitraryExpressionsSupportRector
Replace arbitrary expressions used with new or instanceof
@ -269,24 +240,6 @@ return static function (RectorConfig $rectorConfig): void {
<br>
## DowngradeCatchThrowableRector
Make catch clauses catching `Throwable` also catch `Exception` to support exception hierarchies in PHP 5.
- class: [`Rector\DowngradePhp70\Rector\TryCatch\DowngradeCatchThrowableRector`](../rules/DowngradePhp70/Rector/TryCatch/DowngradeCatchThrowableRector.php)
```diff
try {
// Some code...
} catch (\Throwable $exception) {
handle();
+} catch (\Exception $exception) {
+ handle();
}
```
<br>
## DowngradeClassConstantVisibilityRector
Downgrade class constant visibility
@ -326,19 +279,6 @@ Change `$object::class` to get_class($object)
<br>
## DowngradeClosureCallRector
Replace `Closure::call()` by `Closure::bindTo()`
- class: [`Rector\DowngradePhp70\Rector\MethodCall\DowngradeClosureCallRector`](../rules/DowngradePhp70/Rector/MethodCall/DowngradeClosureCallRector.php)
```diff
-$closure->call($newObj, ...$args);
+call_user_func($closure->bindTo($newObj, $newObj), ...$args);
```
<br>
## DowngradeClosureFromCallableRector
Converts `Closure::fromCallable()` to compatible alternative.
@ -417,24 +357,6 @@ Make method return same type as parent
<br>
## DowngradeDefineArrayConstantRector
Change array contant definition via define to const
- class: [`Rector\DowngradePhp70\Rector\Expression\DowngradeDefineArrayConstantRector`](../rules/DowngradePhp70/Rector/Expression/DowngradeDefineArrayConstantRector.php)
```diff
-define('ANIMALS', [
+const ANIMALS = [
'dog',
'cat',
'bird'
-]);
+];
```
<br>
## DowngradeDereferenceableOperationRector
Add parentheses around non-dereferenceable expressions.
@ -451,19 +373,6 @@ Add parentheses around non-dereferenceable expressions.
<br>
## DowngradeDirnameLevelsRector
Replace the 2nd argument of `dirname()`
- class: [`Rector\DowngradePhp70\Rector\FuncCall\DowngradeDirnameLevelsRector`](../rules/DowngradePhp70/Rector/FuncCall/DowngradeDirnameLevelsRector.php)
```diff
-return dirname($path, 2);
+return dirname(dirname($path));
```
<br>
## DowngradeEnumToConstantListClassRector
Downgrade enum to constant list class
@ -548,19 +457,6 @@ Changes `fread()` or `fwrite()` compare to false to negation check
<br>
## DowngradeInstanceofThrowableRector
Add `instanceof Exception` check as a fallback to `instanceof Throwable` to support exception hierarchies in PHP 5
- class: [`Rector\DowngradePhp70\Rector\Instanceof_\DowngradeInstanceofThrowableRector`](../rules/DowngradePhp70/Rector/Instanceof_/DowngradeInstanceofThrowableRector.php)
```diff
-return $exception instanceof \Throwable;
+return $exception instanceof \Throwable || $exception instanceof \Exception;
```
<br>
## DowngradeIsCountableRector
Downgrade `is_countable()` to former version
@ -713,20 +609,6 @@ Downgrade `match()` to `switch()`
<br>
## DowngradeMethodCallOnCloneRector
Replace (clone `$obj)->call()` to object assign and call
- class: [`Rector\DowngradePhp70\Rector\MethodCall\DowngradeMethodCallOnCloneRector`](../rules/DowngradePhp70/Rector/MethodCall/DowngradeMethodCallOnCloneRector.php)
```diff
-(clone $this)->execute();
+$object = (clone $this);
+$object->execute();
```
<br>
## DowngradeMixedTypeDeclarationRector
Remove the "mixed" param and return type, add a `@param` and `@return` tag instead
@ -868,19 +750,6 @@ Downgrade catch () without variable to one
<br>
## DowngradeNullCoalesceRector
Change null coalesce to isset ternary check
- class: [`Rector\DowngradePhp70\Rector\Coalesce\DowngradeNullCoalesceRector`](../rules/DowngradePhp70/Rector/Coalesce/DowngradeNullCoalesceRector.php)
```diff
-$username = $_GET['user'] ?? 'nobody';
+$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';
```
<br>
## DowngradeNullCoalescingOperatorRector
Remove null coalescing operator ??=
@ -1047,32 +916,6 @@ return static function (RectorConfig $rectorConfig): void {
<br>
## DowngradeParentTypeDeclarationRector
Remove "parent" return type, add a `"@return` parent" tag instead
- class: [`Rector\DowngradePhp70\Rector\ClassMethod\DowngradeParentTypeDeclarationRector`](../rules/DowngradePhp70/Rector/ClassMethod/DowngradeParentTypeDeclarationRector.php)
```diff
class ParentClass
{
}
class SomeClass extends ParentClass
{
- public function foo(): parent
+ /**
+ * @return parent
+ */
+ public function foo()
{
return $this;
}
}
```
<br>
## DowngradePhp71JsonConstRector
Remove Json constant that available only in php 7.1
@ -1403,7 +1246,7 @@ Downgrade reflection `$reflection->getType()` method call
public function run(ReflectionProperty $reflectionProperty)
{
- if ($reflectionProperty->getType()) {
+ if (null) {
+ if (method_exists($reflectionProperty, 'getType') ? $reflectionProperty->getType() ? null) {
return true;
}
@ -1433,85 +1276,6 @@ Downgrade `ReflectionProperty->getDefaultValue()`
<br>
## DowngradeScalarTypeDeclarationRector
Remove the type params and return type, add `@param` and `@return` tags instead
- class: [`Rector\DowngradePhp70\Rector\FunctionLike\DowngradeScalarTypeDeclarationRector`](../rules/DowngradePhp70/Rector/FunctionLike/DowngradeScalarTypeDeclarationRector.php)
```diff
class SomeClass
{
- public function run(string $input): string
+ /**
+ * @param string $input
+ * @return string
+ */
+ public function run($input)
{
}
}
```
<br>
## DowngradeSelfTypeDeclarationRector
Remove "self" return type, add a `"@return` `$this"` tag instead
- class: [`Rector\DowngradePhp70\Rector\ClassMethod\DowngradeSelfTypeDeclarationRector`](../rules/DowngradePhp70/Rector/ClassMethod/DowngradeSelfTypeDeclarationRector.php)
```diff
class SomeClass
{
- public function foo(): self
+ /**
+ * @return $this
+ */
+ public function foo()
{
return $this;
}
}
```
<br>
## DowngradeSessionStartArrayOptionsRector
Move array option of session_start($options) to before statement's `ini_set()`
- class: [`Rector\DowngradePhp70\Rector\FuncCall\DowngradeSessionStartArrayOptionsRector`](../rules/DowngradePhp70/Rector/FuncCall/DowngradeSessionStartArrayOptionsRector.php)
```diff
-session_start([
- 'cache_limiter' => 'private',
-]);
+ini_set('session.cache_limiter', 'private');
+session_start();
```
<br>
## DowngradeSpaceshipRector
Change spaceship with check equal, and ternary to result 0, -1, 1
- class: [`Rector\DowngradePhp70\Rector\Spaceship\DowngradeSpaceshipRector`](../rules/DowngradePhp70/Rector/Spaceship/DowngradeSpaceshipRector.php)
```diff
-return $a <=> $b;
+$battleShipcompare = function ($left, $right) {
+ if ($left === $right) {
+ return 0;
+ }
+ return $left < $right ? -1 : 1;
+};
+return $battleShipcompare($a, $b);
```
<br>
## DowngradeStaticTypeDeclarationRector
Remove "static" return and param type, add a `"@param` `$this"` and `"@return` `$this"` tag instead
@ -1617,19 +1381,6 @@ Downgrade `stream_isatty()` function
<br>
## DowngradeStrictTypeDeclarationRector
Remove the declare(strict_types=1)
- class: [`Rector\DowngradePhp70\Rector\Declare_\DowngradeStrictTypeDeclarationRector`](../rules/DowngradePhp70/Rector/Declare_/DowngradeStrictTypeDeclarationRector.php)
```diff
-declare(strict_types=1);
echo 'something';
```
<br>
## DowngradeStringReturnTypeOnToStringRector
Add "string" return on current `__toString()` method when parent method has string return on `__toString()` method
@ -1699,29 +1450,6 @@ Downgrade throw expression
<br>
## DowngradeThrowableTypeDeclarationRector
Replace `Throwable` type hints by PHPDoc tags
- class: [`Rector\DowngradePhp70\Rector\FunctionLike\DowngradeThrowableTypeDeclarationRector`](../rules/DowngradePhp70/Rector/FunctionLike/DowngradeThrowableTypeDeclarationRector.php)
```diff
class SomeClass
{
- public function foo(\Throwable $e): ?\Throwable
+ /**
+ * @param \Throwable $e
+ * @return \Throwable|null
+ */
+ public function foo($e)
{
return new \Exception("Troubles");
}
}
```
<br>
## DowngradeTrailingCommasInFunctionCallsRector
Remove trailing commas in function calls
@ -1809,33 +1537,6 @@ Changes property type definition from type definitions to `@var` annotations.
<br>
## DowngradeUncallableValueCallToCallUserFuncRector
Downgrade calling a value that is not directly callable in PHP 5 (property, static property, closure, …) to call_user_func.
- class: [`Rector\DowngradePhp70\Rector\FuncCall\DowngradeUncallableValueCallToCallUserFuncRector`](../rules/DowngradePhp70/Rector/FuncCall/DowngradeUncallableValueCallToCallUserFuncRector.php)
```diff
final class Foo
{
/** @var callable */
public $handler;
/** @var callable */
public static $staticHandler;
}
$foo = new Foo;
-($foo->handler)(/* args */);
-($foo::$staticHandler)(41);
+call_user_func($foo->handler, /* args */);
+call_user_func($foo::$staticHandler, 41);
-(function() { /* … */ })();
+call_user_func(function() { /* … */ });
```
<br>
## DowngradeUnionTypeDeclarationRector
Remove the union type params and returns, add `@param/@return` tags instead
@ -1878,29 +1579,6 @@ Removes union type property type definition, adding `@var` annotations instead.
<br>
## DowngradeUnnecessarilyParenthesizedExpressionRector
Remove parentheses around expressions allowed by Uniform variable syntax RFC where they are not necessary to prevent parse errors on PHP 5.
- class: [`Rector\DowngradePhp70\Rector\Expr\DowngradeUnnecessarilyParenthesizedExpressionRector`](../rules/DowngradePhp70/Rector/Expr/DowngradeUnnecessarilyParenthesizedExpressionRector.php)
```diff
-($f)['foo'];
-($f)->foo;
-($f)->foo();
-($f)::$foo;
-($f)::foo();
-($f)();
+$f['foo'];
+$f->foo;
+$f->foo();
+$f::$foo;
+$f::foo();
+$f();
```
<br>
## DowngradeVoidTypeDeclarationRector
Remove "void" return type, add a `"@return` void" tag instead
@ -1953,23 +1631,6 @@ Convert setcookie option array to arguments
<br>
## SplitGroupedUseImportsRector
Refactor grouped use imports to standalone lines
- class: [`Rector\DowngradePhp70\Rector\GroupUse\SplitGroupedUseImportsRector`](../rules/DowngradePhp70/Rector/GroupUse/SplitGroupedUseImportsRector.php)
```diff
-use SomeNamespace\{
- First,
- Second
-};
+use SomeNamespace\First;
+use SomeNamespace\Second;
```
<br>
## SymmetricArrayDestructuringToListRector
Downgrade Symmetric array destructuring to `list()` function

View File

@ -1,13 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\DowngradePhp70\NodeFactory;
use PhpParser\Node\Stmt\Class_;
final class ClassFromAnonymousFactory
{
public function create(string $className, Class_ $newClass) : Class_
{
return new Class_($className, ['flags' => $newClass->flags, 'extends' => $newClass->extends, 'implements' => $newClass->implements, 'stmts' => $newClass->stmts, 'attrGroups' => $newClass->attrGroups]);
}
}

View File

@ -1,96 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\DowngradePhp70\Rector\ClassMethod;
use PhpParser\Node;
use PhpParser\Node\Stmt\ClassMethod;
use PHPStan\Reflection\ClassReflection;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\Reflection\ReflectionResolver;
use Rector\PhpDocDecorator\PhpDocFromTypeDeclarationDecorator;
use Rector\StaticTypeMapper\ValueObject\Type\ParentObjectWithoutClassType;
use Rector\StaticTypeMapper\ValueObject\Type\ParentStaticType;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see \Rector\Tests\DowngradePhp70\Rector\ClassMethod\DowngradeParentTypeDeclarationRector\DowngradeParentTypeDeclarationRectorTest
*/
final class DowngradeParentTypeDeclarationRector extends AbstractRector
{
/**
* @readonly
* @var \Rector\PhpDocDecorator\PhpDocFromTypeDeclarationDecorator
*/
private $phpDocFromTypeDeclarationDecorator;
/**
* @readonly
* @var \Rector\Core\Reflection\ReflectionResolver
*/
private $reflectionResolver;
public function __construct(PhpDocFromTypeDeclarationDecorator $phpDocFromTypeDeclarationDecorator, ReflectionResolver $reflectionResolver)
{
$this->phpDocFromTypeDeclarationDecorator = $phpDocFromTypeDeclarationDecorator;
$this->reflectionResolver = $reflectionResolver;
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes() : array
{
return [ClassMethod::class];
}
public function getRuleDefinition() : RuleDefinition
{
return new RuleDefinition('Remove "parent" return type, add a "@return parent" tag instead', [new CodeSample(<<<'CODE_SAMPLE'
class ParentClass
{
}
class SomeClass extends ParentClass
{
public function foo(): parent
{
return $this;
}
}
CODE_SAMPLE
, <<<'CODE_SAMPLE'
class ParentClass
{
}
class SomeClass extends ParentClass
{
/**
* @return parent
*/
public function foo()
{
return $this;
}
}
CODE_SAMPLE
)]);
}
/**
* @param ClassMethod $node
*/
public function refactor(Node $node) : ?Node
{
$classReflection = $this->reflectionResolver->resolveClassReflection($node);
if (!$classReflection instanceof ClassReflection) {
return null;
}
$parentClassReflection = $classReflection->getParentClass();
if ($parentClassReflection instanceof ClassReflection) {
$staticType = new ParentStaticType($parentClassReflection);
} else {
$staticType = new ParentObjectWithoutClassType();
}
if (!$this->phpDocFromTypeDeclarationDecorator->decorateReturnWithSpecificType($node, $staticType)) {
return null;
}
return $node;
}
}

View File

@ -1,82 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\DowngradePhp70\Rector\ClassMethod;
use PhpParser\Node;
use PhpParser\Node\Stmt\ClassMethod;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Type\ThisType;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\Reflection\ReflectionResolver;
use Rector\PhpDocDecorator\PhpDocFromTypeDeclarationDecorator;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see \Rector\Tests\DowngradePhp70\Rector\ClassMethod\DowngradeSelfTypeDeclarationRector\DowngradeSelfTypeDeclarationRectorTest
*/
final class DowngradeSelfTypeDeclarationRector extends AbstractRector
{
/**
* @readonly
* @var \Rector\PhpDocDecorator\PhpDocFromTypeDeclarationDecorator
*/
private $phpDocFromTypeDeclarationDecorator;
/**
* @readonly
* @var \Rector\Core\Reflection\ReflectionResolver
*/
private $reflectionResolver;
public function __construct(PhpDocFromTypeDeclarationDecorator $phpDocFromTypeDeclarationDecorator, ReflectionResolver $reflectionResolver)
{
$this->phpDocFromTypeDeclarationDecorator = $phpDocFromTypeDeclarationDecorator;
$this->reflectionResolver = $reflectionResolver;
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes() : array
{
return [ClassMethod::class];
}
public function getRuleDefinition() : RuleDefinition
{
return new RuleDefinition('Remove "self" return type, add a "@return $this" tag instead', [new CodeSample(<<<'CODE_SAMPLE'
class SomeClass
{
public function foo(): self
{
return $this;
}
}
CODE_SAMPLE
, <<<'CODE_SAMPLE'
class SomeClass
{
/**
* @return $this
*/
public function foo()
{
return $this;
}
}
CODE_SAMPLE
)]);
}
/**
* @param ClassMethod $node
*/
public function refactor(Node $node) : ?Node
{
$classReflection = $this->reflectionResolver->resolveClassReflection($node);
if (!$classReflection instanceof ClassReflection) {
return null;
}
$thisType = new ThisType($classReflection);
if (!$this->phpDocFromTypeDeclarationDecorator->decorateReturnWithSpecificType($node, $thisType)) {
return null;
}
return $node;
}
}

View File

@ -1,62 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\DowngradePhp70\Rector\Coalesce;
use PhpParser\Node;
use PhpParser\Node\Expr\BinaryOp\Coalesce;
use PhpParser\Node\Expr\BinaryOp\NotIdentical;
use PhpParser\Node\Expr\Isset_;
use PhpParser\Node\Expr\Ternary;
use Rector\Core\Rector\AbstractRector;
use Rector\NodeAnalyzer\CoalesceAnalyzer;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @changelog https://wiki.php.net/rfc/isset_ternary
*
* @see \Rector\Tests\DowngradePhp70\Rector\Coalesce\DowngradeNullCoalesceRector\DowngradeNullCoalesceRectorTest
*/
final class DowngradeNullCoalesceRector extends AbstractRector
{
/**
* @readonly
* @var \Rector\NodeAnalyzer\CoalesceAnalyzer
*/
private $coalesceAnalyzer;
public function __construct(CoalesceAnalyzer $coalesceAnalyzer)
{
$this->coalesceAnalyzer = $coalesceAnalyzer;
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes() : array
{
return [Coalesce::class];
}
public function getRuleDefinition() : RuleDefinition
{
return new RuleDefinition('Change null coalesce to isset ternary check', [new CodeSample(<<<'CODE_SAMPLE'
$username = $_GET['user'] ?? 'nobody';
CODE_SAMPLE
, <<<'CODE_SAMPLE'
$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';
CODE_SAMPLE
)]);
}
/**
* @param Coalesce $node
*/
public function refactor(Node $node) : Ternary
{
$if = $node->left;
$else = $node->right;
if ($this->coalesceAnalyzer->hasIssetableLeft($node)) {
$cond = new Isset_([$if]);
} else {
$cond = new NotIdentical($if, $this->nodeFactory->createNull());
}
return new Ternary($cond, $if, $else);
}
}

View File

@ -1,54 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\DowngradePhp70\Rector\Declare_;
use PhpParser\Node;
use PhpParser\Node\Stmt\Declare_;
use PhpParser\NodeTraverser;
use Rector\Core\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see \Rector\Tests\DowngradePhp70\Rector\Declare_\DowngradeStrictTypeDeclarationRector\DowngradeStrictTypeDeclarationRectorTest
*/
final class DowngradeStrictTypeDeclarationRector extends AbstractRector
{
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes() : array
{
return [Declare_::class];
}
public function getRuleDefinition() : RuleDefinition
{
return new RuleDefinition('Remove the declare(strict_types=1)', [new CodeSample(<<<'CODE_SAMPLE'
declare(strict_types=1);
echo 'something';
CODE_SAMPLE
, <<<'CODE_SAMPLE'
echo 'something';
CODE_SAMPLE
)]);
}
/**
* @param Declare_ $node
*/
public function refactor(Node $node) : ?int
{
if ($this->shouldSkip($node)) {
return null;
}
return NodeTraverser::REMOVE_NODE;
}
private function shouldSkip(Declare_ $declare) : bool
{
foreach ($declare->declares as $singleDeclare) {
if ($this->isName($singleDeclare->key, 'strict_types')) {
return \false;
}
}
return \true;
}
}

View File

@ -1,94 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\DowngradePhp70\Rector\Expr;
use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\ArrayDimFetch;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Expr\StaticPropertyFetch;
use Rector\Core\Rector\AbstractRector;
use Rector\DowngradePhp70\Tokenizer\WrappedInParenthesesAnalyzer;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @changelog https://wiki.php.net/rfc/uniform_variable_syntax
*
* @see \Rector\Tests\DowngradePhp70\Rector\Expr\DowngradeUnnecessarilyParenthesizedExpressionRector\DowngradeUnnecessarilyParenthesizedExpressionRectorTest
*/
final class DowngradeUnnecessarilyParenthesizedExpressionRector extends AbstractRector
{
/**
* @readonly
* @var \Rector\DowngradePhp70\Tokenizer\WrappedInParenthesesAnalyzer
*/
private $wrappedInParenthesesAnalyzer;
/**
* @var array<class-string<Expr>>
*/
private const PARENTHESIZABLE_NODES = [ArrayDimFetch::class, PropertyFetch::class, MethodCall::class, StaticPropertyFetch::class, StaticCall::class, FuncCall::class];
public function __construct(WrappedInParenthesesAnalyzer $wrappedInParenthesesAnalyzer)
{
$this->wrappedInParenthesesAnalyzer = $wrappedInParenthesesAnalyzer;
}
public function getRuleDefinition() : RuleDefinition
{
return new RuleDefinition('Remove parentheses around expressions allowed by Uniform variable syntax RFC where they are not necessary to prevent parse errors on PHP 5.', [new CodeSample(<<<'CODE_SAMPLE'
($f)['foo'];
($f)->foo;
($f)->foo();
($f)::$foo;
($f)::foo();
($f)();
CODE_SAMPLE
, <<<'CODE_SAMPLE'
$f['foo'];
$f->foo;
$f->foo();
$f::$foo;
$f::foo();
$f();
CODE_SAMPLE
)]);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes() : array
{
return [
// TODO: Make PHPStan rules allow Expr namespace for its subclasses.
Expr::class,
];
}
/**
* @param ArrayDimFetch|PropertyFetch|MethodCall|StaticPropertyFetch|StaticCall|FuncCall $node
*/
public function refactor(Node $node) : ?Expr
{
if (!\in_array(\get_class($node), self::PARENTHESIZABLE_NODES, \true)) {
return null;
}
$leftSubNode = $this->getLeftSubNode($node);
if (!$leftSubNode instanceof Node) {
return null;
}
if (!$this->wrappedInParenthesesAnalyzer->isParenthesized($this->file, $leftSubNode)) {
return null;
}
// Parenthesization is not part of the AST and Rector only re-generates code for AST nodes that changed.
// Lets remove the original node reference forcing the re-generation of the corresponding code.
// The code generator will only put parentheses where strictly necessary, which other rules should handle.
$node->setAttribute(AttributeKey::ORIGINAL_NODE, null);
return $node;
}
private function getLeftSubNode(Node $node) : ?Node
{
return \true === $node instanceof ArrayDimFetch ? $node->var : (\true === $node instanceof PropertyFetch ? $node->var : (\true === $node instanceof MethodCall ? $node->var : (\true === $node instanceof StaticPropertyFetch ? $node->class : (\true === $node instanceof StaticCall ? $node->class : (\true === $node instanceof FuncCall ? $node->name : null)))));
}
}

View File

@ -1,84 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\DowngradePhp70\Rector\Expression;
use PhpParser\Node;
use PhpParser\Node\Const_;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Expression;
use PhpParser\Node\Stmt\Function_;
use Rector\Core\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see \Rector\Tests\DowngradePhp70\Rector\Expression\DowngradeDefineArrayConstantRector\DowngradeDefineArrayConstantRectorTest
*/
final class DowngradeDefineArrayConstantRector extends AbstractRector
{
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes() : array
{
return [Expression::class];
}
public function getRuleDefinition() : RuleDefinition
{
return new RuleDefinition('Change array contant definition via define to const', [new CodeSample(<<<'CODE_SAMPLE'
define('ANIMALS', [
'dog',
'cat',
'bird'
]);
CODE_SAMPLE
, <<<'CODE_SAMPLE'
const ANIMALS = [
'dog',
'cat',
'bird'
];
CODE_SAMPLE
)]);
}
/**
* @param Expression $node
*/
public function refactor(Node $node) : ?Node
{
if (!$node->expr instanceof FuncCall) {
return null;
}
$funcCall = $node->expr;
if ($this->shouldSkip($funcCall)) {
return null;
}
$args = $funcCall->getArgs();
/** @var String_ $arg0 */
$arg0 = $args[0]->value;
$arg0Value = $arg0->value;
/** @var Array_ $arg1Value */
$arg1Value = $args[1]->value;
return new Node\Stmt\Const_([new Const_($arg0Value, $arg1Value)]);
}
private function shouldSkip(FuncCall $funcCall) : bool
{
if ($funcCall->isFirstClassCallable()) {
return \true;
}
if (!$this->isName($funcCall, 'define')) {
return \true;
}
$args = $funcCall->getArgs();
if (!$args[0]->value instanceof String_) {
return \true;
}
if (!$args[1]->value instanceof Array_) {
return \true;
}
return (bool) $this->betterNodeFinder->findParentByTypes($funcCall, [ClassMethod::class, Function_::class]);
}
}

View File

@ -1,81 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\DowngradePhp70\Rector\FuncCall;
use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Name;
use PhpParser\Node\Scalar\LNumber;
use Rector\Core\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @changelog https://bugs.php.net/bug.php?id=70112
*
* @see \Rector\Tests\DowngradePhp70\Rector\FuncCall\DowngradeDirnameLevelsRector\DowngradeDirnameLevelsRectorTest
*/
final class DowngradeDirnameLevelsRector extends AbstractRector
{
/**
* @var string
*/
private const DIRNAME = 'dirname';
public function getRuleDefinition() : RuleDefinition
{
return new RuleDefinition('Replace the 2nd argument of dirname()', [new CodeSample(<<<'CODE_SAMPLE'
return dirname($path, 2);
CODE_SAMPLE
, <<<'CODE_SAMPLE'
return dirname(dirname($path));
CODE_SAMPLE
)]);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes() : array
{
return [FuncCall::class];
}
/**
* @param FuncCall $node
*/
public function refactor(Node $node)
{
if (!$this->isName($node, 'dirname')) {
return null;
}
$explicitValue = $this->getLevelsRealValue($node);
if (\is_int($explicitValue)) {
return $this->refactorForFixedLevels($node, $explicitValue);
}
return null;
}
private function getLevelsRealValue(FuncCall $funcCall) : ?int
{
$args = $funcCall->getArgs();
$levelsArg = $args[1] ?? null;
if (!$levelsArg instanceof Arg) {
return null;
}
if ($levelsArg->value instanceof LNumber) {
return $levelsArg->value->value;
}
return null;
}
private function refactorForFixedLevels(FuncCall $funcCall, int $levels) : FuncCall
{
// keep only the 1st argument
$funcCall->args = [$funcCall->args[0]];
for ($i = 1; $i < $levels; ++$i) {
$funcCall = $this->createDirnameFuncCall(new Arg($funcCall));
}
return $funcCall;
}
private function createDirnameFuncCall(Arg $pathArg) : FuncCall
{
return new FuncCall(new Name(self::DIRNAME), [$pathArg]);
}
}

View File

@ -1,100 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\DowngradePhp70\Rector\FuncCall;
use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Expr\ArrayItem;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Name;
use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Stmt;
use PhpParser\Node\Stmt\Expression;
use PhpParser\Node\Stmt\If_;
use PhpParser\Node\Stmt\Return_;
use Rector\Core\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see \Rector\Tests\DowngradePhp70\Rector\FuncCall\DowngradeSessionStartArrayOptionsRector\DowngradeSessionStartArrayOptionsRectorTest
*/
final class DowngradeSessionStartArrayOptionsRector extends AbstractRector
{
public function getRuleDefinition() : RuleDefinition
{
return new RuleDefinition('Move array option of session_start($options) to before statement\'s ini_set()', [new CodeSample(<<<'CODE_SAMPLE'
session_start([
'cache_limiter' => 'private',
]);
CODE_SAMPLE
, <<<'CODE_SAMPLE'
ini_set('session.cache_limiter', 'private');
session_start();
CODE_SAMPLE
)]);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes() : array
{
return [Expression::class, Return_::class, If_::class];
}
/**
* @param Expression|Return_|If_ $node
* @return Stmt[]|null
*/
public function refactor(Node $node) : ?array
{
$funcCalls = $this->betterNodeFinder->findInstanceOf($node, FuncCall::class);
$nodesToReturn = [];
foreach ($funcCalls as $funcCall) {
if ($this->shouldSkip($funcCall)) {
continue;
}
$firstArg = $funcCall->getArgs()[0] ?? null;
if (!$firstArg instanceof Arg) {
continue;
}
/** @var Array_ $options */
$options = $firstArg->value;
foreach ($options->items as $option) {
if (!$option instanceof ArrayItem) {
continue;
}
if (!$option->key instanceof String_) {
continue;
}
if (!$this->valueResolver->isTrueOrFalse($option->value) && !$option->value instanceof String_) {
continue;
}
$initSetFuncCall = $this->createInitSetFuncCall($option, $option->key);
unset($funcCall->args[0]);
$nodesToReturn[] = new Expression($initSetFuncCall);
}
}
if ($nodesToReturn !== []) {
return \array_merge($nodesToReturn, [$node]);
}
return null;
}
private function shouldSkip(FuncCall $funcCall) : bool
{
if (!$this->isName($funcCall, 'session_start')) {
return \true;
}
$args = $funcCall->getArgs();
if (!isset($args[0])) {
return \true;
}
return !$args[0]->value instanceof Array_;
}
private function createInitSetFuncCall(ArrayItem $arrayItem, String_ $string) : FuncCall
{
$sessionKey = new String_('session.' . $string->value);
$funcName = new Name('ini_set');
return new FuncCall($funcName, [new Arg($sessionKey), new Arg($arrayItem->value)]);
}
}

View File

@ -1,97 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\DowngradePhp70\Rector\FuncCall;
use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\Closure;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Expr\StaticPropertyFetch;
use PhpParser\Node\Name;
use Rector\Core\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @changelog https://wiki.php.net/rfc/uniform_variable_syntax
*
* @see \Rector\Tests\DowngradePhp70\Rector\FuncCall\DowngradeUncallableValueCallToCallUserFuncRector\DowngradeUncallableValueCallToCallUserFuncRectorTest
*/
final class DowngradeUncallableValueCallToCallUserFuncRector extends AbstractRector
{
/**
* @var array<class-string<Expr>>
*/
private const INDIRECT_CALLABLE_EXPR = [
// Interpreted as MethodCall without parentheses.
PropertyFetch::class,
// Interpreted as StaticCall without parentheses.
StaticPropertyFetch::class,
Closure::class,
// The first function call does not even need to be wrapped in parentheses
// but PHP 5 still does not like curried functions like `f($args)($moreArgs)`.
FuncCall::class,
];
public function getRuleDefinition() : RuleDefinition
{
return new RuleDefinition('Downgrade calling a value that is not directly callable in PHP 5 (property, static property, closure, …) to call_user_func.', [new CodeSample(<<<'CODE_SAMPLE'
final class Foo
{
/** @var callable */
public $handler;
/** @var callable */
public static $staticHandler;
}
$foo = new Foo;
($foo->handler)(/* args */);
($foo::$staticHandler)(41);
(function() { /* … */ })();
CODE_SAMPLE
, <<<'CODE_SAMPLE'
final class Foo
{
/** @var callable */
public $handler;
/** @var callable */
public static $staticHandler;
}
$foo = new Foo;
call_user_func($foo->handler, /* args */);
call_user_func($foo::$staticHandler, 41);
call_user_func(function() { /* … */ });
CODE_SAMPLE
)]);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes() : array
{
return [FuncCall::class];
}
/**
* @param FuncCall $node
*/
public function refactor(Node $node) : ?FuncCall
{
if ($node->name instanceof Name) {
return null;
}
if (!$this->isNotDirectlyCallableInPhp5($node->name)) {
return null;
}
$args = $node->getArgs();
$args = \array_merge([new Arg($node->name)], $args);
return new FuncCall(new Name('call_user_func'), $args);
}
private function isNotDirectlyCallableInPhp5(Expr $expr) : bool
{
return \in_array(\get_class($expr), self::INDIRECT_CALLABLE_EXPR, \true);
}
}

View File

@ -1,140 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\DowngradePhp70\Rector\FunctionLike;
use PhpParser\Node;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\Cast;
use PhpParser\Node\Expr\Cast\Bool_;
use PhpParser\Node\Expr\Cast\Double;
use PhpParser\Node\Expr\Cast\Int_;
use PhpParser\Node\Expr\Cast\String_;
use PhpParser\Node\Expr\Closure;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Expression;
use PhpParser\Node\Stmt\Function_;
use PHPStan\Type\BooleanType;
use PHPStan\Type\FloatType;
use PHPStan\Type\IntegerType;
use PHPStan\Type\StringType;
use PHPStan\Type\Type;
use Rector\Core\Rector\AbstractRector;
use Rector\PhpDocDecorator\PhpDocFromTypeDeclarationDecorator;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @changelog https://wiki.php.net/rfc/scalar_type_hints
*
* @see \Rector\Tests\DowngradePhp70\Rector\FunctionLike\DowngradeScalarTypeDeclarationRector\DowngradeScalarTypeDeclarationRectorTest
*/
final class DowngradeScalarTypeDeclarationRector extends AbstractRector
{
/**
* @readonly
* @var \Rector\PhpDocDecorator\PhpDocFromTypeDeclarationDecorator
*/
private $phpDocFromTypeDeclarationDecorator;
public function __construct(PhpDocFromTypeDeclarationDecorator $phpDocFromTypeDeclarationDecorator)
{
$this->phpDocFromTypeDeclarationDecorator = $phpDocFromTypeDeclarationDecorator;
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes() : array
{
return [Function_::class, ClassMethod::class, Closure::class];
}
public function getRuleDefinition() : RuleDefinition
{
return new RuleDefinition('Remove the type params and return type, add @param and @return tags instead', [new CodeSample(<<<'CODE_SAMPLE'
class SomeClass
{
public function run(string $input): string
{
}
}
CODE_SAMPLE
, <<<'CODE_SAMPLE'
class SomeClass
{
/**
* @param string $input
* @return string
*/
public function run($input)
{
}
}
CODE_SAMPLE
)]);
}
/**
* @param Function_|ClassMethod|Closure $node
*/
public function refactor(Node $node) : ?Node
{
$recastAssigns = [];
foreach ($node->params as $param) {
if ($param->type === null) {
continue;
}
$this->phpDocFromTypeDeclarationDecorator->decorateParam($param, $node, [StringType::class, IntegerType::class, BooleanType::class, FloatType::class]);
$recastAssign = $this->resolveRecastAssign($param, $node);
if ($recastAssign instanceof Expression) {
$recastAssigns[] = $recastAssign;
}
}
if ($recastAssigns !== []) {
$node->stmts = \array_merge($recastAssigns, (array) $node->stmts);
}
if ($node->returnType === null) {
return null;
}
$this->phpDocFromTypeDeclarationDecorator->decorateReturn($node);
return $node;
}
/**
* @param \PhpParser\Node\Stmt\Function_|\PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Expr\Closure $functionLike
*/
private function resolveRecastAssign(Param $param, $functionLike) : ?Expression
{
if ($functionLike->stmts === null) {
return null;
}
if ($functionLike->stmts === []) {
return null;
}
// add possible object with __toString() re-type to keep original behavior
// @see https://twitter.com/VotrubaT/status/1390974218108538887
/** @var string $paramName */
$paramName = $this->getName($param->var);
$variable = new Variable($paramName);
$paramType = $this->getType($param);
$variableCast = $this->recastVariableIfScalarType($variable, $paramType);
if (!$variableCast instanceof Cast) {
return null;
}
$assign = new Assign($variable, $variableCast);
return new Expression($assign);
}
private function recastVariableIfScalarType(Variable $variable, Type $type) : ?Cast
{
if ($type instanceof StringType) {
return new String_($variable);
}
if ($type instanceof IntegerType) {
return new Int_($variable);
}
if ($type instanceof FloatType) {
return new Double($variable);
}
if ($type instanceof BooleanType) {
return new Bool_($variable);
}
return null;
}
}

View File

@ -1,84 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\DowngradePhp70\Rector\FunctionLike;
use PhpParser\Node;
use PhpParser\Node\Expr\Closure;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Function_;
use PHPStan\Type\ObjectType;
use Rector\Core\Rector\AbstractRector;
use Rector\PhpDocDecorator\PhpDocFromTypeDeclarationDecorator;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see \Rector\Tests\DowngradePhp70\Rector\FunctionLike\DowngradeThrowableTypeDeclarationRector\DowngradeThrowableTypeDeclarationRectorTest
*/
final class DowngradeThrowableTypeDeclarationRector extends AbstractRector
{
/**
* @readonly
* @var \Rector\PhpDocDecorator\PhpDocFromTypeDeclarationDecorator
*/
private $phpDocFromTypeDeclarationDecorator;
public function __construct(PhpDocFromTypeDeclarationDecorator $phpDocFromTypeDeclarationDecorator)
{
$this->phpDocFromTypeDeclarationDecorator = $phpDocFromTypeDeclarationDecorator;
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes() : array
{
return [Function_::class, ClassMethod::class, Closure::class];
}
public function getRuleDefinition() : RuleDefinition
{
return new RuleDefinition('Replace `Throwable` type hints by PHPDoc tags', [new CodeSample(<<<'CODE_SAMPLE'
class SomeClass
{
public function foo(\Throwable $e): ?\Throwable
{
return new \Exception("Troubles");
}
}
CODE_SAMPLE
, <<<'CODE_SAMPLE'
class SomeClass
{
/**
* @param \Throwable $e
* @return \Throwable|null
*/
public function foo($e)
{
return new \Exception("Troubles");
}
}
CODE_SAMPLE
)]);
}
/**
* @param ClassMethod|Function_|Closure $node
*/
public function refactor(Node $node) : ?Node
{
$objectType = new ObjectType('Throwable');
$hasChanged = \false;
$hasParamChanged = \false;
foreach ($node->getParams() as $param) {
$hasParamChanged = $this->phpDocFromTypeDeclarationDecorator->decorateParamWithSpecificType($param, $node, $objectType);
if ($hasParamChanged) {
$hasChanged = \true;
}
}
if (!$this->phpDocFromTypeDeclarationDecorator->decorateReturnWithSpecificType($node, $objectType)) {
if ($hasChanged) {
return $node;
}
return null;
}
return $node;
}
}

View File

@ -1,55 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\DowngradePhp70\Rector\GroupUse;
use PhpParser\Node;
use PhpParser\Node\Name;
use PhpParser\Node\Stmt\GroupUse;
use PhpParser\Node\Stmt\Use_;
use Rector\Core\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @changelog https://wiki.php.net/rfc/group_use_declarations
*
* @see \Rector\Tests\DowngradePhp70\Rector\GroupUse\SplitGroupedUseImportsRector\SplitGroupedUseImportsRectorTest
*/
final class SplitGroupedUseImportsRector extends AbstractRector
{
public function getRuleDefinition() : RuleDefinition
{
return new RuleDefinition('Refactor grouped use imports to standalone lines', [new CodeSample(<<<'CODE_SAMPLE'
use SomeNamespace\{
First,
Second
};
CODE_SAMPLE
, <<<'CODE_SAMPLE'
use SomeNamespace\First;
use SomeNamespace\Second;
CODE_SAMPLE
)]);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes() : array
{
return [GroupUse::class];
}
/**
* @param GroupUse $node
* @return Use_[]
*/
public function refactor(Node $node) : array
{
$prefix = $this->getName($node->prefix);
$uses = [];
foreach ($node->uses as $useUse) {
$useUse->name = new Name($prefix . '\\' . $this->getName($useUse->name));
$uses[] = new Use_([$useUse], $node->type);
}
return $uses;
}
}

View File

@ -1,73 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\DowngradePhp70\Rector\Instanceof_;
use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\BinaryOp\BooleanOr;
use PhpParser\Node\Expr\Instanceof_;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\NodeTraverser;
use Rector\Core\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* Throwable was introduced in PHP 7.0 so to support older versions we need to also check for Exception.
*
* @changelog https://www.php.net/manual/en/class.throwable.php
* @see \Rector\Tests\DowngradePhp70\Rector\Instanceof_\DowngradeInstanceofThrowableRector\DowngradeInstanceofThrowableRectorTest
*/
final class DowngradeInstanceofThrowableRector extends AbstractRector
{
/**
* @var string
*/
private const JUST_CREATED_ATTRIBUTE = 'just_created';
public function getRuleDefinition() : RuleDefinition
{
return new RuleDefinition('Add `instanceof Exception` check as a fallback to `instanceof Throwable` to support exception hierarchies in PHP 5', [new CodeSample(<<<'CODE_SAMPLE'
return $exception instanceof \Throwable;
CODE_SAMPLE
, <<<'CODE_SAMPLE'
return $exception instanceof \Throwable || $exception instanceof \Exception;
CODE_SAMPLE
)]);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes() : array
{
return [Instanceof_::class, BooleanOr::class];
}
/**
* @param Instanceof_|BooleanOr $node
*/
public function refactor(Node $node)
{
if ($node instanceof BooleanOr) {
if ($this->isInstanceofNamed($node->left, 'Throwable') && $this->isInstanceofNamed($node->right, 'Exception')) {
return NodeTraverser::DONT_TRAVERSE_CHILDREN;
}
return null;
}
if ($node->getAttribute(self::JUST_CREATED_ATTRIBUTE)) {
return null;
}
if (!$this->nodeNameResolver->isName($node->class, 'Throwable')) {
return null;
}
$throwableInstanceof = new Instanceof_($node->expr, new FullyQualified('Throwable'));
$throwableInstanceof->setAttribute(self::JUST_CREATED_ATTRIBUTE, \true);
$exceptionInstanceof = new Instanceof_($node->expr, new FullyQualified('Exception'));
return new BooleanOr($throwableInstanceof, $exceptionInstanceof);
}
private function isInstanceofNamed(Expr $expr, string $className) : bool
{
if (!$expr instanceof Instanceof_) {
return \false;
}
return $this->nodeNameResolver->isName($expr->class, $className);
}
}

View File

@ -1,86 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\DowngradePhp70\Rector\MethodCall;
use Closure;
use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Name;
use PhpParser\Node\Param;
use PhpParser\Node\Scalar\LNumber;
use Rector\Core\Rector\AbstractRector;
use Rector\NodeAnalyzer\MethodCallTypeAnalyzer;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @changelog https://wiki.php.net/rfc/closure_apply
*
* @see \Rector\Tests\DowngradePhp70\Rector\MethodCall\DowngradeClosureCallRector\DowngradeClosureCallRectorTest
*/
final class DowngradeClosureCallRector extends AbstractRector
{
/**
* @readonly
* @var \Rector\NodeAnalyzer\MethodCallTypeAnalyzer
*/
private $methodCallTypeAnalyzer;
public function __construct(MethodCallTypeAnalyzer $methodCallTypeAnalyzer)
{
$this->methodCallTypeAnalyzer = $methodCallTypeAnalyzer;
}
public function getRuleDefinition() : RuleDefinition
{
return new RuleDefinition('Replace Closure::call() by Closure::bindTo()', [new CodeSample(<<<'CODE_SAMPLE'
$closure->call($newObj, ...$args);
CODE_SAMPLE
, <<<'CODE_SAMPLE'
call_user_func($closure->bindTo($newObj, $newObj), ...$args);
CODE_SAMPLE
)]);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes() : array
{
return [MethodCall::class];
}
/**
* @param MethodCall $node
*/
public function refactor(Node $node) : ?FuncCall
{
if ($this->shouldSkip($node)) {
return null;
}
$methodCall = $this->createBindToCall($node);
$args = $node->getArgs();
$args = \array_merge([new Arg($methodCall)], \array_slice($args, 1));
return new FuncCall(new Name('call_user_func'), $args);
}
private function shouldSkip(MethodCall $methodCall) : bool
{
if ($methodCall->args === []) {
return \true;
}
return !$this->methodCallTypeAnalyzer->isMethodCallTo($methodCall, Closure::class, 'call');
}
private function createBindToCall(MethodCall $methodCall) : MethodCall
{
$args = $methodCall->getArgs();
$newObj = $args[0];
if ($newObj->value instanceof Variable) {
$args = [$newObj, $newObj];
} else {
// we don't want the expression to be executed twice so we use array_fill() as a trick
$args = [new Arg(new LNumber(0)), new Arg(new LNumber(2)), $newObj];
$funcCall = new FuncCall(new Name('array_fill'), $args);
$args = [new Arg($funcCall, \false, \true)];
}
return new MethodCall($methodCall->var, 'bindTo', $args);
}
}

View File

@ -1,71 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\DowngradePhp70\Rector\MethodCall;
use PhpParser\Node;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\Clone_;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Stmt\Expression;
use Rector\Core\Rector\AbstractRector;
use Rector\Naming\Naming\VariableNaming;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @changelog https://www.php.net/manual/en/migration70.new-features.php#migration70.new-features.others
*
* @see \Rector\Tests\DowngradePhp70\Rector\MethodCall\DowngradeMethodCallOnCloneRector\DowngradeMethodCallOnCloneRectorTest
*/
final class DowngradeMethodCallOnCloneRector extends AbstractRector
{
/**
* @readonly
* @var \Rector\Naming\Naming\VariableNaming
*/
private $variableNaming;
public function __construct(VariableNaming $variableNaming)
{
$this->variableNaming = $variableNaming;
}
public function getRuleDefinition() : RuleDefinition
{
return new RuleDefinition('Replace (clone $obj)->call() to object assign and call', [new CodeSample(<<<'CODE_SAMPLE'
(clone $this)->execute();
CODE_SAMPLE
, <<<'CODE_SAMPLE'
$object = (clone $this);
$object->execute();
CODE_SAMPLE
)]);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes() : array
{
return [Expression::class];
}
/**
* @param Expression $node
*/
public function refactor(Node $node)
{
if (!$node->expr instanceof MethodCall) {
return null;
}
$methodCall = $node->expr;
if (!$methodCall->var instanceof Clone_) {
return null;
}
$clone = $methodCall->var;
$scope = $node->getAttribute(AttributeKey::SCOPE);
$newVariableName = $this->variableNaming->createCountedValueName('object', $scope);
$variable = new Variable($newVariableName);
$assign = new Assign($variable, $clone);
$variableMethodCall = new MethodCall($variable, $methodCall->name);
return [new Expression($assign), new Expression($variableMethodCall)];
}
}

View File

@ -1,132 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\DowngradePhp70\Rector\New_;
use PhpParser\Node;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Name;
use PhpParser\Node\Stmt\Class_;
use Rector\Core\NodeAnalyzer\ClassAnalyzer;
use Rector\Core\Rector\AbstractRector;
use Rector\DowngradePhp70\NodeFactory\ClassFromAnonymousFactory;
use Rector\NodeManipulator\NamespacedNameDecorator;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see \Rector\Tests\DowngradePhp70\Rector\New_\DowngradeAnonymousClassRector\DowngradeAnonymousClassRectorTest
*/
final class DowngradeAnonymousClassRector extends AbstractRector
{
/**
* @readonly
* @var \Rector\Core\NodeAnalyzer\ClassAnalyzer
*/
private $classAnalyzer;
/**
* @readonly
* @var \Rector\DowngradePhp70\NodeFactory\ClassFromAnonymousFactory
*/
private $classFromAnonymousFactory;
/**
* @readonly
* @var \Rector\NodeManipulator\NamespacedNameDecorator
*/
private $namespacedNameDecorator;
/**
* @var string
*/
private const ANONYMOUS_CLASS_PREFIX = 'Anonymous__';
/**
* @var Class_[]
*/
private $classes = [];
public function __construct(ClassAnalyzer $classAnalyzer, ClassFromAnonymousFactory $classFromAnonymousFactory, NamespacedNameDecorator $namespacedNameDecorator)
{
$this->classAnalyzer = $classAnalyzer;
$this->classFromAnonymousFactory = $classFromAnonymousFactory;
$this->namespacedNameDecorator = $namespacedNameDecorator;
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes() : array
{
return [New_::class];
}
public function getRuleDefinition() : RuleDefinition
{
return new RuleDefinition('Remove anonymous class', [new CodeSample(<<<'CODE_SAMPLE'
class SomeClass
{
public function run()
{
return new class {
public function execute()
{
}
};
}
}
CODE_SAMPLE
, <<<'CODE_SAMPLE'
class Anonymous
{
public function execute()
{
}
}
class SomeClass
{
public function run()
{
return new Anonymous();
}
}
CODE_SAMPLE
)]);
}
/**
* @param Node[] $nodes
* @return Node[]|null
*/
public function beforeTraverse(array $nodes) : ?array
{
$this->classes = [];
return parent::beforeTraverse($nodes);
}
/**
* @param Node[] $nodes
* @return Node[]
*/
public function afterTraverse(array $nodes) : array
{
if ($this->classes === []) {
return $nodes;
}
return \array_merge($nodes, $this->classes);
}
/**
* @param New_ $node
*/
public function refactor(Node $node) : ?Node
{
if (!$this->classAnalyzer->isAnonymousClass($node->class)) {
return null;
}
if (!$node->class instanceof Class_) {
return null;
}
$className = $this->createAnonymousClassName();
$class = $this->classFromAnonymousFactory->create($className, $node->class);
$this->classes[] = $class;
$this->namespacedNameDecorator->decorate($class);
$args = $node->getArgs();
return new New_(new Name($className), $args);
}
private function createAnonymousClassName() : string
{
$filePathHash = \md5($this->file->getFilePath());
return self::ANONYMOUS_CLASS_PREFIX . $filePathHash . '__' . \count($this->classes);
}
}

View File

@ -1,103 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\DowngradePhp70\Rector\Spaceship;
use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\BinaryOp\Identical;
use PhpParser\Node\Expr\BinaryOp\Smaller;
use PhpParser\Node\Expr\BinaryOp\Spaceship;
use PhpParser\Node\Expr\Closure;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\Ternary;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Param;
use PhpParser\Node\Scalar\LNumber;
use PhpParser\Node\Stmt\Expression;
use PhpParser\Node\Stmt\If_;
use PhpParser\Node\Stmt\Return_;
use Rector\Core\NodeManipulator\IfManipulator;
use Rector\Core\Rector\AbstractRector;
use Rector\NodeFactory\NamedVariableFactory;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see \Rector\Tests\DowngradePhp70\Rector\Spaceship\DowngradeSpaceshipRector\DowngradeSpaceshipRectorTest
*/
final class DowngradeSpaceshipRector extends AbstractRector
{
/**
* @readonly
* @var \Rector\Core\NodeManipulator\IfManipulator
*/
private $ifManipulator;
/**
* @readonly
* @var \Rector\NodeFactory\NamedVariableFactory
*/
private $namedVariableFactory;
public function __construct(IfManipulator $ifManipulator, NamedVariableFactory $namedVariableFactory)
{
$this->ifManipulator = $ifManipulator;
$this->namedVariableFactory = $namedVariableFactory;
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes() : array
{
return [Return_::class, If_::class];
}
public function getRuleDefinition() : RuleDefinition
{
return new RuleDefinition('Change spaceship with check equal, and ternary to result 0, -1, 1', [new CodeSample(<<<'CODE_SAMPLE'
return $a <=> $b;
CODE_SAMPLE
, <<<'CODE_SAMPLE'
$battleShipcompare = function ($left, $right) {
if ($left === $right) {
return 0;
}
return $left < $right ? -1 : 1;
};
return $battleShipcompare($a, $b);
CODE_SAMPLE
)]);
}
/**
* @param Return_|If_ $node
*/
public function refactor(Node $node)
{
$hasFound = \false;
$assignVariable = $this->namedVariableFactory->createVariable('battleShipcompare', $node);
$this->traverseNodesWithCallable($node, static function (Node $node) use(&$hasFound, $assignVariable) : ?FuncCall {
if (!$node instanceof Spaceship) {
return null;
}
$hasFound = \true;
return new FuncCall($assignVariable, [new Arg($node->left), new Arg($node->right)]);
});
if ($hasFound === \false) {
return null;
}
$anonymousFunction = $this->createAnonymousFunction();
$assignExpression = new Expression(new Assign($assignVariable, $anonymousFunction));
return [$assignExpression, $node];
}
private function createAnonymousFunction() : Closure
{
$leftVariableParam = new Variable('left');
$rightVariableParam = new Variable('right');
$leftParam = new Param($leftVariableParam);
$rightParam = new Param($rightVariableParam);
$if = $this->ifManipulator->createIfStmt(new Identical($leftVariableParam, $rightVariableParam), new Return_(new LNumber(0)));
$smaller = new Smaller($leftVariableParam, $rightVariableParam);
$ternaryIf = new LNumber(-1);
$ternaryElse = new LNumber(1);
$ternary = new Ternary($smaller, $ternaryIf, $ternaryElse);
return new Closure(['params' => [$leftParam, $rightParam], 'stmts' => [$if, new Return_($ternary)]]);
}
}

View File

@ -1,111 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\DowngradePhp70\Rector\TryCatch;
use PhpParser\Node;
use PhpParser\Node\Name;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Stmt;
use PhpParser\Node\Stmt\Catch_;
use PhpParser\Node\Stmt\TryCatch;
use Rector\Core\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* Throwable was introduced in PHP 7.0 so to support older versions we need to also check for Exception.
* @changelog https://www.php.net/manual/en/class.throwable.php
* @see \Rector\Tests\DowngradePhp70\Rector\TryCatch\DowngradeCatchThrowableRector\DowngradeCatchThrowableRectorTest
*/
final class DowngradeCatchThrowableRector extends AbstractRector
{
/**
* @var string
*/
private const EXCEPTION = 'Exception';
public function getRuleDefinition() : RuleDefinition
{
return new RuleDefinition('Make catch clauses catching `Throwable` also catch `Exception` to support exception hierarchies in PHP 5.', [new CodeSample(<<<'CODE_SAMPLE'
try {
// Some code...
} catch (\Throwable $exception) {
handle();
}
CODE_SAMPLE
, <<<'CODE_SAMPLE'
try {
// Some code...
} catch (\Throwable $exception) {
handle();
} catch (\Exception $exception) {
handle();
}
CODE_SAMPLE
)]);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes() : array
{
return [TryCatch::class];
}
/**
* @param TryCatch $node
*/
public function refactor(Node $node) : ?Node
{
$originalCatches = $node->catches;
$hasChanged = \false;
foreach ($node->catches as $catch) {
if (!$this->shouldAddExceptionFallback($catch, $node)) {
continue;
}
$catchType = new FullyQualified(self::EXCEPTION);
$exceptionCatch = new Catch_([$catchType], $catch->var, $catch->stmts);
$originalCatches[] = $exceptionCatch;
$hasChanged = \true;
}
if (!$hasChanged) {
return null;
}
$node->catches = $originalCatches;
return $node;
}
/**
* @param Name[] $types
*/
private function isCatchingType(array $types, string $expected) : bool
{
foreach ($types as $type) {
if ($this->nodeNameResolver->isName($type, $expected)) {
return \true;
}
}
return \false;
}
/**
* @param Stmt[] $body
* @param Catch_[] $catches
*/
private function isCaughtByAnotherClause(array $body, array $catches) : bool
{
foreach ($catches as $catch) {
$caughtAndBodyMatches = $this->isCatchingType($catch->types, self::EXCEPTION) && $this->nodeComparator->areNodesEqual($catch->stmts, $body);
if ($caughtAndBodyMatches) {
return \true;
}
}
return \false;
}
private function shouldAddExceptionFallback(Catch_ $catch, TryCatch $tryCatch) : bool
{
if (!$this->isCatchingType($catch->types, 'Throwable')) {
return \false;
}
if ($this->isCatchingType($catch->types, self::EXCEPTION)) {
return \false;
}
return !$this->isCaughtByAnotherClause($catch->stmts, $tryCatch->catches);
}
}

View File

@ -1,19 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\DowngradePhp70\Tokenizer;
use PhpParser\Node;
use Rector\Core\ValueObject\Application\File;
final class WrappedInParenthesesAnalyzer
{
public function isParenthesized(File $file, Node $node) : bool
{
$oldTokens = $file->getOldTokens();
$startTokenPos = $node->getStartTokenPos();
$endTokenPos = $node->getEndTokenPos();
$previousTokenPos = $startTokenPos >= 0 ? $startTokenPos - 1 : -1;
$nextTokenPos = $endTokenPos >= 0 ? $endTokenPos + 1 : -1;
return isset($oldTokens[$previousTokenPos]) && $oldTokens[$previousTokenPos] === '(' && isset($oldTokens[$nextTokenPos]) && $oldTokens[$nextTokenPos] === ')';
}
}

View File

@ -81,12 +81,12 @@ CODE_SAMPLE
$defaultExpr = new ConstFetch(new Name('null'));
}
$currentTernary = null;
foreach ($reversedMatchArms as $matchArm) {
if ($matchArm->conds === null) {
foreach ($reversedMatchArms as $reversedMatchArm) {
if ($reversedMatchArm->conds === null) {
continue;
}
$cond = $this->createCond($matchArm->conds, $node);
$currentTernary = new Ternary($cond, $matchArm->body, $currentTernary ?: $defaultExpr);
$cond = $this->createCond($reversedMatchArm->conds, $node);
$currentTernary = new Ternary($cond, $reversedMatchArm->body, $currentTernary ?: $defaultExpr);
}
return $currentTernary;
}

View File

@ -1,56 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\NodeAnalyzer;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Identifier;
use PHPStan\Type\Constant\ConstantStringType;
use PHPStan\Type\TypeWithClassName;
use Rector\NodeTypeResolver\NodeTypeResolver;
final class MethodCallTypeAnalyzer
{
/**
* @readonly
* @var \Rector\NodeTypeResolver\NodeTypeResolver
*/
private $nodeTypeResolver;
public function __construct(NodeTypeResolver $nodeTypeResolver)
{
$this->nodeTypeResolver = $nodeTypeResolver;
}
public function isMethodCallTo(MethodCall $methodCall, string $expectedClass, string $expectedMethod) : bool
{
if (!$this->isMethodName($methodCall, $expectedMethod)) {
return \false;
}
return $this->isInstanceOf($methodCall->var, $expectedClass);
}
private function isMethodName(MethodCall $methodCall, string $expectedName) : bool
{
if ($methodCall->name instanceof Identifier && $this->areNamesEqual($methodCall->name->toString(), $expectedName)) {
return \true;
}
$type = $this->nodeTypeResolver->getType($methodCall->name);
return $type instanceof ConstantStringType && $this->areNamesEqual($type->getValue(), $expectedName);
}
private function areNamesEqual(string $left, string $right) : bool
{
return \strcasecmp($left, $right) === 0;
}
/**
* @param class-string $expectedClass
*/
private function isInstanceOf(Expr $expr, string $expectedClass) : bool
{
$type = $this->nodeTypeResolver->getType($expr);
if (!$type instanceof TypeWithClassName) {
return \false;
}
if ($this->areNamesEqual($expectedClass, $type->getClassName())) {
return \true;
}
return $type->getAncestorWithClassName($expectedClass) instanceof TypeWithClassName;
}
}

View File

@ -1,24 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\NodeManipulator;
use PhpParser\Node;
use PhpParser\NodeTraverser;
use PhpParser\NodeVisitor\NameResolver;
final class NamespacedNameDecorator
{
/**
* @api downgrade
* @param \PhpParser\Node|mixed[] $node
*/
public function decorate($node) : void
{
$nodes = \is_array($node) ? $node : [$node];
// traverse with node name resolver, to to comply with PHPStan default parser
$nameResolver = new NameResolver(null, ['replaceNodes' => \false, 'preserveOriginalNames' => \true]);
$nodeTraverser = new NodeTraverser();
$nodeTraverser->addVisitor($nameResolver);
$nodeTraverser->traverse($nodes);
}
}

View File

@ -37,8 +37,4 @@ final class DowngradeLevelSetList implements SetListInterface
* @var string
*/
public const DOWN_TO_PHP_70 = __DIR__ . '/../../../config/set/level/down-to-php70.php';
/**
* @var string
*/
public const DOWN_TO_PHP_56 = __DIR__ . '/../../../config/set/level/down-to-php56.php';
}

View File

@ -9,10 +9,6 @@ use Rector\Set\Contract\SetListInterface;
*/
final class DowngradeSetList implements SetListInterface
{
/**
* @var string
*/
public const PHP_70 = __DIR__ . '/../../../config/set/downgrade-php70.php';
/**
* @var string
*/

View File

@ -169,15 +169,17 @@ CODE_SAMPLE
}
private function hasLastReturnResponse(ClassMethod $classMethod) : bool
{
$node = $this->betterNodeFinder->findLastInstanceOf((array) $classMethod->stmts, Return_::class);
if (!$node instanceof Return_) {
/** @var Return_[] $returns */
$returns = $this->betterNodeFinder->findInstanceOf((array) $classMethod->stmts, Return_::class);
if ($returns === []) {
return \false;
}
if (!$node->expr instanceof Expr) {
$lastReturn = \array_pop($returns);
if (!$lastReturn->expr instanceof Expr) {
return \false;
}
$responseObjectType = new ObjectType(SymfonyClass::RESPONSE);
$returnType = $this->getType($node->expr);
$returnType = $this->getType($lastReturn->expr);
return $responseObjectType->isSuperTypeOf($returnType)->yes();
}
private function refactorReturn(Return_ $return, DoctrineAnnotationTagValueNode $templateDoctrineAnnotationTagValueNode, bool $hasThisRenderOrReturnsResponse, ClassMethod $classMethod) : void