From 08cec1591e87679ec082a400a18d17b8855c3156 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Thu, 22 Feb 2024 09:08:40 +0000 Subject: [PATCH] Updated Rector to commit 4951accb91a39af88d3903930112f2752e497076 https://github.com/rectorphp/rector-src/commit/4951accb91a39af88d3903930112f2752e497076 [Renaming] New Rule: RenameFunctionLikeParamWithinCallLikeArgRector (#5554) --- docs/rector_rules_overview.md | 19 +- .../Guard/BreakingVariableRenameGuard.php | 13 +- ...nctionLikeParamWithinCallLikeArgRector.php | 190 ++++++++++++++++++ ...nameFunctionLikeParamWithinCallLikeArg.php | 74 +++++++ src/Application/VersionResolver.php | 4 +- vendor/composer/autoload_classmap.php | 2 + vendor/composer/autoload_static.php | 2 + 7 files changed, 295 insertions(+), 9 deletions(-) create mode 100644 rules/Renaming/Rector/FunctionLike/RenameFunctionLikeParamWithinCallLikeArgRector.php create mode 100644 rules/Renaming/ValueObject/RenameFunctionLikeParamWithinCallLikeArg.php diff --git a/docs/rector_rules_overview.md b/docs/rector_rules_overview.md index 05a1afe8b7c..492de469499 100644 --- a/docs/rector_rules_overview.md +++ b/docs/rector_rules_overview.md @@ -1,4 +1,4 @@ -# 360 Rules Overview +# 361 Rules Overview
@@ -50,7 +50,7 @@ - [Removing](#removing) (5) -- [Renaming](#renaming) (9) +- [Renaming](#renaming) (10) - [Strict](#strict) (5) @@ -5601,6 +5601,21 @@ Replace constant by new ones
+### RenameFunctionLikeParamWithinCallLikeArgRector + +Rename param within closures and arrow functions based on use with specified method calls + +:wrench: **configure it!** + +- class: [`Rector\Renaming\Rector\FunctionLike\RenameFunctionLikeParamWithinCallLikeArgRector`](../rules/Renaming/Rector/FunctionLike/RenameFunctionLikeParamWithinCallLikeArgRector.php) + +```diff +-(new SomeClass)->process(function ($param) {}); ++(new SomeClass)->process(function ($parameter) {}); +``` + +
+ ### RenameFunctionRector Turns defined function call new one. diff --git a/rules/Naming/Guard/BreakingVariableRenameGuard.php b/rules/Naming/Guard/BreakingVariableRenameGuard.php index dd5fa21af66..987ff0b21a2 100644 --- a/rules/Naming/Guard/BreakingVariableRenameGuard.php +++ b/rules/Naming/Guard/BreakingVariableRenameGuard.php @@ -73,7 +73,7 @@ final class BreakingVariableRenameGuard $this->nodeNameResolver = $nodeNameResolver; } /** - * @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\Expr\Closure $functionLike + * @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\Expr\Closure|\PhpParser\Node\Expr\ArrowFunction $functionLike */ public function shouldSkipVariable(string $currentName, string $expectedName, $functionLike, Variable $variable) : bool { @@ -85,7 +85,7 @@ final class BreakingVariableRenameGuard if ($this->conflictingNameResolver->hasNameIsInFunctionLike($expectedName, $functionLike)) { return \true; } - if ($this->overridenExistingNamesResolver->hasNameInClassMethodForNew($currentName, $functionLike)) { + if (!$functionLike instanceof ArrowFunction && $this->overridenExistingNamesResolver->hasNameInClassMethodForNew($currentName, $functionLike)) { return \true; } if ($this->isVariableAlreadyDefined($variable, $currentName)) { @@ -94,7 +94,7 @@ final class BreakingVariableRenameGuard if ($this->hasConflictVariable($functionLike, $expectedName)) { return \true; } - return $this->isUsedInClosureUsesName($expectedName, $functionLike); + return $functionLike instanceof Closure && $this->isUsedInClosureUsesName($expectedName, $functionLike); } /** * @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\Expr\Closure|\PhpParser\Node\Expr\ArrowFunction $classMethod @@ -151,11 +151,14 @@ final class BreakingVariableRenameGuard return $trinaryLogic->maybe(); } /** - * @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\Expr\Closure $functionLike + * @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\Expr\Closure|\PhpParser\Node\Expr\ArrowFunction $functionLike */ private function hasConflictVariable($functionLike, string $newName) : bool { - return $this->betterNodeFinder->hasInstanceOfName((array) $functionLike->stmts, Variable::class, $newName); + if ($functionLike instanceof ArrowFunction) { + return $this->betterNodeFinder->hasInstanceOfName(\array_merge([$functionLike->expr], $functionLike->params), Variable::class, $newName); + } + return $this->betterNodeFinder->hasInstanceOfName(\array_merge((array) $functionLike->stmts, $functionLike->params), Variable::class, $newName); } /** * @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\Expr\Closure $functionLike diff --git a/rules/Renaming/Rector/FunctionLike/RenameFunctionLikeParamWithinCallLikeArgRector.php b/rules/Renaming/Rector/FunctionLike/RenameFunctionLikeParamWithinCallLikeArgRector.php new file mode 100644 index 00000000000..b6403de2d1e --- /dev/null +++ b/rules/Renaming/Rector/FunctionLike/RenameFunctionLikeParamWithinCallLikeArgRector.php @@ -0,0 +1,190 @@ +breakingVariableRenameGuard = $breakingVariableRenameGuard; + $this->paramRenamer = $paramRenamer; + $this->paramRenameFactory = $paramRenameFactory; + } + public function getRuleDefinition() : RuleDefinition + { + return new RuleDefinition('Rename param within closures and arrow functions based on use with specified method calls', [new ConfiguredCodeSample(<<<'CODE_SAMPLE' +(new SomeClass)->process(function ($param) {}); +CODE_SAMPLE +, <<<'CODE_SAMPLE' +(new SomeClass)->process(function ($parameter) {}); +CODE_SAMPLE +, [new RenameFunctionLikeParamWithinCallLikeArg('SomeClass', 'process', 0, 0, 'parameter')])]); + } + /** + * @return array> + */ + public function getNodeTypes() : array + { + return [MethodCall::class, StaticCall::class]; + } + /** + * @param CallLike $node + */ + public function refactor(Node $node) : ?Node + { + $hasChanged = \false; + foreach ($this->renameFunctionLikeParamWithinCallLikeArgs as $renameFunctionLikeParamWithinCallLikeArg) { + if (!$node instanceof MethodCall && !$node instanceof StaticCall) { + continue; + } + switch (\true) { + case $node instanceof MethodCall: + $type = $node->var; + break; + case $node instanceof StaticCall: + $type = $node->class; + break; + } + if (!$this->isObjectType($type, $renameFunctionLikeParamWithinCallLikeArg->getObjectType())) { + continue; + } + if (($node->name ?? null) === null) { + continue; + } + if (!$node->name instanceof Identifier) { + continue; + } + if (!$this->isName($node->name, $renameFunctionLikeParamWithinCallLikeArg->getMethodName())) { + continue; + } + $arg = $this->findArgFromMethodCall($renameFunctionLikeParamWithinCallLikeArg, $node); + $functionLike = ($nullsafeVariable1 = $arg) ? $nullsafeVariable1->value : null; + if (!$arg instanceof Arg) { + continue; + } + if (!$functionLike instanceof FunctionLike) { + continue; + } + $param = $this->findParameterFromArg($arg, $renameFunctionLikeParamWithinCallLikeArg); + if (!$param instanceof Param) { + continue; + } + if (!$param->var instanceof Variable) { + continue; + } + if (($functionLike instanceof Closure || $functionLike instanceof ArrowFunction) && $this->breakingVariableRenameGuard->shouldSkipVariable((string) $this->nodeNameResolver->getName($param->var), $renameFunctionLikeParamWithinCallLikeArg->getNewParamName(), $functionLike, $param->var)) { + continue; + } + $paramRename = $this->paramRenameFactory->createFromResolvedExpectedName($functionLike, $param, $renameFunctionLikeParamWithinCallLikeArg->getNewParamName()); + if (!$paramRename instanceof ParamRename) { + continue; + } + $this->paramRenamer->rename($paramRename); + $hasChanged = \true; + } + if (!$hasChanged) { + return null; + } + return $node; + } + /** + * @param RenameFunctionLikeParamWithinCallLikeArg[] $configuration + */ + public function configure(array $configuration) : void + { + Assert::allIsAOf($configuration, RenameFunctionLikeParamWithinCallLikeArg::class); + $this->renameFunctionLikeParamWithinCallLikeArgs = $configuration; + } + public function findParameterFromArg(Arg $arg, RenameFunctionLikeParamWithinCallLikeArg $renameFunctionLikeParamWithinCallLikeArg) : ?Param + { + $functionLike = $arg->value; + if (!$functionLike instanceof FunctionLike) { + return null; + } + return $functionLike->params[$renameFunctionLikeParamWithinCallLikeArg->getFunctionLikePosition()] ?? null; + } + private function findArgFromMethodCall(RenameFunctionLikeParamWithinCallLikeArg $renameFunctionLikeParamWithinCallLikeArg, CallLike $callLike) : ?Arg + { + if (\is_int($renameFunctionLikeParamWithinCallLikeArg->getCallLikePosition())) { + $arg = $this->processPositionalArg($callLike, $renameFunctionLikeParamWithinCallLikeArg); + } else { + $arg = $this->processNamedArg($callLike, $renameFunctionLikeParamWithinCallLikeArg); + } + return $arg; + } + private function processPositionalArg(CallLike $callLike, RenameFunctionLikeParamWithinCallLikeArg $renameFunctionLikeParamWithinCallLikeArg) : ?Arg + { + if ($callLike->isFirstClassCallable()) { + return null; + } + if ($callLike->getArgs() === []) { + return null; + } + $arg = $callLike->args[$renameFunctionLikeParamWithinCallLikeArg->getCallLikePosition()] ?? null; + if (!$arg instanceof Arg) { + return null; + } + // int positions shouldn't have names + if ($arg->name !== null) { + return null; + } + return $arg; + } + private function processNamedArg(CallLike $callLike, RenameFunctionLikeParamWithinCallLikeArg $renameFunctionLikeParamWithinCallLikeArg) : ?Arg + { + $args = \array_filter($callLike->getArgs(), static function (Arg $arg) use($renameFunctionLikeParamWithinCallLikeArg) : bool { + if ($arg->name === null) { + return \false; + } + return $arg->name->name === $renameFunctionLikeParamWithinCallLikeArg->getCallLikePosition(); + }); + if ($args === []) { + return null; + } + return \array_values($args)[0]; + } +} diff --git a/rules/Renaming/ValueObject/RenameFunctionLikeParamWithinCallLikeArg.php b/rules/Renaming/ValueObject/RenameFunctionLikeParamWithinCallLikeArg.php new file mode 100644 index 00000000000..71b28ae217a --- /dev/null +++ b/rules/Renaming/ValueObject/RenameFunctionLikeParamWithinCallLikeArg.php @@ -0,0 +1,74 @@ +|string + * @readonly + */ + private $callLikePosition; + /** + * @var int<0, max> + * @readonly + */ + private $functionLikePosition; + /** + * @readonly + * @var string + */ + private $newParamName; + /** + * @param int<0, max>|string $callLikePosition + * @param int<0, max> $functionLikePosition + */ + public function __construct(string $className, string $methodName, $callLikePosition, int $functionLikePosition, string $newParamName) + { + $this->className = $className; + $this->methodName = $methodName; + $this->callLikePosition = $callLikePosition; + $this->functionLikePosition = $functionLikePosition; + $this->newParamName = $newParamName; + RectorAssert::className($className); + } + public function getObjectType() : ObjectType + { + return new ObjectType($this->className); + } + public function getMethodName() : string + { + return $this->methodName; + } + /** + * @return int<0, max>|string + */ + public function getCallLikePosition() + { + return $this->callLikePosition; + } + /** + * @return int<0, max> + */ + public function getFunctionLikePosition() : int + { + return $this->functionLikePosition; + } + public function getNewParamName() : string + { + return $this->newParamName; + } +} diff --git a/src/Application/VersionResolver.php b/src/Application/VersionResolver.php index 477c8f23680..1f06d0c33c1 100644 --- a/src/Application/VersionResolver.php +++ b/src/Application/VersionResolver.php @@ -19,12 +19,12 @@ final class VersionResolver * @api * @var string */ - public const PACKAGE_VERSION = 'f9b3312035a4e5baee7105b19715d057587e1f59'; + public const PACKAGE_VERSION = '4951accb91a39af88d3903930112f2752e497076'; /** * @api * @var string */ - public const RELEASE_DATE = '2024-02-22 15:43:48'; + public const RELEASE_DATE = '2024-02-22 10:06:22'; /** * @var int */ diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index 08468bfc4d7..531eeb20f40 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -2023,6 +2023,7 @@ return array( 'Rector\\Renaming\\Rector\\ClassMethod\\RenameAnnotationRector' => $baseDir . '/rules/Renaming/Rector/ClassMethod/RenameAnnotationRector.php', 'Rector\\Renaming\\Rector\\ConstFetch\\RenameConstantRector' => $baseDir . '/rules/Renaming/Rector/ConstFetch/RenameConstantRector.php', 'Rector\\Renaming\\Rector\\FuncCall\\RenameFunctionRector' => $baseDir . '/rules/Renaming/Rector/FuncCall/RenameFunctionRector.php', + 'Rector\\Renaming\\Rector\\FunctionLike\\RenameFunctionLikeParamWithinCallLikeArgRector' => $baseDir . '/rules/Renaming/Rector/FunctionLike/RenameFunctionLikeParamWithinCallLikeArgRector.php', 'Rector\\Renaming\\Rector\\MethodCall\\RenameMethodRector' => $baseDir . '/rules/Renaming/Rector/MethodCall/RenameMethodRector.php', 'Rector\\Renaming\\Rector\\Name\\RenameClassRector' => $baseDir . '/rules/Renaming/Rector/Name/RenameClassRector.php', 'Rector\\Renaming\\Rector\\PropertyFetch\\RenamePropertyRector' => $baseDir . '/rules/Renaming/Rector/PropertyFetch/RenamePropertyRector.php', @@ -2034,6 +2035,7 @@ return array( 'Rector\\Renaming\\ValueObject\\RenameAnnotationByType' => $baseDir . '/rules/Renaming/ValueObject/RenameAnnotationByType.php', 'Rector\\Renaming\\ValueObject\\RenameClassAndConstFetch' => $baseDir . '/rules/Renaming/ValueObject/RenameClassAndConstFetch.php', 'Rector\\Renaming\\ValueObject\\RenameClassConstFetch' => $baseDir . '/rules/Renaming/ValueObject/RenameClassConstFetch.php', + 'Rector\\Renaming\\ValueObject\\RenameFunctionLikeParamWithinCallLikeArg' => $baseDir . '/rules/Renaming/ValueObject/RenameFunctionLikeParamWithinCallLikeArg.php', 'Rector\\Renaming\\ValueObject\\RenameProperty' => $baseDir . '/rules/Renaming/ValueObject/RenameProperty.php', 'Rector\\Renaming\\ValueObject\\RenameStaticMethod' => $baseDir . '/rules/Renaming/ValueObject/RenameStaticMethod.php', 'Rector\\Set\\Contract\\SetListInterface' => $baseDir . '/src/Set/Contract/SetListInterface.php', diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index bd519ac65de..53f4b5b35b8 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -2242,6 +2242,7 @@ class ComposerStaticInit2d887a2f87c676eb32b3e04612865e54 'Rector\\Renaming\\Rector\\ClassMethod\\RenameAnnotationRector' => __DIR__ . '/../..' . '/rules/Renaming/Rector/ClassMethod/RenameAnnotationRector.php', 'Rector\\Renaming\\Rector\\ConstFetch\\RenameConstantRector' => __DIR__ . '/../..' . '/rules/Renaming/Rector/ConstFetch/RenameConstantRector.php', 'Rector\\Renaming\\Rector\\FuncCall\\RenameFunctionRector' => __DIR__ . '/../..' . '/rules/Renaming/Rector/FuncCall/RenameFunctionRector.php', + 'Rector\\Renaming\\Rector\\FunctionLike\\RenameFunctionLikeParamWithinCallLikeArgRector' => __DIR__ . '/../..' . '/rules/Renaming/Rector/FunctionLike/RenameFunctionLikeParamWithinCallLikeArgRector.php', 'Rector\\Renaming\\Rector\\MethodCall\\RenameMethodRector' => __DIR__ . '/../..' . '/rules/Renaming/Rector/MethodCall/RenameMethodRector.php', 'Rector\\Renaming\\Rector\\Name\\RenameClassRector' => __DIR__ . '/../..' . '/rules/Renaming/Rector/Name/RenameClassRector.php', 'Rector\\Renaming\\Rector\\PropertyFetch\\RenamePropertyRector' => __DIR__ . '/../..' . '/rules/Renaming/Rector/PropertyFetch/RenamePropertyRector.php', @@ -2253,6 +2254,7 @@ class ComposerStaticInit2d887a2f87c676eb32b3e04612865e54 'Rector\\Renaming\\ValueObject\\RenameAnnotationByType' => __DIR__ . '/../..' . '/rules/Renaming/ValueObject/RenameAnnotationByType.php', 'Rector\\Renaming\\ValueObject\\RenameClassAndConstFetch' => __DIR__ . '/../..' . '/rules/Renaming/ValueObject/RenameClassAndConstFetch.php', 'Rector\\Renaming\\ValueObject\\RenameClassConstFetch' => __DIR__ . '/../..' . '/rules/Renaming/ValueObject/RenameClassConstFetch.php', + 'Rector\\Renaming\\ValueObject\\RenameFunctionLikeParamWithinCallLikeArg' => __DIR__ . '/../..' . '/rules/Renaming/ValueObject/RenameFunctionLikeParamWithinCallLikeArg.php', 'Rector\\Renaming\\ValueObject\\RenameProperty' => __DIR__ . '/../..' . '/rules/Renaming/ValueObject/RenameProperty.php', 'Rector\\Renaming\\ValueObject\\RenameStaticMethod' => __DIR__ . '/../..' . '/rules/Renaming/ValueObject/RenameStaticMethod.php', 'Rector\\Set\\Contract\\SetListInterface' => __DIR__ . '/../..' . '/src/Set/Contract/SetListInterface.php',