[NetteCodeQuality] Fix ChangeFormArrayAccessToAnnotatedControlVariableRector for in-closure (#4506)

* [NetteCodeQuality] Fix ChangeFormArrayAccessToAnnotatedControlVariableRector for in-closure

* [ci-review] Rector Rectify

* [ci-review] Rector Rectify

* [ci-review] Rector Rectify

* fix name

* fix unknown mixed type on fluent

* [ci-review] Rector Rectify

Co-authored-by: rector-bot <tomas@getrector.org>
This commit is contained in:
Tomas Votruba 2020-10-29 22:25:35 +01:00 committed by GitHub
parent a2ae659e0a
commit 91a354c080
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 356 additions and 111 deletions

View File

@ -180,8 +180,8 @@ final class PhpDocInfo
public function getParamType(string $name): Type
{
$paramTagValue = $this->getParamTagValueByName($name);
return $this->getTypeOrMixed($paramTagValue);
$attributeAwareParamTagValueNode = $this->getParamTagValueByName($name);
return $this->getTypeOrMixed($attributeAwareParamTagValueNode);
}
/**
@ -190,8 +190,8 @@ final class PhpDocInfo
public function getParamTypes(): array
{
$paramTypes = [];
foreach ($this->phpDocNode->getParamTagValues() as $paramTagValue) {
$paramTypes[] = $this->staticTypeMapper->mapPHPStanPhpDocTypeToPHPStanType($paramTagValue, $this->node);
foreach ($this->phpDocNode->getParamTagValues() as $paramTagValueNode) {
$paramTypes[] = $this->staticTypeMapper->mapPHPStanPhpDocTypeToPHPStanType($paramTagValueNode, $this->node);
}
return $paramTypes;
@ -199,12 +199,12 @@ final class PhpDocInfo
public function getParamTagValueNodeByName(string $parameterName): ?ParamTagValueNode
{
foreach ($this->phpDocNode->getParamTagValues() as $paramTagValue) {
if ($paramTagValue->parameterName !== '$' . $parameterName) {
foreach ($this->phpDocNode->getParamTagValues() as $paramTagValueNode) {
if ($paramTagValueNode->parameterName !== '$' . $parameterName) {
continue;
}
return $paramTagValue;
return $paramTagValueNode;
}
return null;
@ -485,9 +485,9 @@ final class PhpDocInfo
{
$throwsTypes = [];
foreach ($this->phpDocNode->getThrowsTagValues() as $throwsPhpDocNode) {
foreach ($this->phpDocNode->getThrowsTagValues() as $throwsTagValueNode) {
$throwsTypes[] = $this->staticTypeMapper->mapPHPStanPhpDocTypeToPHPStanType(
$throwsPhpDocNode,
$throwsTagValueNode,
$this->node
);
}

View File

@ -18,9 +18,10 @@ final class ParentScopeFinder
*/
public function find(Node $node): ?Node
{
return $node->getAttribute(AttributeKey::METHOD_NODE)
?? $node->getAttribute(AttributeKey::FUNCTION_NODE)
?? $node->getAttribute(AttributeKey::CLASS_NODE)
?? $node->getAttribute(AttributeKey::NAMESPACE_NODE);
return $node->getAttribute(AttributeKey::CLOSURE_NODE) ??
$node->getAttribute(AttributeKey::FUNCTION_NODE) ??
$node->getAttribute(AttributeKey::METHOD_NODE) ??
$node->getAttribute(AttributeKey::CLASS_NODE) ??
$node->getAttribute(AttributeKey::NAMESPACE_NODE);
}
}

View File

@ -113,6 +113,10 @@ final class FunctionMethodAndClassNodeVisitor extends NodeVisitorAbstract
$this->methodName = (string) $this->methodName;
}
if ($node instanceof Closure) {
$this->closure = null;
}
return null;
}

View File

@ -115,9 +115,9 @@ final class ShortNameResolver
return $fileInfo->getRealPath();
}
$currentFileInfo = $this->currentFileInfoProvider->getSmartFileInfo();
if ($currentFileInfo !== null) {
return $currentFileInfo->getRealPath();
$smartFileInfo = $this->currentFileInfoProvider->getSmartFileInfo();
if ($smartFileInfo !== null) {
return $smartFileInfo->getRealPath();
}
return null;

View File

@ -70,14 +70,14 @@ final class UsedClassConstsExtractor
private function getClassConstByName(Class_ $class, string $classConstName): ClassConst
{
$classConstantNames = [];
foreach ($class->getConstants() as $constant) {
$classConstantNames[] = $this->nodeNameResolver->getName($constant);
foreach ($class->getConstants() as $classConst) {
$classConstantNames[] = $this->nodeNameResolver->getName($classConst);
if (! $this->nodeNameResolver->isName($constant, $classConstName)) {
if (! $this->nodeNameResolver->isName($classConst, $classConstName)) {
continue;
}
return $constant;
return $classConst;
}
$className = $this->nodeNameResolver->getName($class);

View File

@ -7,6 +7,7 @@ namespace Rector\Defluent\NodeFactory;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Expr\Variable;
use PHPStan\Type\ObjectType;
use Rector\Defluent\NodeAnalyzer\FluentChainMethodCallRootExtractor;
use Rector\Defluent\ValueObject\FirstAssignFluentCall;
use Rector\Defluent\ValueObject\FluentMethodCalls;
@ -40,7 +41,7 @@ final class ReturnFluentMethodCallFactory
$this->propertyNaming = $propertyNaming;
}
public function createFromFluentMethodCalls(FluentMethodCalls $fluentMethodCalls): FirstAssignFluentCall
public function createFromFluentMethodCalls(FluentMethodCalls $fluentMethodCalls): ?FirstAssignFluentCall
{
$rootMethodCall = $fluentMethodCalls->getRootMethodCall();
@ -58,6 +59,10 @@ final class ReturnFluentMethodCallFactory
// we need a variable to assign the stuff into
// the method call, does not belong to the
$staticType = $this->nodeTypeResolver->getStaticType($rootMethodCall);
if (! $staticType instanceof ObjectType) {
return null;
}
$variableName = $this->propertyNaming->fqnToVariableName($staticType);
$assignExpr = new Variable($variableName);
}

View File

@ -125,6 +125,10 @@ CODE_SAMPLE
$fluentMethodCalls
);
if ($firstAssignFluentCall === null) {
return [];
}
// should be skipped?
if ($this->fluentMethodCallSkipper->shouldSkipFirstAssignFluentCall($firstAssignFluentCall)) {
return [];

View File

@ -181,7 +181,7 @@ CODE_SAMPLE
private function addRepositoryProperty(Class_ $class, Expr $entityReferenceExpr): void
{
$repositoryPropertyType = $this->repositoryTypeFactory->createRepositoryPropertyType($entityReferenceExpr);
$this->addPropertyToClass($class, $repositoryPropertyType, 'repository');
$genericObjectType = $this->repositoryTypeFactory->createRepositoryPropertyType($entityReferenceExpr);
$this->addPropertyToClass($class, $genericObjectType, 'repository');
}
}

View File

@ -200,7 +200,6 @@ final class ExpectedNameResolver
}
$returnedType = $this->nodeTypeResolver->getStaticType($expr);
if ($returnedType->isIterable()->no()) {
return null;
}

View File

@ -0,0 +1,78 @@
<?php
declare(strict_types=1);
namespace Rector\NetteCodeQuality\NodeAdding;
use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr\Closure;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Stmt\ClassMethod;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\NodeNestingScope\ParentScopeFinder;
use Rector\NodeTypeResolver\Node\AttributeKey;
final class FunctionLikeFirstLevelStatementResolver
{
/**
* @var ParentScopeFinder
*/
private $parentScopeFinder;
public function __construct(ParentScopeFinder $parentScopeFinder)
{
$this->parentScopeFinder = $parentScopeFinder;
}
public function resolveFirstLevelStatement(Node $node): Node
{
$multiplierClosure = $this->matchMultiplierClosure($node);
$functionLike = $multiplierClosure ?? $this->parentScopeFinder->find($node);
/** @var ClassMethod|Closure|null $functionLike */
if ($functionLike === null) {
throw new ShouldNotHappenException();
}
$currentStatement = $node->getAttribute(AttributeKey::CURRENT_STATEMENT);
if (! $currentStatement instanceof Node) {
throw new ShouldNotHappenException();
}
while (! in_array($currentStatement, (array) $functionLike->stmts, true)) {
$parent = $currentStatement->getAttribute(AttributeKey::PARENT_NODE);
if (! $parent instanceof Node) {
throw new ShouldNotHappenException();
}
$currentStatement = $parent->getAttribute(AttributeKey::CURRENT_STATEMENT);
}
return $currentStatement;
}
/**
* Form might be costructured inside private closure for multiplier
* @see https://doc.nette.org/en/3.0/multiplier
*/
private function matchMultiplierClosure(Node $node): ?Closure
{
/** @var Closure|null $closure */
$closure = $node->getAttribute(AttributeKey::CLOSURE_NODE);
if ($closure === null) {
return null;
}
$parent = $closure->getAttribute(AttributeKey::PARENT_NODE);
if (! $parent instanceof Arg) {
return null;
}
$parentParent = $parent->getAttribute(AttributeKey::PARENT_NODE);
if (! $parentParent instanceof New_) {
return null;
}
return $closure;
}
}

View File

@ -4,20 +4,16 @@ declare(strict_types=1);
namespace Rector\NetteCodeQuality\Rector\ArrayDimFetch;
use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr\ArrayDimFetch;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\Closure;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Expression;
use PHPStan\Type\ObjectType;
use Rector\BetterPhpDocParser\PhpDocManipulator\VarAnnotationManipulator;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\Rector\AbstractRector;
use Rector\NetteCodeQuality\Naming\NetteControlNaming;
use Rector\NetteCodeQuality\NodeAdding\FunctionLikeFirstLevelStatementResolver;
use Rector\NetteCodeQuality\NodeAnalyzer\ControlDimFetchAnalyzer;
use Rector\NodeTypeResolver\Node\AttributeKey;
@ -46,17 +42,24 @@ abstract class AbstractArrayDimFetchToAnnotatedControlVariableRector extends Abs
*/
private $alreadyInitializedAssignsClassMethodObjectHashes = [];
/**
* @var FunctionLikeFirstLevelStatementResolver
*/
private $functionLikeFirstLevelStatementResolver;
/**
* @required
*/
public function autowireAbstractArrayDimFetchToAnnotatedControlVariableRector(
VarAnnotationManipulator $varAnnotationManipulator,
ControlDimFetchAnalyzer $controlDimFetchAnalyzer,
NetteControlNaming $netteControlNaming
NetteControlNaming $netteControlNaming,
FunctionLikeFirstLevelStatementResolver $functionLikeFirstLevelStatementResolver
): void {
$this->controlDimFetchAnalyzer = $controlDimFetchAnalyzer;
$this->netteControlNaming = $netteControlNaming;
$this->varAnnotationManipulator = $varAnnotationManipulator;
$this->functionLikeFirstLevelStatementResolver = $functionLikeFirstLevelStatementResolver;
}
/**
@ -78,7 +81,7 @@ abstract class AbstractArrayDimFetchToAnnotatedControlVariableRector extends Abs
$assignExpression = $this->createAnnotatedAssignExpression($variableName, $arrayDimFetch, $controlObjectType);
$currentStatement = $this->getClassMethodFirstLevelStatement($arrayDimFetch);
$currentStatement = $this->functionLikeFirstLevelStatementResolver->resolveFirstLevelStatement($arrayDimFetch);
$this->addNodeBeforeNode($assignExpression, $currentStatement);
}
@ -133,33 +136,6 @@ abstract class AbstractArrayDimFetchToAnnotatedControlVariableRector extends Abs
return $assignExpression;
}
private function getClassMethodFirstLevelStatement(Node $node): Node
{
$multiplierClosure = $this->matchMultiplierClosure($node);
$functionLike = $multiplierClosure ?? $node->getAttribute(AttributeKey::METHOD_NODE);
/** @var ClassMethod|Closure|null $functionLike */
if ($functionLike === null) {
throw new ShouldNotHappenException();
}
$currentStatement = $node->getAttribute(AttributeKey::CURRENT_STATEMENT);
if (! $currentStatement instanceof Node) {
throw new ShouldNotHappenException();
}
while (! in_array($currentStatement, (array) $functionLike->stmts, true)) {
$parent = $currentStatement->getAttribute(AttributeKey::PARENT_NODE);
if (! $parent instanceof Node) {
throw new ShouldNotHappenException();
}
$currentStatement = $parent->getAttribute(AttributeKey::CURRENT_STATEMENT);
}
return $currentStatement;
}
private function createAssignExpression(string $variableName, ArrayDimFetch $arrayDimFetch): Expression
{
$variable = new Variable($variableName);
@ -168,29 +144,4 @@ abstract class AbstractArrayDimFetchToAnnotatedControlVariableRector extends Abs
return new Expression($assign);
}
/**
* Form might be costructured inside private closure for multiplier
* @see https://doc.nette.org/en/3.0/multiplier
*/
private function matchMultiplierClosure(Node $node): ?Closure
{
/** @var Closure|null $closure */
$closure = $node->getAttribute(AttributeKey::CLOSURE_NODE);
if ($closure === null) {
return null;
}
$parent = $closure->getAttribute(AttributeKey::PARENT_NODE);
if (! $parent instanceof Arg) {
return null;
}
$parentParent = $parent->getAttribute(AttributeKey::PARENT_NODE);
if (! $parentParent instanceof New_) {
return null;
}
return $closure;
}
}

View File

@ -0,0 +1,57 @@
<?php
namespace Rector\NetteCodeQuality\Tests\Rector\ArrayDimFetch\ChangeFormArrayAccessToAnnotatedControlVariableRector\Fixture;
use Nette\Application\UI\Form;
final class InOnSuccessCall
{
public function run()
{
$form = $this->makeForm();
$onSuccess = function (Form $form) {
$form['email_else']->value = 'hey@hi.hello';
};
}
public function makeForm(): Form
{
$form = new Form();
$form->addText('email_else', 'Email');
return $form;
}
}
?>
-----
<?php
namespace Rector\NetteCodeQuality\Tests\Rector\ArrayDimFetch\ChangeFormArrayAccessToAnnotatedControlVariableRector\Fixture;
use Nette\Application\UI\Form;
final class InOnSuccessCall
{
public function run()
{
$form = $this->makeForm();
$onSuccess = function (Form $form) {
/** @var \Nette\Forms\Controls\TextInput $emailElseControl */
$emailElseControl = $form['email_else'];
$emailElseControl->value = 'hey@hi.hello';
};
}
public function makeForm(): Form
{
$form = new Form();
$form->addText('email_else', 'Email');
return $form;
}
}
?>

View File

@ -26,6 +26,7 @@ use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\NetteKdyby\Naming\VariableNaming;
use Rector\NodeNestingScope\ParentScopeFinder;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\Php70\ValueObject\VariableAssignPair;
@ -46,10 +47,19 @@ final class NonVariableToVariableOnFunctionCallRector extends AbstractRector
*/
private $variableNaming;
public function __construct(CallReflectionResolver $callReflectionResolver, VariableNaming $variableNaming)
{
/**
* @var ParentScopeFinder
*/
private $parentScopeFinder;
public function __construct(
CallReflectionResolver $callReflectionResolver,
VariableNaming $variableNaming,
ParentScopeFinder $parentScopeFinder
) {
$this->callReflectionResolver = $callReflectionResolver;
$this->variableNaming = $variableNaming;
$this->parentScopeFinder = $parentScopeFinder;
}
public function getDefinition(): RectorDefinition
@ -78,7 +88,10 @@ final class NonVariableToVariableOnFunctionCallRector extends AbstractRector
return null;
}
$scopeNode = $this->resolveScopeNode($node);
$scopeNode = $this->parentScopeFinder->find($node);
if ($scopeNode === null) {
return null;
}
$currentScope = $scopeNode->getAttribute(AttributeKey::SCOPE);
if (! $currentScope instanceof MutatingScope) {
@ -151,13 +164,6 @@ final class NonVariableToVariableOnFunctionCallRector extends AbstractRector
return $arguments;
}
private function resolveScopeNode(Node $node): Node
{
return $node->getAttribute(AttributeKey::METHOD_NODE) ??
$node->getAttribute(AttributeKey::FUNCTION_NODE) ??
$node->getAttribute(AttributeKey::CLOSURE_NODE);
}
private function getReplacementsFor(Expr $expr, MutatingScope $mutatingScope, Node $scopeNode): VariableAssignPair
{
/** @var Assign|AssignOp|AssignRef $expr */

View File

@ -5,8 +5,11 @@ namespace Rector\Php70\Tests\Rector\FuncCall\NonVariableToVariableOnFunctionCall
function anonymousFunction()
{
$anonymousFunction = function (&$bar) {};
$anonymousFunction(bar());
$staticAnonymousFunction = static function (&$bar) {};
$staticAnonymousFunction(bar());
}
@ -20,9 +23,12 @@ function anonymousFunction()
{
$anonymousFunction = function (&$bar) {};
$bar = bar();
$anonymousFunction($bar);
$staticAnonymousFunction = static function (&$bar) {};
$bar2 = bar();
$staticAnonymousFunction($bar2);
}

View File

@ -117,19 +117,19 @@ final class ClassMethodExternalCallNodeAnalyzer
private function isEventSubscriberMethod(ClassMethod $classMethod, string $methodName): bool
{
$classNode = $classMethod->getAttribute(AttributeKey::CLASS_NODE);
if (! $classNode instanceof Class_) {
$classLike = $classMethod->getAttribute(AttributeKey::CLASS_NODE);
if (! $classLike instanceof Class_) {
return false;
}
if (! $this->nodeTypeResolver->isObjectType(
$classNode,
$classLike,
'Symfony\Component\EventDispatcher\EventSubscriberInterface')
) {
return false;
}
$getSubscribedEventsClassMethod = $classNode->getMethod('getSubscribedEvents');
$getSubscribedEventsClassMethod = $classLike->getMethod('getSubscribedEvents');
if ($getSubscribedEventsClassMethod === null) {
return false;
}

View File

@ -199,8 +199,8 @@ CODE_SAMPLE
}
if ($type instanceof FloatType) {
$isFloat = $this->createFuncCall('is_float', [$variable]);
return $this->createFuncCall(self::ASSERT, [$isFloat]);
$funcCall = $this->createFuncCall('is_float', [$variable]);
return $this->createFuncCall(self::ASSERT, [$funcCall]);
}
if ($type instanceof StringType) {

View File

@ -270,12 +270,12 @@ final class RectorApplication
return;
}
$oldContent = $fileInfo->getContents();
$contents = $fileInfo->getContents();
$newContent = $this->configuration->isDryRun() ? $this->fileProcessor->printToString($fileInfo)
: $this->fileProcessor->printToFile($fileInfo);
$this->errorAndDiffCollector->addFileDiff($fileInfo, $newContent, $oldContent);
$this->errorAndDiffCollector->addFileDiff($fileInfo, $newContent, $contents);
}
/**

View File

@ -325,13 +325,13 @@ final class ClassMethodAssignManipulator
return false;
}
/** @var ParameterReflection $parameter */
foreach ($parametersAcceptor->getParameters() as $parameter) {
if ($parameter->getName() !== $variableName) {
/** @var ParameterReflection $parameterReflection */
foreach ($parametersAcceptor->getParameters() as $parameterReflection) {
if ($parameterReflection->getName() !== $variableName) {
continue;
}
return $parameter->passedByReference()
return $parameterReflection->passedByReference()
->yes();
}
@ -375,13 +375,13 @@ final class ClassMethodAssignManipulator
return false;
}
/** @var ParameterReflection $parameter */
foreach ($parametersAcceptor->getParameters() as $parameterPosition => $parameter) {
/** @var ParameterReflection $parameterReflection */
foreach ($parametersAcceptor->getParameters() as $parameterPosition => $parameterReflection) {
if ($parameterPosition !== $argumentPosition) {
continue;
}
return $parameter->passedByReference()
return $parameterReflection->passedByReference()
->yes();
}

View File

@ -92,12 +92,12 @@ final class ClassMethodManipulator
return false;
}
$classNode = $classMethod->getAttribute(AttributeKey::CLASS_NODE);
if (! $classNode instanceof Class_) {
$classLike = $classMethod->getAttribute(AttributeKey::CLASS_NODE);
if (! $classLike instanceof Class_) {
return false;
}
return $classMethod->isPrivate() || (! $classNode->isFinal() && $classMethod->isProtected());
return $classMethod->isPrivate() || (! $classLike->isFinal() && $classMethod->isProtected());
}
public function hasParentMethodOrInterfaceMethod(ClassMethod $classMethod, ?string $methodName = null): bool

View File

@ -0,0 +1,91 @@
<?php
declare(strict_types=1);
namespace Rector\Core\Tests\RectorCombination\RenameAndFluent\Fixture;
use PhpParser\Node\Expr\New_;
use PHPStan\Reflection\ParameterReflection;
use Rector\Core\PHPStan\Reflection\CallReflectionResolver;
final class CyclicParameterReflection
{
/**
* @var CallReflectionResolver
*/
private $callReflectionResolver;
public function __construct(CallReflectionResolver $callReflectionResolver)
{
$this->callReflectionResolver = $callReflectionResolver;
}
private function isParameterReferencedInMethodReflection(New_ $new, int $argumentPosition): bool
{
$methodReflection = $this->callReflectionResolver->resolveConstructor($new);
$parametersAcceptor = $this->callReflectionResolver->resolveParametersAcceptor($methodReflection, $new);
if ($parametersAcceptor === null) {
return false;
}
/** @var ParameterReflection $parameter */
foreach ($parametersAcceptor->getParameters() as $parameterPosition => $parameter) {
if ($parameterPosition !== $argumentPosition) {
continue;
}
return $parameter->passedByReference()->yes();
}
return false;
}
}
?>
-----
<?php
declare(strict_types=1);
namespace Rector\Core\Tests\RectorCombination\RenameAndFluent\Fixture;
use PhpParser\Node\Expr\New_;
use PHPStan\Reflection\ParameterReflection;
use Rector\Core\PHPStan\Reflection\CallReflectionResolver;
final class CyclicParameterReflection
{
/**
* @var CallReflectionResolver
*/
private $callReflectionResolver;
public function __construct(CallReflectionResolver $callReflectionResolver)
{
$this->callReflectionResolver = $callReflectionResolver;
}
private function isParameterReferencedInMethodReflection(New_ $new, int $argumentPosition): bool
{
$methodReflection = $this->callReflectionResolver->resolveConstructor($new);
$parametersAcceptor = $this->callReflectionResolver->resolveParametersAcceptor($methodReflection, $new);
if ($parametersAcceptor === null) {
return false;
}
/** @var ParameterReflection $parameterReflection */
foreach ($parametersAcceptor->getParameters() as $parameterPosition => $parameterReflection) {
if ($parameterPosition !== $argumentPosition) {
continue;
}
return $parameterReflection->passedByReference()->yes();
}
return false;
}
}
?>

View File

@ -0,0 +1,30 @@
<?php
declare(strict_types=1);
namespace Rector\Core\Tests\RectorCombination\RenameAndFluent;
use Iterator;
use Rector\Core\Testing\PHPUnit\AbstractRectorTestCase;
use Symplify\SmartFileSystem\SmartFileInfo;
final class RenameAndFluentTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(SmartFileInfo $fileInfo): void
{
$this->doTestFileInfo($fileInfo);
}
public function provideData(): Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}
protected function provideConfigFileInfo(): ?SmartFileInfo
{
return new SmartFileInfo(__DIR__ . '/config/rename_and_fluent.php');
}
}

View File

@ -0,0 +1,13 @@
<?php
declare(strict_types=1);
use Rector\Defluent\Rector\Return_\ReturnFluentChainMethodCallToNormalMethodCallRector;
use Rector\Naming\Rector\Foreach_\RenameForeachValueVariableToMatchMethodCallReturnTypeRector;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
$services->set(ReturnFluentChainMethodCallToNormalMethodCallRector::class);
$services->set(RenameForeachValueVariableToMatchMethodCallReturnTypeRector::class);
};