From dac05e6206ba4878e35c395eba805979c7c5363c Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Sat, 4 Oct 2025 18:34:22 +0200 Subject: [PATCH 1/4] add scalar types condition --- .../ClassMethod/KnownMagicClassMethodTypeRector.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/rules/TypeDeclaration/Rector/ClassMethod/KnownMagicClassMethodTypeRector.php b/rules/TypeDeclaration/Rector/ClassMethod/KnownMagicClassMethodTypeRector.php index 7917e871b23..a352764071b 100644 --- a/rules/TypeDeclaration/Rector/ClassMethod/KnownMagicClassMethodTypeRector.php +++ b/rules/TypeDeclaration/Rector/ClassMethod/KnownMagicClassMethodTypeRector.php @@ -10,7 +10,12 @@ use PhpParser\Node\Stmt\Class_; use Rector\Rector\AbstractRector; use Rector\ValueObject\MethodName; +<<<<<<< HEAD use Rector\VendorLocker\ParentClassMethodTypeOverrideGuard; +======= +use Rector\ValueObject\PhpVersionFeature; +use Rector\VersionBonding\Contract\MinPhpVersionInterface; +>>>>>>> 971356b355 (add scalar types condition) use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; @@ -19,7 +24,7 @@ * * @see https://www.php.net/manual/en/language.oop5.overloading.php#object.call */ -final class KnownMagicClassMethodTypeRector extends AbstractRector +final class KnownMagicClassMethodTypeRector extends AbstractRector implements MinPhpVersionInterface { public function __construct( private readonly ParentClassMethodTypeOverrideGuard $parentClassMethodTypeOverrideGuard @@ -100,4 +105,9 @@ public function refactor(Node $node): ?Node return null; } + + public function provideMinPhpVersion(): int + { + return PhpVersionFeature::SCALAR_TYPES; + } } From 3ffe8017a4a82cfee0adc47779a2fd6f593ab4b9 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Sat, 4 Oct 2025 18:43:03 +0200 Subject: [PATCH 2/4] add call static support, set and get --- .../Fixture/call_static_method.php.inc | 25 +++++++++++ .../Fixture/get_and_set.php.inc | 33 +++++++++++++++ .../KnownMagicClassMethodTypeRector.php | 42 +++++++++++++++++++ src/ValueObject/MethodName.php | 5 +++ 4 files changed, 105 insertions(+) create mode 100644 rules-tests/TypeDeclaration/Rector/ClassMethod/KnownMagicClassMethodTypeRector/Fixture/call_static_method.php.inc create mode 100644 rules-tests/TypeDeclaration/Rector/ClassMethod/KnownMagicClassMethodTypeRector/Fixture/get_and_set.php.inc diff --git a/rules-tests/TypeDeclaration/Rector/ClassMethod/KnownMagicClassMethodTypeRector/Fixture/call_static_method.php.inc b/rules-tests/TypeDeclaration/Rector/ClassMethod/KnownMagicClassMethodTypeRector/Fixture/call_static_method.php.inc new file mode 100644 index 00000000000..56d58471ac4 --- /dev/null +++ b/rules-tests/TypeDeclaration/Rector/ClassMethod/KnownMagicClassMethodTypeRector/Fixture/call_static_method.php.inc @@ -0,0 +1,25 @@ + +----- + diff --git a/rules-tests/TypeDeclaration/Rector/ClassMethod/KnownMagicClassMethodTypeRector/Fixture/get_and_set.php.inc b/rules-tests/TypeDeclaration/Rector/ClassMethod/KnownMagicClassMethodTypeRector/Fixture/get_and_set.php.inc new file mode 100644 index 00000000000..d93ec6f791c --- /dev/null +++ b/rules-tests/TypeDeclaration/Rector/ClassMethod/KnownMagicClassMethodTypeRector/Fixture/get_and_set.php.inc @@ -0,0 +1,33 @@ + +----- + diff --git a/rules/TypeDeclaration/Rector/ClassMethod/KnownMagicClassMethodTypeRector.php b/rules/TypeDeclaration/Rector/ClassMethod/KnownMagicClassMethodTypeRector.php index a352764071b..9a5377340b0 100644 --- a/rules/TypeDeclaration/Rector/ClassMethod/KnownMagicClassMethodTypeRector.php +++ b/rules/TypeDeclaration/Rector/ClassMethod/KnownMagicClassMethodTypeRector.php @@ -8,6 +8,7 @@ use PhpParser\Node\Identifier; use PhpParser\Node\Name; use PhpParser\Node\Stmt\Class_; +use Rector\Php\PhpVersionProvider; use Rector\Rector\AbstractRector; use Rector\ValueObject\MethodName; <<<<<<< HEAD @@ -27,9 +28,17 @@ final class KnownMagicClassMethodTypeRector extends AbstractRector implements MinPhpVersionInterface { public function __construct( +<<<<<<< HEAD private readonly ParentClassMethodTypeOverrideGuard $parentClassMethodTypeOverrideGuard ){ } +======= + private readonly PhpVersionProvider $phpVersionProvider + ) { + + } + +>>>>>>> 3a091179f1 (add call static support, set and get) public function getRuleDefinition(): RuleDefinition { return new RuleDefinition( @@ -78,9 +87,18 @@ public function refactor(Node $node): ?Node continue; } +<<<<<<< HEAD if (! $this->isName($classMethod, MethodName::CALL)) { continue; } +======= + if ($this->isNames($classMethod, [MethodName::CALL, MethodName::CALL_STATIC])) { + $firstParam = $classMethod->getParams()[0]; + if (! $firstParam->type instanceof Node) { + $firstParam->type = new Identifier('string'); + $hasChanged = true; + } +>>>>>>> 3a091179f1 (add call static support, set and get) if ($this->parentClassMethodTypeOverrideGuard->hasParentClassMethod($classMethod)) { return null; @@ -97,6 +115,30 @@ public function refactor(Node $node): ?Node $secondParam->type = new Name('array'); $hasChanged = true; } + + if ($this->isName($classMethod, MethodName::__GET)) { + $firstParam = $classMethod->getParams()[0]; + if (! $firstParam->type instanceof Node) { + $firstParam->type = new Identifier('string'); + $hasChanged = true; + } + } + + if ($this->isName($classMethod, MethodName::__SET)) { + $firstParam = $classMethod->getParams()[0]; + if (! $firstParam->type instanceof Node) { + $firstParam->type = new Identifier('string'); + $hasChanged = true; + } + + if ($this->phpVersionProvider->isAtLeastPhpVersion(PhpVersionFeature::MIXED_TYPE)) { + $secondParam = $classMethod->getParams()[1]; + if (! $secondParam->type instanceof Node) { + $secondParam->type = new Identifier('mixed'); + $hasChanged = true; + } + } + } } if ($hasChanged) { diff --git a/src/ValueObject/MethodName.php b/src/ValueObject/MethodName.php index 64352c4724e..00b40f04112 100644 --- a/src/ValueObject/MethodName.php +++ b/src/ValueObject/MethodName.php @@ -58,6 +58,11 @@ final class MethodName */ public const CALL = '__call'; + /** + * @var string + */ + public const CALL_STATIC = '__callStatic'; + /** * @var string */ From addfd97368b5767031c765a992c9e3b1e1ae2611 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Sat, 4 Oct 2025 19:40:09 +0200 Subject: [PATCH 3/4] add isset/unset keys --- .../Fixture/isset_unset.php.inc | 35 +++++++++ .../config/configured_rule.php | 3 +- .../KnownMagicClassMethodTypeRector.php | 74 +++++++------------ src/ValueObject/MethodName.php | 5 ++ 4 files changed, 69 insertions(+), 48 deletions(-) create mode 100644 rules-tests/TypeDeclaration/Rector/ClassMethod/KnownMagicClassMethodTypeRector/Fixture/isset_unset.php.inc diff --git a/rules-tests/TypeDeclaration/Rector/ClassMethod/KnownMagicClassMethodTypeRector/Fixture/isset_unset.php.inc b/rules-tests/TypeDeclaration/Rector/ClassMethod/KnownMagicClassMethodTypeRector/Fixture/isset_unset.php.inc new file mode 100644 index 00000000000..15894cb6271 --- /dev/null +++ b/rules-tests/TypeDeclaration/Rector/ClassMethod/KnownMagicClassMethodTypeRector/Fixture/isset_unset.php.inc @@ -0,0 +1,35 @@ + +----- + diff --git a/rules-tests/TypeDeclaration/Rector/ClassMethod/KnownMagicClassMethodTypeRector/config/configured_rule.php b/rules-tests/TypeDeclaration/Rector/ClassMethod/KnownMagicClassMethodTypeRector/config/configured_rule.php index bc7d6210ac2..f804b2d0893 100644 --- a/rules-tests/TypeDeclaration/Rector/ClassMethod/KnownMagicClassMethodTypeRector/config/configured_rule.php +++ b/rules-tests/TypeDeclaration/Rector/ClassMethod/KnownMagicClassMethodTypeRector/config/configured_rule.php @@ -6,4 +6,5 @@ use Rector\TypeDeclaration\Rector\ClassMethod\KnownMagicClassMethodTypeRector; return RectorConfig::configure() - ->withRules([KnownMagicClassMethodTypeRector::class]); + ->withRules([KnownMagicClassMethodTypeRector::class]) + ->withPhpVersion(\Rector\ValueObject\PhpVersionFeature::MIXED_TYPE); diff --git a/rules/TypeDeclaration/Rector/ClassMethod/KnownMagicClassMethodTypeRector.php b/rules/TypeDeclaration/Rector/ClassMethod/KnownMagicClassMethodTypeRector.php index 9a5377340b0..5121f11721c 100644 --- a/rules/TypeDeclaration/Rector/ClassMethod/KnownMagicClassMethodTypeRector.php +++ b/rules/TypeDeclaration/Rector/ClassMethod/KnownMagicClassMethodTypeRector.php @@ -11,12 +11,9 @@ use Rector\Php\PhpVersionProvider; use Rector\Rector\AbstractRector; use Rector\ValueObject\MethodName; -<<<<<<< HEAD -use Rector\VendorLocker\ParentClassMethodTypeOverrideGuard; -======= use Rector\ValueObject\PhpVersionFeature; +use Rector\VendorLocker\ParentClassMethodTypeOverrideGuard; use Rector\VersionBonding\Contract\MinPhpVersionInterface; ->>>>>>> 971356b355 (add scalar types condition) use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; @@ -28,17 +25,12 @@ final class KnownMagicClassMethodTypeRector extends AbstractRector implements MinPhpVersionInterface { public function __construct( -<<<<<<< HEAD - private readonly ParentClassMethodTypeOverrideGuard $parentClassMethodTypeOverrideGuard - ){ - } -======= - private readonly PhpVersionProvider $phpVersionProvider + private readonly ParentClassMethodTypeOverrideGuard $parentClassMethodTypeOverrideGuard, + private readonly PhpVersionProvider $phpVersionProvider, ) { } ->>>>>>> 3a091179f1 (add call static support, set and get) public function getRuleDefinition(): RuleDefinition { return new RuleDefinition( @@ -87,56 +79,44 @@ public function refactor(Node $node): ?Node continue; } -<<<<<<< HEAD - if (! $this->isName($classMethod, MethodName::CALL)) { - continue; - } -======= - if ($this->isNames($classMethod, [MethodName::CALL, MethodName::CALL_STATIC])) { - $firstParam = $classMethod->getParams()[0]; - if (! $firstParam->type instanceof Node) { - $firstParam->type = new Identifier('string'); - $hasChanged = true; - } ->>>>>>> 3a091179f1 (add call static support, set and get) - if ($this->parentClassMethodTypeOverrideGuard->hasParentClassMethod($classMethod)) { return null; } - $firstParam = $classMethod->getParams()[0]; - if (! $firstParam->type instanceof Node) { - $firstParam->type = new Identifier('string'); - $hasChanged = true; - } - - $secondParam = $classMethod->getParams()[1]; - if (! $secondParam->type instanceof Node) { - $secondParam->type = new Name('array'); - $hasChanged = true; - } - - if ($this->isName($classMethod, MethodName::__GET)) { - $firstParam = $classMethod->getParams()[0]; - if (! $firstParam->type instanceof Node) { - $firstParam->type = new Identifier('string'); + if ($this->isNames($classMethod, [MethodName::CALL, MethodName::CALL_STATIC])) { + $secondParam = $classMethod->getParams()[1]; + if (! $secondParam->type instanceof Node) { + $secondParam->type = new Name('array'); $hasChanged = true; } } - if ($this->isName($classMethod, MethodName::__SET)) { + // first arg string + if ($this->isNames( + $classMethod, + [ + MethodName::CALL, + MethodName::CALL_STATIC, + MethodName::__SET, + MethodName::__GET, + MethodName::ISSET, + MethodName::UNSET, + ] + )) { $firstParam = $classMethod->getParams()[0]; if (! $firstParam->type instanceof Node) { $firstParam->type = new Identifier('string'); $hasChanged = true; } + } - if ($this->phpVersionProvider->isAtLeastPhpVersion(PhpVersionFeature::MIXED_TYPE)) { - $secondParam = $classMethod->getParams()[1]; - if (! $secondParam->type instanceof Node) { - $secondParam->type = new Identifier('mixed'); - $hasChanged = true; - } + if ($this->isName($classMethod, MethodName::__SET) && $this->phpVersionProvider->isAtLeastPhpVersion( + PhpVersionFeature::MIXED_TYPE + )) { + $secondParam = $classMethod->getParams()[1]; + if (! $secondParam->type instanceof Node) { + $secondParam->type = new Identifier('mixed'); + $hasChanged = true; } } } diff --git a/src/ValueObject/MethodName.php b/src/ValueObject/MethodName.php index 00b40f04112..357507b6508 100644 --- a/src/ValueObject/MethodName.php +++ b/src/ValueObject/MethodName.php @@ -77,4 +77,9 @@ final class MethodName * @var string */ public const ISSET = '__isset'; + + /** + * @var string + */ + public const UNSET = '__unset'; } From d6ec2dd7a69ba645a80c95813564ccba5fa2aa0e Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Sat, 4 Oct 2025 17:50:27 +0000 Subject: [PATCH 4/4] [ci-review] Rector Rectify --- .../KnownMagicClassMethodTypeRector/config/configured_rule.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rules-tests/TypeDeclaration/Rector/ClassMethod/KnownMagicClassMethodTypeRector/config/configured_rule.php b/rules-tests/TypeDeclaration/Rector/ClassMethod/KnownMagicClassMethodTypeRector/config/configured_rule.php index f804b2d0893..93c7de5d39f 100644 --- a/rules-tests/TypeDeclaration/Rector/ClassMethod/KnownMagicClassMethodTypeRector/config/configured_rule.php +++ b/rules-tests/TypeDeclaration/Rector/ClassMethod/KnownMagicClassMethodTypeRector/config/configured_rule.php @@ -2,9 +2,10 @@ declare(strict_types=1); +use Rector\ValueObject\PhpVersionFeature; use Rector\Config\RectorConfig; use Rector\TypeDeclaration\Rector\ClassMethod\KnownMagicClassMethodTypeRector; return RectorConfig::configure() ->withRules([KnownMagicClassMethodTypeRector::class]) - ->withPhpVersion(\Rector\ValueObject\PhpVersionFeature::MIXED_TYPE); + ->withPhpVersion(PhpVersionFeature::MIXED_TYPE);