diff --git a/rules-tests/Php81/Rector/FuncCall/NullToStrictStringFuncCallArgRector/Fixture/skip_string_casted.php.inc b/rules-tests/Php81/Rector/FuncCall/NullToStrictStringFuncCallArgRector/Fixture/skip_string_casted.php.inc new file mode 100644 index 00000000000..4b4ab63caa2 --- /dev/null +++ b/rules-tests/Php81/Rector/FuncCall/NullToStrictStringFuncCallArgRector/Fixture/skip_string_casted.php.inc @@ -0,0 +1,16 @@ + +----- + diff --git a/rules/Php81/NodeManipulator/NullToStrictStringIntConverter.php b/rules/Php81/NodeManipulator/NullToStrictStringIntConverter.php index f58ebeadf61..fcdd417d65f 100644 --- a/rules/Php81/NodeManipulator/NullToStrictStringIntConverter.php +++ b/rules/Php81/NodeManipulator/NullToStrictStringIntConverter.php @@ -24,6 +24,7 @@ use PHPStan\Type\Type; use PHPStan\Type\UnionType; use Rector\NodeAnalyzer\PropertyFetchAnalyzer; +use Rector\NodeTypeResolver\Node\AttributeKey; use Rector\NodeTypeResolver\NodeTypeResolver; use Rector\PhpParser\Node\Value\ValueResolver; @@ -53,12 +54,18 @@ public function convertIfNull( } $argValue = $args[$position]->value; + if ($this->valueResolver->isNull($argValue)) { $args[$position]->value = $targetType === 'string' ? new String_('') : new Int_(0); $funcCall->args = $args; return $funcCall; } + // skip (string) ternary conditions with both values + if ($this->isStringCastedTernaryOfMixedTypes($argValue, $scope)) { + return null; + } + if ($this->shouldSkipValue($argValue, $scope, $isTrait, $targetType)) { return null; } @@ -72,6 +79,7 @@ public function convertIfNull( } if ($argValue instanceof Ternary && ! $this->shouldSkipValue($argValue->else, $scope, $isTrait, $targetType)) { + if ($this->valueResolver->isNull($argValue->else)) { $argValue->else = $targetType === 'string' ? new String_('') : new Int_(0); } else { @@ -81,12 +89,27 @@ public function convertIfNull( } $args[$position]->value = $argValue; - $funcCall->args = $args; + return $funcCall; } - $args[$position]->value = $targetType === 'string' ? new CastString_($argValue) : new CastInt_($argValue); - $funcCall->args = $args; + $wrapInParentheses = false; + if ($argValue instanceof Ternary && $argValue->cond instanceof CastString_) { + $wrapInParentheses = true; + } + + if ($targetType === 'string') { + $castedType = new CastString_($argValue); + } else { + $castedType = new CastInt_($argValue); + } + + if ($wrapInParentheses) { + $argValue->setAttribute(AttributeKey::WRAPPED_IN_PARENTHESES, true); + } + + $args[$position]->value = $castedType; + return $funcCall; } @@ -221,4 +244,23 @@ private function isPossibleArrayVariableName(Type $passedType, Type $reflectionP return false; } + + private function isStringCastedTernaryOfMixedTypes(Expr $expr, Scope $scope): bool + { + if (! $expr instanceof Ternary) { + return false; + } + + if (! $expr->cond instanceof CastString_) { + return false; + } + + if (! $expr->if instanceof Expr) { + return false; + } + + $ifType = $scope->getType($expr->if); + $elseType = $scope->getType($expr->else); + return $ifType instanceof MixedType || $elseType instanceof MixedType; + } }