From c49acecae551bb34dd0a1c8e540b851cb58a4a4b Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 16 May 2026 20:34:24 +0000 Subject: [PATCH] [Php81] Skip NullToStrictStringFuncCallArgRector for magic __get() property access resolving to ErrorType Fixes https://github.com/rectorphp/rector/issues/9762 --- ...ic_get_property_in_if_truthy_check.php.inc | 23 ++++++++++++++++ .../NullToStrictStringIntConverter.php | 26 +++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 rules-tests/Php81/Rector/FuncCall/NullToStrictStringFuncCallArgRector/Fixture/skip_magic_get_property_in_if_truthy_check.php.inc diff --git a/rules-tests/Php81/Rector/FuncCall/NullToStrictStringFuncCallArgRector/Fixture/skip_magic_get_property_in_if_truthy_check.php.inc b/rules-tests/Php81/Rector/FuncCall/NullToStrictStringFuncCallArgRector/Fixture/skip_magic_get_property_in_if_truthy_check.php.inc new file mode 100644 index 00000000000..ad80f49af5b --- /dev/null +++ b/rules-tests/Php81/Rector/FuncCall/NullToStrictStringFuncCallArgRector/Fixture/skip_magic_get_property_in_if_truthy_check.php.inc @@ -0,0 +1,23 @@ +_fields[$field])) { + $value = &$this->_fields[$field]; + } + + return $value; + } +} + +$entity = new EntityWithMagicGet(); +if ($entity->someProp) { + preg_replace('/\r\n|\n|\r/', '', $entity->someProp); +} diff --git a/rules/Php81/NodeManipulator/NullToStrictStringIntConverter.php b/rules/Php81/NodeManipulator/NullToStrictStringIntConverter.php index 43dc0f1f1b1..75c982b3cc8 100644 --- a/rules/Php81/NodeManipulator/NullToStrictStringIntConverter.php +++ b/rules/Php81/NodeManipulator/NullToStrictStringIntConverter.php @@ -10,6 +10,7 @@ use PhpParser\Node\Expr\Cast\String_ as CastString_; use PhpParser\Node\Expr\FuncCall; use PhpParser\Node\Expr\MethodCall; +use PhpParser\Node\Expr\PropertyFetch; use PhpParser\Node\Expr\Ternary; use PhpParser\Node\Expr\Variable; use PhpParser\Node\Scalar\Int_; @@ -19,9 +20,11 @@ use PHPStan\Analyser\Scope; use PHPStan\Reflection\Native\ExtendedNativeParameterReflection; use PHPStan\Reflection\ParametersAcceptor; +use PHPStan\Reflection\ReflectionProvider; use PHPStan\Type\ErrorType; use PHPStan\Type\MixedType; use PHPStan\Type\NullType; +use PHPStan\Type\ObjectType; use PHPStan\Type\Type; use PHPStan\Type\UnionType; use Rector\NodeAnalyzer\PropertyFetchAnalyzer; @@ -35,6 +38,7 @@ public function __construct( private ValueResolver $valueResolver, private NodeTypeResolver $nodeTypeResolver, private PropertyFetchAnalyzer $propertyFetchAnalyzer, + private ReflectionProvider $reflectionProvider, ) { } @@ -116,6 +120,10 @@ public function convertIfNull( private function shouldSkipValue(Expr $expr, Scope $scope, bool $isTrait, string $targetType): bool { + if ($this->isPropertyFetchOnClassWithMagicGet($expr)) { + return true; + } + $type = $this->nodeTypeResolver->getType($expr); if ($type->isString()->yes() && $targetType === 'string') { return true; @@ -153,6 +161,24 @@ private function shouldSkipValue(Expr $expr, Scope $scope, bool $isTrait, string return $this->shouldSkipTrait($expr, $type, $isTrait); } + private function isPropertyFetchOnClassWithMagicGet(Expr $expr): bool + { + if (! $expr instanceof PropertyFetch) { + return false; + } + + $varType = $this->nodeTypeResolver->getType($expr->var); + if (! $varType instanceof ObjectType) { + return false; + } + + if (! $this->reflectionProvider->hasClass($varType->getClassName())) { + return false; + } + + return $this->reflectionProvider->getClass($varType->getClassName())->hasMethod('__get'); + } + private function isValidUnionType(Type $type): bool { if (! $type instanceof UnionType) {