diff --git a/rules-tests/CodeQuality/Rector/MethodCall/ScalarArgumentToExpectedParamTypeRector/Fixture/skip_not_match_position_named_argument.php.inc b/rules-tests/CodeQuality/Rector/MethodCall/ScalarArgumentToExpectedParamTypeRector/Fixture/skip_not_match_position_named_argument.php.inc new file mode 100644 index 00000000..f4cffc22 --- /dev/null +++ b/rules-tests/CodeQuality/Rector/MethodCall/ScalarArgumentToExpectedParamTypeRector/Fixture/skip_not_match_position_named_argument.php.inc @@ -0,0 +1,18 @@ +methodParametersAndReturnTypesResolver->resolveCallParameterTypes($node); + $callParameterNames = $this->methodParametersAndReturnTypesResolver->resolveCallParameterNames($node); foreach ($node->getArgs() as $key => $arg) { if (! $arg->value instanceof Scalar) { @@ -108,6 +110,16 @@ public function refactor(Node $node): ?Node } $knownParameterType = $callParameterTypes[$key] ?? null; + if ($arg->name instanceof Identifier) { + $argName = $arg->name->toString(); + foreach ($callParameterNames as $keyParameterNames => $callParameterName) { + if ($argName === $callParameterName) { + $knownParameterType = $callParameterTypes[$keyParameterNames] ?? null; + break; + } + } + } + if (! $knownParameterType instanceof Type) { continue; } diff --git a/rules/CodeQuality/Reflection/MethodParametersAndReturnTypesResolver.php b/rules/CodeQuality/Reflection/MethodParametersAndReturnTypesResolver.php index 261b7c9e..00afac20 100644 --- a/rules/CodeQuality/Reflection/MethodParametersAndReturnTypesResolver.php +++ b/rules/CodeQuality/Reflection/MethodParametersAndReturnTypesResolver.php @@ -89,6 +89,35 @@ public function resolveCallParameterTypes(MethodCall|StaticCall $call): ?array return $this->resolveParameterTypes($extendedMethodReflection, $classReflection); } + /** + * @return string[] + */ + public function resolveCallParameterNames(MethodCall|StaticCall $call): array + { + if (! $call->name instanceof Identifier) { + return []; + } + + $methodName = $call->name->toString(); + + $callerType = $this->nodeTypeResolver->getType($call instanceof MethodCall ? $call->var : $call->class); + if (! $callerType instanceof ObjectType) { + return []; + } + + $classReflection = $callerType->getClassReflection(); + if (! $classReflection instanceof ClassReflection) { + return []; + } + + if (! $classReflection->hasNativeMethod($methodName)) { + return []; + } + + $extendedMethodReflection = $classReflection->getNativeMethod($methodName); + return $this->resolveParameterNames($extendedMethodReflection); + } + /** * @return Type[] */ @@ -115,6 +144,23 @@ public function resolveParameterTypes( return $parameterTypes; } + /** + * @return string[] + */ + private function resolveParameterNames(ExtendedMethodReflection $extendedMethodReflection): array + { + $extendedParametersAcceptor = ParametersAcceptorSelector::combineAcceptors( + $extendedMethodReflection->getVariants() + ); + + $parameterNames = []; + foreach ($extendedParametersAcceptor->getParameters() as $parameterReflection) { + $parameterNames[] = $parameterReflection->getName(); + } + + return $parameterNames; + } + private function resolveObjectType(Type $type): ObjectType|Type { if ($type instanceof ObjectType) {