Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\KnownMagicClassMethodTypeRector\Fixture;

final class CallStaticMethod
{
public function __callStatic($method, $args)
{
}
}

?>
-----
<?php

namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\KnownMagicClassMethodTypeRector\Fixture;

final class CallStaticMethod
{
public function __callStatic(string $method, array $args)
{
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\KnownMagicClassMethodTypeRector\Fixture;

final class GetAndSet
{
public function __get($method)
{
}

public function __set($method, $args)
{
}
}

?>
-----
<?php

namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\KnownMagicClassMethodTypeRector\Fixture;

final class GetAndSet
{
public function __get(string $method)
{
}

public function __set(string $method, mixed $args)
{
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\KnownMagicClassMethodTypeRector\Fixture;

final class IssetUnset
{
public function __isset($key): bool
{
return true;
}

public function __unset($key): void
{
}
}

?>
-----
<?php

namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\KnownMagicClassMethodTypeRector\Fixture;

final class IssetUnset
{
public function __isset(string $key): bool
{
return true;
}

public function __unset(string $key): void
{
}
}

?>
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +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]);
->withRules([KnownMagicClassMethodTypeRector::class])
->withPhpVersion(PhpVersionFeature::MIXED_TYPE);
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@
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;
use Rector\ValueObject\PhpVersionFeature;
use Rector\VendorLocker\ParentClassMethodTypeOverrideGuard;
use Rector\VersionBonding\Contract\MinPhpVersionInterface;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;

Expand All @@ -19,12 +22,15 @@
*
* @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
){
private readonly ParentClassMethodTypeOverrideGuard $parentClassMethodTypeOverrideGuard,
private readonly PhpVersionProvider $phpVersionProvider,
) {

}

public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition(
Expand Down Expand Up @@ -73,24 +79,45 @@ public function refactor(Node $node): ?Node
continue;
}

if (! $this->isName($classMethod, MethodName::CALL)) {
continue;
}

if ($this->parentClassMethodTypeOverrideGuard->hasParentClassMethod($classMethod)) {
return null;
}

$firstParam = $classMethod->getParams()[0];
if (! $firstParam->type instanceof Node) {
$firstParam->type = new Identifier('string');
$hasChanged = true;
if ($this->isNames($classMethod, [MethodName::CALL, MethodName::CALL_STATIC])) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By this change, the parent guard can't early return null, as check match method name moved after, I will create new parent to move below here, or use continue instead.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created PR for check parent with other method to continue on it:

$secondParam = $classMethod->getParams()[1];
if (! $secondParam->type instanceof Node) {
$secondParam->type = new Name('array');
$hasChanged = true;
}
}

$secondParam = $classMethod->getParams()[1];
if (! $secondParam->type instanceof Node) {
$secondParam->type = new Name('array');
$hasChanged = true;
// 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->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;
}
}
}

Expand All @@ -100,4 +127,9 @@ public function refactor(Node $node): ?Node

return null;
}

public function provideMinPhpVersion(): int
{
return PhpVersionFeature::SCALAR_TYPES;
}
}
10 changes: 10 additions & 0 deletions src/ValueObject/MethodName.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ final class MethodName
*/
public const CALL = '__call';

/**
* @var string
*/
public const CALL_STATIC = '__callStatic';

/**
* @var string
*/
Expand All @@ -72,4 +77,9 @@ final class MethodName
* @var string
*/
public const ISSET = '__isset';

/**
* @var string
*/
public const UNSET = '__unset';
}