diff --git a/rules-tests/Php81/Rector/FuncCall/NullToStrictStringFuncCallArgRector/Fixture/skip_preg_replace.php.inc b/rules-tests/Php81/Rector/FuncCall/NullToStrictStringFuncCallArgRector/Fixture/skip_preg_replace.php.inc new file mode 100644 index 00000000000..400752bdede --- /dev/null +++ b/rules-tests/Php81/Rector/FuncCall/NullToStrictStringFuncCallArgRector/Fixture/skip_preg_replace.php.inc @@ -0,0 +1,13 @@ +getParameters()[$position] ?? null; - if ($parameter instanceof ExtendedNativeParameterReflection && $parameter->getType() instanceof UnionType) { - $parameterType = $parameter->getType(); + $parameterReflection = $parametersAcceptor->getParameters()[$position] ?? null; + if ($parameterReflection instanceof ExtendedNativeParameterReflection && $parameterReflection->getType() instanceof UnionType) { + $parameterType = $parameterReflection->getType(); if (! $this->isValidUnionType($parameterType)) { return null; } @@ -109,6 +110,10 @@ private function shouldSkipValue(Expr $expr, Scope $scope, bool $isTrait, string return true; } + if ($this->isPossibleArrayVariableName($type, $nativeType, $expr)) { + return true; + } + if ($this->shouldSkipType($type)) { return true; } @@ -193,4 +198,27 @@ private function isAnErrorType(Expr $expr, Type $type, Scope $scope): bool && ! $type->isExplicitMixed() && $type->getSubtractedType() instanceof NullType; } + + /** + * @see https://github.com/rectorphp/rector/issues/9447 for context + */ + private function isPossibleArrayVariableName(Type $passedType, Type $reflectionParamType, Expr $expr): bool + { + // could mixed, resp. array, no need to (string) cast array + if (! $passedType instanceof MixedType) { + return false; + } + + if (! $reflectionParamType->isArray()->maybe()) { + return false; + } + + if ($expr instanceof Variable && is_string($expr->name)) { + $variableName = $expr->name; + // most likely plural variable + return strlen($variableName) > 3 && str_ends_with($variableName, 's'); + } + + return false; + } } diff --git a/rules/Php81/Rector/FuncCall/NullToStrictStringFuncCallArgRector.php b/rules/Php81/Rector/FuncCall/NullToStrictStringFuncCallArgRector.php index 7b115dc6d2b..5a41f2cb531 100644 --- a/rules/Php81/Rector/FuncCall/NullToStrictStringFuncCallArgRector.php +++ b/rules/Php81/Rector/FuncCall/NullToStrictStringFuncCallArgRector.php @@ -87,7 +87,7 @@ public function refactor(Node $node): ?Node } $args = $node->getArgs(); - $positions = $this->resolvePositions($node, $args, $scope); + $positions = $this->resolveStringPositions($node, $args, $scope); if ($positions === []) { return null; @@ -133,9 +133,9 @@ public function provideMinPhpVersion(): int /** * @param Arg[] $args - * @return int[]|string[] + * @return int[] */ - private function resolvePositions(FuncCall $funcCall, array $args, Scope $scope): array + private function resolveStringPositions(FuncCall $funcCall, array $args, Scope $scope): array { $positions = [];