mirror of
https://github.com/rectorphp/rector.git
synced 2025-01-19 06:18:07 +01:00
[CodingStyle] Add CallUserFuncToMethodCallRector (#6328)
This commit is contained in:
parent
68ed4d9b2d
commit
745a7a9739
@ -68,6 +68,8 @@ use Rector\CodeQuality\Rector\Ternary\SimplifyDuplicatedTernaryRector;
|
||||
use Rector\CodeQuality\Rector\Ternary\SimplifyTautologyTernaryRector;
|
||||
use Rector\CodeQuality\Rector\Ternary\SwitchNegatedTernaryRector;
|
||||
use Rector\CodeQuality\Rector\Ternary\UnnecessaryTernaryExpressionRector;
|
||||
use Rector\CodingStyle\Rector\ClassMethod\FuncGetArgsToVariadicParamRector;
|
||||
use Rector\CodingStyle\Rector\FuncCall\CallUserFuncToMethodCallRector;
|
||||
use Rector\Php52\Rector\Property\VarToPublicPropertyRector;
|
||||
use Rector\Php71\Rector\FuncCall\RemoveExtraParametersRector;
|
||||
use Rector\Renaming\Rector\FuncCall\RenameFunctionRector;
|
||||
@ -171,5 +173,6 @@ return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services->set(SingularSwitchToIfRector::class);
|
||||
$services->set(SimplifyIfNullableReturnRector::class);
|
||||
$services->set(NarrowUnionTypeDocRector::class);
|
||||
$services->set(\Rector\CodingStyle\Rector\ClassMethod\FuncGetArgsToVariadicParamRector::class);
|
||||
$services->set(FuncGetArgsToVariadicParamRector::class);
|
||||
$services->set(CallUserFuncToMethodCallRector::class);
|
||||
};
|
||||
|
@ -15,7 +15,7 @@ use Rector\CodingStyle\Rector\ClassMethod\RemoveDoubleUnderscoreInMethodNameRect
|
||||
use Rector\CodingStyle\Rector\ClassMethod\UnSpreadOperatorRector;
|
||||
use Rector\CodingStyle\Rector\Encapsed\EncapsedStringsToSprintfRector;
|
||||
use Rector\CodingStyle\Rector\Encapsed\WrapEncapsedVariableInCurlyBracesRector;
|
||||
use Rector\CodingStyle\Rector\FuncCall\CallUserFuncCallToVariadicRector;
|
||||
use Rector\CodingStyle\Rector\FuncCall\CallUserFuncArrayToVariadicRector;
|
||||
use Rector\CodingStyle\Rector\FuncCall\ConsistentImplodeRector;
|
||||
use Rector\CodingStyle\Rector\FuncCall\ConsistentPregDelimiterRector;
|
||||
use Rector\CodingStyle\Rector\FuncCall\VersionCompareFuncCallToConstantRector;
|
||||
@ -60,7 +60,7 @@ return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services->set(AddArrayDefaultToArrayPropertyRector::class);
|
||||
$services->set(AddFalseDefaultToBoolPropertyRector::class);
|
||||
$services->set(MakeInheritedMethodVisibilitySameAsParentRector::class);
|
||||
$services->set(CallUserFuncCallToVariadicRector::class);
|
||||
$services->set(CallUserFuncArrayToVariadicRector::class);
|
||||
$services->set(VersionCompareFuncCallToConstantRector::class);
|
||||
$services->set(UseMessageVariableForSprintfInSymfonyStyleRector::class);
|
||||
|
||||
|
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\CodingStyle\Rector\FuncCall\CallUserFuncArrayToVariadicRector;
|
||||
|
||||
use Iterator;
|
||||
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
|
||||
final class CallUserFuncArrayToVariadicRectorTest extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider provideData()
|
||||
*/
|
||||
public function test(SmartFileInfo $fileInfo): void
|
||||
{
|
||||
$this->doTestFileInfo($fileInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Iterator<SmartFileInfo>
|
||||
*/
|
||||
public function provideData(): Iterator
|
||||
{
|
||||
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
|
||||
}
|
||||
|
||||
public function provideConfigFilePath(): string
|
||||
{
|
||||
return __DIR__ . '/config/configured_rule.php';
|
||||
}
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\CodingStyle\Rector\FuncCall\CallUserFuncCallToVariadicRector\Fixture;
|
||||
namespace Rector\Tests\CodingStyle\Rector\FuncCall\CallUserFuncArrayToVariadicRector\Fixture;
|
||||
|
||||
use Rector\Tests\CodingStyle\Rector\FuncCall\CallUserFuncCallToVariadicRector\Source\Redirector;
|
||||
use Rector\Tests\CodingStyle\Rector\FuncCall\CallUserFuncArrayToVariadicRector\Source\Redirector;
|
||||
|
||||
final class ArrayLocalMethod
|
||||
{
|
||||
@ -24,9 +24,9 @@ final class ArrayLocalMethod
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\CodingStyle\Rector\FuncCall\CallUserFuncCallToVariadicRector\Fixture;
|
||||
namespace Rector\Tests\CodingStyle\Rector\FuncCall\CallUserFuncArrayToVariadicRector\Fixture;
|
||||
|
||||
use Rector\Tests\CodingStyle\Rector\FuncCall\CallUserFuncCallToVariadicRector\Source\Redirector;
|
||||
use Rector\Tests\CodingStyle\Rector\FuncCall\CallUserFuncArrayToVariadicRector\Source\Redirector;
|
||||
|
||||
final class ArrayLocalMethod
|
||||
{
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\CodingStyle\Rector\FuncCall\CallUserFuncCallToVariadicRector\Fixture;
|
||||
namespace Rector\Tests\CodingStyle\Rector\FuncCall\CallUserFuncArrayToVariadicRector\Fixture;
|
||||
|
||||
use Rector\Tests\CodingStyle\Rector\FuncCall\CallUserFuncCallToVariadicRector\Source\Redirector;
|
||||
use Rector\Tests\CodingStyle\Rector\FuncCall\CallUserFuncArrayToVariadicRector\Source\Redirector;
|
||||
|
||||
final class ArrayLocalMethodWithReference
|
||||
{
|
||||
@ -24,9 +24,9 @@ final class ArrayLocalMethodWithReference
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\CodingStyle\Rector\FuncCall\CallUserFuncCallToVariadicRector\Fixture;
|
||||
namespace Rector\Tests\CodingStyle\Rector\FuncCall\CallUserFuncArrayToVariadicRector\Fixture;
|
||||
|
||||
use Rector\Tests\CodingStyle\Rector\FuncCall\CallUserFuncCallToVariadicRector\Source\Redirector;
|
||||
use Rector\Tests\CodingStyle\Rector\FuncCall\CallUserFuncArrayToVariadicRector\Source\Redirector;
|
||||
|
||||
final class ArrayLocalMethodWithReference
|
||||
{
|
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\CodingStyle\Rector\FuncCall\CallUserFuncCallToVariadicRector\Fixture;
|
||||
namespace Rector\Tests\CodingStyle\Rector\FuncCall\CallUserFuncArrayToVariadicRector\Fixture;
|
||||
|
||||
class Fixture
|
||||
{
|
||||
@ -14,7 +14,7 @@ class Fixture
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\CodingStyle\Rector\FuncCall\CallUserFuncCallToVariadicRector\Fixture;
|
||||
namespace Rector\Tests\CodingStyle\Rector\FuncCall\CallUserFuncArrayToVariadicRector\Fixture;
|
||||
|
||||
class Fixture
|
||||
{
|
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\CodingStyle\Rector\FuncCall\CallUserFuncCallToVariadicRector\Fixture;
|
||||
namespace Rector\Tests\CodingStyle\Rector\FuncCall\CallUserFuncArrayToVariadicRector\Fixture;
|
||||
|
||||
class SkipUnknownValue
|
||||
{
|
@ -2,7 +2,7 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\CodingStyle\Rector\FuncCall\CallUserFuncCallToVariadicRector\Source;
|
||||
namespace Rector\Tests\CodingStyle\Rector\FuncCall\CallUserFuncArrayToVariadicRector\Source;
|
||||
|
||||
final class Redirector
|
||||
{
|
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Rector\CodingStyle\Rector\FuncCall\CallUserFuncArrayToVariadicRector;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
|
||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services = $containerConfigurator->services();
|
||||
$services->set(CallUserFuncArrayToVariadicRector::class);
|
||||
};
|
@ -2,13 +2,13 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\CodingStyle\Rector\FuncCall\CallUserFuncCallToVariadicRector;
|
||||
namespace Rector\Tests\CodingStyle\Rector\FuncCall\CallUserFuncToMethodCallRector;
|
||||
|
||||
use Iterator;
|
||||
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
|
||||
final class CallUserFuncCallToVariadicRectorTest extends AbstractRectorTestCase
|
||||
final class CallUserFuncToMethodCallRectorTest extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider provideData()
|
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\CodingStyle\Rector\FuncCall\CallUserFuncToMethodCallRector\Fixture;
|
||||
|
||||
final class SkipStringArray
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$result = \call_user_func(['some', 'method'], $args);
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\CodingStyle\Rector\FuncCall\CallUserFuncToMethodCallRector\Fixture;
|
||||
|
||||
final class SomeClass
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$result = \call_user_func([$this->property, 'method'], $args);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\CodingStyle\Rector\FuncCall\CallUserFuncToMethodCallRector\Fixture;
|
||||
|
||||
final class SomeClass
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$result = $this->property->method($args);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -2,10 +2,11 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Rector\CodingStyle\Rector\FuncCall\CallUserFuncCallToVariadicRector;
|
||||
use Rector\CodingStyle\Rector\FuncCall\CallUserFuncToMethodCallRector;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
|
||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services = $containerConfigurator->services();
|
||||
$services->set(CallUserFuncCallToVariadicRector::class);
|
||||
$services->set(CallUserFuncToMethodCallRector::class);
|
||||
};
|
@ -7,7 +7,7 @@ function getRand()
|
||||
return rand(1,100);
|
||||
}
|
||||
|
||||
class FuncCall
|
||||
class SomeFuncCall
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
@ -26,7 +26,7 @@ function getRand()
|
||||
return rand(1,100);
|
||||
}
|
||||
|
||||
class FuncCall
|
||||
class SomeFuncCall
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
@ -40,4 +40,4 @@ class FuncCall
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
?>
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace Rector\Tests\DowngradePhp71\Rector\String_\DowngradeNegativeStringOffsetToStrlenRector\Fixture;
|
||||
|
||||
class PropertyFetch
|
||||
final class SomePropertyFetch
|
||||
{
|
||||
private $var;
|
||||
|
||||
@ -19,7 +19,7 @@ class PropertyFetch
|
||||
|
||||
namespace Rector\Tests\DowngradePhp71\Rector\String_\DowngradeNegativeStringOffsetToStrlenRector\Fixture;
|
||||
|
||||
class PropertyFetch
|
||||
final class SomePropertyFetch
|
||||
{
|
||||
private $var;
|
||||
|
||||
|
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\CodingStyle\NodeFactory;
|
||||
|
||||
use PhpParser\Node\Expr\Array_;
|
||||
use PhpParser\Node\Expr\ArrayItem;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Expr\PropertyFetch;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use PhpParser\Node\Scalar\String_;
|
||||
|
||||
final class ArrayCallableToMethodCallFactory
|
||||
{
|
||||
public function create(Array_ $array): ?MethodCall
|
||||
{
|
||||
if (count($array->items) !== 2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$firstItem = $array->items[0];
|
||||
$secondItem = $array->items[1];
|
||||
|
||||
if (! $firstItem instanceof ArrayItem) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! $secondItem instanceof ArrayItem) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! $secondItem->value instanceof String_) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! $firstItem->value instanceof PropertyFetch && ! $firstItem->value instanceof Variable) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$string = $secondItem->value;
|
||||
$methodName = $string->value;
|
||||
|
||||
return new MethodCall($firstItem->value, $methodName);
|
||||
}
|
||||
}
|
@ -8,11 +8,10 @@ use PhpParser\Node;
|
||||
use PhpParser\Node\Arg;
|
||||
use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Expr\Array_;
|
||||
use PhpParser\Node\Expr\ArrayItem;
|
||||
use PhpParser\Node\Expr\FuncCall;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Expr\PropertyFetch;
|
||||
use PhpParser\Node\Scalar\String_;
|
||||
use Rector\CodingStyle\NodeFactory\ArrayCallableToMethodCallFactory;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Core\ValueObject\PhpVersionFeature;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
@ -22,13 +21,23 @@ use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
* @changelog https://www.php.net/manual/en/function.call-user-func-array.php#117655
|
||||
* @changelog https://3v4l.org/CBWt9
|
||||
*
|
||||
* @see \Rector\Tests\CodingStyle\Rector\FuncCall\CallUserFuncCallToVariadicRector\CallUserFuncCallToVariadicRectorTest
|
||||
* @see \Rector\Tests\CodingStyle\Rector\FuncCall\CallUserFuncArrayToVariadicRector\CallUserFuncArrayToVariadicRectorTest
|
||||
*/
|
||||
final class CallUserFuncCallToVariadicRector extends AbstractRector
|
||||
final class CallUserFuncArrayToVariadicRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @var ArrayCallableToMethodCallFactory
|
||||
*/
|
||||
private $arrayCallableToMethodCallFactory;
|
||||
|
||||
public function __construct(ArrayCallableToMethodCallFactory $arrayCallableToMethodCallFactory)
|
||||
{
|
||||
$this->arrayCallableToMethodCallFactory = $arrayCallableToMethodCallFactory;
|
||||
}
|
||||
|
||||
public function getRuleDefinition(): RuleDefinition
|
||||
{
|
||||
return new RuleDefinition('Replace call_user_func_call with variadic', [
|
||||
return new RuleDefinition('Replace call_user_func_array() with variadic', [
|
||||
new CodeSample(
|
||||
<<<'CODE_SAMPLE'
|
||||
class SomeClass
|
||||
@ -100,34 +109,13 @@ CODE_SAMPLE
|
||||
|
||||
private function createMethodCall(Array_ $array, Expr $secondExpr): ?MethodCall
|
||||
{
|
||||
if (count($array->items) !== 2) {
|
||||
$methodCall = $this->arrayCallableToMethodCallFactory->create($array);
|
||||
if (! $methodCall instanceof MethodCall) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$firstItem = $array->items[0];
|
||||
$secondItem = $array->items[1];
|
||||
|
||||
if (! $firstItem instanceof ArrayItem) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! $secondItem instanceof ArrayItem) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($firstItem->value instanceof PropertyFetch) {
|
||||
if (! $secondItem->value instanceof String_) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$string = $secondItem->value;
|
||||
$methodName = $string->value;
|
||||
|
||||
$arg = $this->createUnpackedArg($secondExpr);
|
||||
return new MethodCall($firstItem->value, $methodName, [$arg]);
|
||||
}
|
||||
|
||||
return null;
|
||||
$methodCall->args[] = $this->createUnpackedArg($secondExpr);
|
||||
return $methodCall;
|
||||
}
|
||||
|
||||
private function createUnpackedArg(Expr $expr): Arg
|
@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\CodingStyle\Rector\FuncCall;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\Array_;
|
||||
use PhpParser\Node\Expr\FuncCall;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use Rector\CodingStyle\NodeFactory\ArrayCallableToMethodCallFactory;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
|
||||
/**
|
||||
* @changelog https://stackoverflow.com/a/1596250/1348344
|
||||
*
|
||||
* @see \Rector\Tests\CodingStyle\Rector\FuncCall\CallUserFuncToMethodCallRector\CallUserFuncToMethodCallRectorTest
|
||||
*/
|
||||
final class CallUserFuncToMethodCallRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @var ArrayCallableToMethodCallFactory
|
||||
*/
|
||||
private $arrayCallableToMethodCallFactory;
|
||||
|
||||
public function __construct(ArrayCallableToMethodCallFactory $arrayCallableToMethodCallFactory)
|
||||
{
|
||||
$this->arrayCallableToMethodCallFactory = $arrayCallableToMethodCallFactory;
|
||||
}
|
||||
|
||||
public function getRuleDefinition(): RuleDefinition
|
||||
{
|
||||
return new RuleDefinition('Refactor call_user_func() on known class method to a method call', [
|
||||
new CodeSample(
|
||||
<<<'CODE_SAMPLE'
|
||||
final class SomeClass
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$result = \call_user_func([$this->property, 'method'], $args);
|
||||
}
|
||||
}
|
||||
CODE_SAMPLE
|
||||
|
||||
,
|
||||
<<<'CODE_SAMPLE'
|
||||
final class SomeClass
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$result = $this->property->method($args);
|
||||
}
|
||||
}
|
||||
CODE_SAMPLE
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<class-string<Node>>
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [FuncCall::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FuncCall $node
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
if (! $this->isName($node, 'call_user_func')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$firstArgValue = $node->args[0]->value;
|
||||
if (! $firstArgValue instanceof Array_) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$methodCall = $this->arrayCallableToMethodCallFactory->create($firstArgValue);
|
||||
if (! $methodCall instanceof MethodCall) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$originalArgs = $node->args;
|
||||
unset($originalArgs[0]);
|
||||
|
||||
$methodCall->args = $originalArgs;
|
||||
return $methodCall;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user