mirror of
https://github.com/rectorphp/rector.git
synced 2024-06-03 18:00:50 +00:00
[Transform] Remove specific custom Rector without generic usage (#573)
This commit is contained in:
parent
4d816080ee
commit
e3ce320151
|
@ -1,39 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\RemovingStatic\Rector\Class_\PHPUnitStaticToKernelTestCaseGetRector\Fixture;
|
||||
|
||||
use Rector\Tests\RemovingStatic\Rector\Class_\PHPUnitStaticToKernelTestCaseGetRector\Source\ClassWithStaticMethods;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class SomeTest extends TestCase
|
||||
{
|
||||
public function test()
|
||||
{
|
||||
ClassWithStaticMethods::create('product');
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\RemovingStatic\Rector\Class_\PHPUnitStaticToKernelTestCaseGetRector\Fixture;
|
||||
|
||||
use Rector\Tests\RemovingStatic\Rector\Class_\PHPUnitStaticToKernelTestCaseGetRector\Source\ClassWithStaticMethods;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class SomeTest extends \Symfony\Bundle\FrameworkBundle\Test\KernelTestCase
|
||||
{
|
||||
private \Rector\Tests\RemovingStatic\Rector\Class_\PHPUnitStaticToKernelTestCaseGetRector\Source\ClassWithStaticMethods $classWithStaticMethods;
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->classWithStaticMethods = self::$container->get(\Rector\Tests\RemovingStatic\Rector\Class_\PHPUnitStaticToKernelTestCaseGetRector\Source\ClassWithStaticMethods::class);
|
||||
}
|
||||
public function test()
|
||||
{
|
||||
$this->classWithStaticMethods->create('product');
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,56 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\RemovingStatic\Rector\Class_\PHPUnitStaticToKernelTestCaseGetRector\Fixture;
|
||||
|
||||
use Rector\Tests\RemovingStatic\Rector\Class_\PHPUnitStaticToKernelTestCaseGetRector\Source\ClassWithStaticMethods;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class SetupAlreadyExistsTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $legitimation;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->legitimation = 'GO';
|
||||
}
|
||||
|
||||
public function test()
|
||||
{
|
||||
ClassWithStaticMethods::create('product');
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\RemovingStatic\Rector\Class_\PHPUnitStaticToKernelTestCaseGetRector\Fixture;
|
||||
|
||||
use Rector\Tests\RemovingStatic\Rector\Class_\PHPUnitStaticToKernelTestCaseGetRector\Source\ClassWithStaticMethods;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class SetupAlreadyExistsTest extends \Symfony\Bundle\FrameworkBundle\Test\KernelTestCase
|
||||
{
|
||||
private \Rector\Tests\RemovingStatic\Rector\Class_\PHPUnitStaticToKernelTestCaseGetRector\Source\ClassWithStaticMethods $classWithStaticMethods;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $legitimation;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$this->classWithStaticMethods = self::$container->get(\Rector\Tests\RemovingStatic\Rector\Class_\PHPUnitStaticToKernelTestCaseGetRector\Source\ClassWithStaticMethods::class);
|
||||
$this->legitimation = 'GO';
|
||||
}
|
||||
|
||||
public function test()
|
||||
{
|
||||
$this->classWithStaticMethods->create('product');
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,59 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\RemovingStatic\Rector\Class_\PHPUnitStaticToKernelTestCaseGetRector\Fixture;
|
||||
|
||||
use Rector\Tests\RemovingStatic\Rector\Class_\PHPUnitStaticToKernelTestCaseGetRector\Source\ClassWithStaticMethods;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class SetupAlreadyExistsWithParentSetUpTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $legitimation;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->legitimation = 'GO';
|
||||
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
public function test()
|
||||
{
|
||||
ClassWithStaticMethods::create('product');
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\RemovingStatic\Rector\Class_\PHPUnitStaticToKernelTestCaseGetRector\Fixture;
|
||||
|
||||
use Rector\Tests\RemovingStatic\Rector\Class_\PHPUnitStaticToKernelTestCaseGetRector\Source\ClassWithStaticMethods;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class SetupAlreadyExistsWithParentSetUpTest extends \Symfony\Bundle\FrameworkBundle\Test\KernelTestCase
|
||||
{
|
||||
private \Rector\Tests\RemovingStatic\Rector\Class_\PHPUnitStaticToKernelTestCaseGetRector\Source\ClassWithStaticMethods $classWithStaticMethods;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $legitimation;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->legitimation = 'GO';
|
||||
|
||||
parent::setUp();
|
||||
$this->classWithStaticMethods = self::$container->get(\Rector\Tests\RemovingStatic\Rector\Class_\PHPUnitStaticToKernelTestCaseGetRector\Source\ClassWithStaticMethods::class);
|
||||
}
|
||||
|
||||
public function test()
|
||||
{
|
||||
$this->classWithStaticMethods->create('product');
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,33 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\RemovingStatic\Rector\Class_\PHPUnitStaticToKernelTestCaseGetRector;
|
||||
|
||||
use Iterator;
|
||||
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
|
||||
final class PHPUnitStaticToKernelTestCaseGetRectorTest 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,13 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\RemovingStatic\Rector\Class_\PHPUnitStaticToKernelTestCaseGetRector\Source;
|
||||
|
||||
final class ClassWithStaticMethods
|
||||
{
|
||||
public static function create($value)
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Rector\RemovingStatic\Rector\Class_\PHPUnitStaticToKernelTestCaseGetRector;
|
||||
use Rector\Tests\RemovingStatic\Rector\Class_\PHPUnitStaticToKernelTestCaseGetRector\Source\ClassWithStaticMethods;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
|
||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services = $containerConfigurator->services();
|
||||
$services->set(PHPUnitStaticToKernelTestCaseGetRector::class)
|
||||
->call('configure', [[
|
||||
PHPUnitStaticToKernelTestCaseGetRector::STATIC_CLASS_TYPES => [ClassWithStaticMethods::class],
|
||||
]]);
|
||||
};
|
|
@ -1,31 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\Transform\Rector\Expression\MethodCallToReturnRector\Fixture;
|
||||
|
||||
use Rector\Tests\Transform\Rector\Expression\MethodCallToReturnRector\Source\ReturnDeny;
|
||||
|
||||
class SomeClass
|
||||
{
|
||||
public function run(ReturnDeny $returnDeny)
|
||||
{
|
||||
$returnDeny->deny();
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\Transform\Rector\Expression\MethodCallToReturnRector\Fixture;
|
||||
|
||||
use Rector\Tests\Transform\Rector\Expression\MethodCallToReturnRector\Source\ReturnDeny;
|
||||
|
||||
class SomeClass
|
||||
{
|
||||
public function run(ReturnDeny $returnDeny)
|
||||
{
|
||||
return $returnDeny->deny();
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,20 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\Transform\Rector\Expression\MethodCallToReturnRector\Fixture;
|
||||
|
||||
use Rector\Tests\Transform\Rector\Expression\MethodCallToReturnRector\Source\ReturnDeny;
|
||||
|
||||
class SkipAlreadyReturn
|
||||
{
|
||||
public function run(ReturnDeny $returnDeny)
|
||||
{
|
||||
return $returnDeny->deny();
|
||||
}
|
||||
|
||||
public function whatIf(ReturnDeny $returnDeny)
|
||||
{
|
||||
if (true) {
|
||||
return $returnDeny->deny();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\Transform\Rector\Expression\MethodCallToReturnRector;
|
||||
|
||||
use Iterator;
|
||||
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
|
||||
final class MethodCallToReturnRectorTest 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,13 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\Transform\Rector\Expression\MethodCallToReturnRector\Source;
|
||||
|
||||
final class ReturnDeny
|
||||
{
|
||||
public function deny()
|
||||
{
|
||||
return 'error';
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Rector\Tests\Transform\Rector\Expression\MethodCallToReturnRector\Source\ReturnDeny;
|
||||
use Rector\Transform\Rector\Expression\MethodCallToReturnRector;
|
||||
use Rector\Transform\ValueObject\MethodCallToReturn;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
use Symplify\SymfonyPhpConfig\ValueObjectInliner;
|
||||
|
||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services = $containerConfigurator->services();
|
||||
$services->set(MethodCallToReturnRector::class)
|
||||
->call('configure', [[
|
||||
MethodCallToReturnRector::METHOD_CALL_WRAPS => ValueObjectInliner::inline([
|
||||
new MethodCallToReturn(ReturnDeny::class, 'deny'),
|
||||
]),
|
||||
]]);
|
||||
};
|
|
@ -1,24 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\Transform\Rector\FileWithoutNamespace\FunctionToStaticMethodRector\Fixture;
|
||||
|
||||
function first_static_function()
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
|
||||
$value = first_static_function();
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\Transform\Rector\FileWithoutNamespace\FunctionToStaticMethodRector\Fixture;
|
||||
|
||||
$value = \StaticFunctions::firstStaticFunction();
|
||||
|
||||
?>
|
|
@ -1,42 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\Transform\Rector\FileWithoutNamespace\FunctionToStaticMethodRector;
|
||||
|
||||
use Iterator;
|
||||
use Nette\Utils\FileSystem;
|
||||
use Rector\FileSystemRector\ValueObject\AddedFileWithContent;
|
||||
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
|
||||
final class FunctionToStaticMethodRectorTest extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider provideData()
|
||||
*/
|
||||
public function test(SmartFileInfo $smartFileInfo): void
|
||||
{
|
||||
$this->doTestFileInfo($smartFileInfo);
|
||||
|
||||
$addedFileWithContent = new AddedFileWithContent(
|
||||
$this->originalTempFileInfo->getRealPathDirectory() . '/StaticFunctions.php',
|
||||
FileSystem::read(__DIR__ . '/Source/ExpectedStaticFunctions.php')
|
||||
);
|
||||
|
||||
$this->assertFileWasAdded($addedFileWithContent);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Iterator<SmartFileInfo>
|
||||
*/
|
||||
public function provideData(): Iterator
|
||||
{
|
||||
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
|
||||
}
|
||||
|
||||
public function provideConfigFilePath(): string
|
||||
{
|
||||
return __DIR__ . '/config/configured_rule.php';
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\Transform\Rector\FileWithoutNamespace\FunctionToStaticMethodRector\Fixture;
|
||||
|
||||
final class StaticFunctions
|
||||
{
|
||||
public static function firstStaticFunction()
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Rector\Transform\Rector\FileWithoutNamespace\FunctionToStaticMethodRector;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
|
||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services = $containerConfigurator->services();
|
||||
$services->set(FunctionToStaticMethodRector::class);
|
||||
};
|
|
@ -1,30 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\Transform\Rector\MethodCall\VariableMethodCallToServiceCallRector\Fixture;
|
||||
|
||||
class SomeClass
|
||||
{
|
||||
public function run(\PhpParser\Node $node)
|
||||
{
|
||||
$phpDocInfo = $node->getAttribute('php_doc_info');
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\Transform\Rector\MethodCall\VariableMethodCallToServiceCallRector\Fixture;
|
||||
|
||||
class SomeClass
|
||||
{
|
||||
public function __construct(private \Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory $phpDocInfoFactory)
|
||||
{
|
||||
}
|
||||
public function run(\PhpParser\Node $node)
|
||||
{
|
||||
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,33 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\Transform\Rector\MethodCall\VariableMethodCallToServiceCallRector;
|
||||
|
||||
use Iterator;
|
||||
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
|
||||
final class VariableMethodCallToServiceCallRectorTest 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,30 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Rector\Transform\Rector\MethodCall\VariableMethodCallToServiceCallRector;
|
||||
use Rector\Transform\ValueObject\VariableMethodCallToServiceCall;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
use Symplify\SymfonyPhpConfig\ValueObjectInliner;
|
||||
|
||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services = $containerConfigurator->services();
|
||||
|
||||
$configuration = ValueObjectInliner::inline([
|
||||
new VariableMethodCallToServiceCall(
|
||||
'PhpParser\Node',
|
||||
'getAttribute',
|
||||
'php_doc_info',
|
||||
'Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory',
|
||||
'createFromNodeOrEmpty'
|
||||
),
|
||||
]);
|
||||
|
||||
$services->set(VariableMethodCallToServiceCallRector::class)
|
||||
->call(
|
||||
'configure',
|
||||
[[
|
||||
VariableMethodCallToServiceCallRector::VARIABLE_METHOD_CALLS_TO_SERVICE_CALLS => $configuration,
|
||||
]]
|
||||
);
|
||||
};
|
|
@ -1,63 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\RemovingStatic\NodeAnalyzer;
|
||||
|
||||
use PhpParser\Node\Expr\StaticCall;
|
||||
use PhpParser\Node\Name;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PhpParser\Node\Stmt\Expression;
|
||||
use Rector\Core\ValueObject\MethodName;
|
||||
use Rector\NodeNameResolver\NodeNameResolver;
|
||||
|
||||
final class SetUpClassMethodUpdater
|
||||
{
|
||||
public function __construct(
|
||||
private NodeNameResolver $nodeNameResolver
|
||||
) {
|
||||
}
|
||||
|
||||
public function updateSetUpMethod(
|
||||
ClassMethod $setupClassMethod,
|
||||
Expression $parentSetupStaticCall,
|
||||
Expression $assign
|
||||
): void {
|
||||
$parentSetUpStaticCallPosition = $this->getParentSetUpStaticCallPosition($setupClassMethod);
|
||||
if ($parentSetUpStaticCallPosition === null) {
|
||||
$setupClassMethod->stmts = array_merge([$parentSetupStaticCall, $assign], (array) $setupClassMethod->stmts);
|
||||
} else {
|
||||
assert($setupClassMethod->stmts !== null);
|
||||
array_splice($setupClassMethod->stmts, $parentSetUpStaticCallPosition + 1, 0, [$assign]);
|
||||
}
|
||||
}
|
||||
|
||||
private function getParentSetUpStaticCallPosition(ClassMethod $setupClassMethod): ?int
|
||||
{
|
||||
foreach ((array) $setupClassMethod->stmts as $position => $methodStmt) {
|
||||
if ($methodStmt instanceof Expression) {
|
||||
$methodStmt = $methodStmt->expr;
|
||||
}
|
||||
|
||||
if (! $methodStmt instanceof StaticCall) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! $methodStmt->class instanceof Name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! $this->nodeNameResolver->isName($methodStmt->class, 'parent')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! $this->nodeNameResolver->isName($methodStmt->name, MethodName::SET_UP)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return $position;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\RemovingStatic\NodeFactory;
|
||||
|
||||
use PhpParser\Node\Arg;
|
||||
use PhpParser\Node\Expr\ClassConstFetch;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Expr\StaticPropertyFetch;
|
||||
use PhpParser\Node\Name;
|
||||
use PHPStan\Type\ObjectType;
|
||||
use Rector\Core\Exception\ShouldNotHappenException;
|
||||
use Rector\PHPStanStaticTypeMapper\ValueObject\TypeKind;
|
||||
use Rector\StaticTypeMapper\StaticTypeMapper;
|
||||
|
||||
final class SelfContainerFactory
|
||||
{
|
||||
public function __construct(
|
||||
private StaticTypeMapper $staticTypeMapper
|
||||
) {
|
||||
}
|
||||
|
||||
public function createGetTypeMethodCall(ObjectType $objectType): MethodCall
|
||||
{
|
||||
$staticPropertyFetch = new StaticPropertyFetch(new Name('self'), 'container');
|
||||
$getMethodCall = new MethodCall($staticPropertyFetch, 'get');
|
||||
|
||||
$className = $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode($objectType, TypeKind::RETURN());
|
||||
if (! $className instanceof Name) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
$getMethodCall->args[] = new Arg(new ClassConstFetch($className, 'class'));
|
||||
|
||||
return $getMethodCall;
|
||||
}
|
||||
}
|
|
@ -1,300 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\RemovingStatic\Rector\Class_;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\Assign;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Expr\PropertyFetch;
|
||||
use PhpParser\Node\Expr\StaticCall;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use PhpParser\Node\Name\FullyQualified;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\Expression;
|
||||
use PhpParser\Node\Stmt\Property;
|
||||
use PHPStan\Type\ObjectType;
|
||||
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
|
||||
use Rector\Core\NodeManipulator\ClassInsertManipulator;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Core\ValueObject\MethodName;
|
||||
use Rector\Naming\Naming\PropertyNaming;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\PHPUnit\NodeFactory\SetUpClassMethodFactory;
|
||||
use Rector\PostRector\Collector\PropertyToAddCollector;
|
||||
use Rector\PostRector\ValueObject\PropertyMetadata;
|
||||
use Rector\RemovingStatic\NodeAnalyzer\SetUpClassMethodUpdater;
|
||||
use Rector\RemovingStatic\NodeFactory\SelfContainerFactory;
|
||||
use Rector\RemovingStatic\NodeFactory\SetUpFactory;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
|
||||
/**
|
||||
* @see \Rector\Tests\RemovingStatic\Rector\Class_\PHPUnitStaticToKernelTestCaseGetRector\PHPUnitStaticToKernelTestCaseGetRectorTest
|
||||
*/
|
||||
final class PHPUnitStaticToKernelTestCaseGetRector extends AbstractRector implements ConfigurableRectorInterface
|
||||
{
|
||||
/**
|
||||
* @api
|
||||
* @var string
|
||||
*/
|
||||
public const STATIC_CLASS_TYPES = 'static_class_types';
|
||||
|
||||
/**
|
||||
* @var ObjectType[]
|
||||
*/
|
||||
private array $staticObjectTypes = [];
|
||||
|
||||
/**
|
||||
* @var ObjectType[]
|
||||
*/
|
||||
private array $newPropertyObjectTypes = [];
|
||||
|
||||
public function __construct(
|
||||
private PropertyNaming $propertyNaming,
|
||||
private ClassInsertManipulator $classInsertManipulator,
|
||||
private SetUpClassMethodFactory $setUpClassMethodFactory,
|
||||
private SetUpFactory $setUpFactory,
|
||||
private SelfContainerFactory $selfContainerFactory,
|
||||
private SetUpClassMethodUpdater $setUpClassMethodUpdater,
|
||||
private PropertyToAddCollector $propertyToAddCollector
|
||||
) {
|
||||
}
|
||||
|
||||
public function getRuleDefinition(): RuleDefinition
|
||||
{
|
||||
return new RuleDefinition('Convert static calls in PHPUnit test cases, to get() from the container of KernelTestCase', [
|
||||
new ConfiguredCodeSample(
|
||||
<<<'CODE_SAMPLE'
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class SomeTestCase extends TestCase
|
||||
{
|
||||
public function test()
|
||||
{
|
||||
$product = EntityFactory::create('product');
|
||||
}
|
||||
}
|
||||
CODE_SAMPLE
|
||||
,
|
||||
<<<'CODE_SAMPLE'
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
|
||||
final class SomeTestCase extends KernelTestCase
|
||||
{
|
||||
/**
|
||||
* @var EntityFactory
|
||||
*/
|
||||
private $entityFactory;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$this->entityFactory = $this->getService(EntityFactory::class);
|
||||
}
|
||||
|
||||
public function test()
|
||||
{
|
||||
$product = $this->entityFactory->create('product');
|
||||
}
|
||||
}
|
||||
CODE_SAMPLE
|
||||
,
|
||||
[
|
||||
self::STATIC_CLASS_TYPES => ['EntityFactory'],
|
||||
]
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<class-string<Node>>
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [StaticCall::class, Class_::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param StaticCall|Class_ $node
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
// skip yourself
|
||||
$this->newPropertyObjectTypes = [];
|
||||
|
||||
if ($node instanceof Class_) {
|
||||
if ($this->nodeTypeResolver->isObjectTypes($node, $this->staticObjectTypes)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->processClass($node);
|
||||
}
|
||||
|
||||
return $this->processStaticCall($node);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $configuration
|
||||
*/
|
||||
public function configure(array $configuration): void
|
||||
{
|
||||
$staticClassTypes = $configuration[self::STATIC_CLASS_TYPES] ?? [];
|
||||
foreach ($staticClassTypes as $staticClassType) {
|
||||
$this->staticObjectTypes[] = new ObjectType($staticClassType);
|
||||
}
|
||||
}
|
||||
|
||||
private function processClass(Class_ $class): ?Class_
|
||||
{
|
||||
if ($this->isObjectType($class, new ObjectType('PHPUnit\Framework\TestCase'))) {
|
||||
return $this->processPHPUnitClass($class);
|
||||
}
|
||||
|
||||
// add property with the object
|
||||
$newPropertyObjectTypes = $this->collectNewPropertyObjectTypes($class);
|
||||
if ($newPropertyObjectTypes === []) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// add via constructor
|
||||
foreach ($newPropertyObjectTypes as $newPropertyObjectType) {
|
||||
$newPropertyName = $this->propertyNaming->fqnToVariableName($newPropertyObjectType);
|
||||
|
||||
$propertyMetadata = new PropertyMetadata(
|
||||
$newPropertyName,
|
||||
$newPropertyObjectType,
|
||||
Class_::MODIFIER_PRIVATE
|
||||
);
|
||||
$this->propertyToAddCollector->addPropertyToClass($class, $propertyMetadata);
|
||||
}
|
||||
|
||||
return $class;
|
||||
}
|
||||
|
||||
private function processStaticCall(StaticCall $staticCall): ?MethodCall
|
||||
{
|
||||
$classLike = $staticCall->getAttribute(AttributeKey::CLASS_NODE);
|
||||
if (! $classLike instanceof Class_) {
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach ($this->staticObjectTypes as $staticObjectType) {
|
||||
if (! $this->isObjectType($staticCall->class, $staticObjectType)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return $this->convertStaticCallToPropertyMethodCall($staticCall, $staticObjectType);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function processPHPUnitClass(Class_ $class): ?Class_
|
||||
{
|
||||
// add property with the object
|
||||
$newPropertyTypes = $this->collectNewPropertyObjectTypes($class);
|
||||
if ($newPropertyTypes === []) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// add all properties to class
|
||||
$class = $this->addNewPropertiesToClass($class, $newPropertyTypes);
|
||||
|
||||
$parentSetUpStaticCallExpression = $this->setUpFactory->createParentStaticCall();
|
||||
foreach ($newPropertyTypes as $newPropertyType) {
|
||||
// container fetch assign
|
||||
$assign = $this->createContainerGetTypeToPropertyAssign($newPropertyType);
|
||||
|
||||
$setupClassMethod = $class->getMethod(MethodName::SET_UP);
|
||||
|
||||
// get setup or create a setup add add it there
|
||||
if ($setupClassMethod !== null) {
|
||||
$this->setUpClassMethodUpdater->updateSetUpMethod(
|
||||
$setupClassMethod,
|
||||
$parentSetUpStaticCallExpression,
|
||||
$assign
|
||||
);
|
||||
} else {
|
||||
$setUpMethod = $this->setUpClassMethodFactory->createSetUpMethod([$assign]);
|
||||
$this->classInsertManipulator->addAsFirstMethod($class, $setUpMethod);
|
||||
}
|
||||
}
|
||||
|
||||
// update parent clsas if not already
|
||||
if (! $this->isObjectType($class, new ObjectType('Symfony\Bundle\FrameworkBundle\Test\KernelTestCase'))) {
|
||||
$class->extends = new FullyQualified('Symfony\Bundle\FrameworkBundle\Test\KernelTestCase');
|
||||
}
|
||||
|
||||
return $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ObjectType[]
|
||||
*/
|
||||
private function collectNewPropertyObjectTypes(Class_ $class): array
|
||||
{
|
||||
$this->newPropertyObjectTypes = [];
|
||||
|
||||
$this->traverseNodesWithCallable($class->stmts, function (Node $node): void {
|
||||
if (! $node instanceof StaticCall) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($this->staticObjectTypes as $staticObjectType) {
|
||||
if (! $this->isObjectType($node->class, $staticObjectType)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->newPropertyObjectTypes[] = $staticObjectType;
|
||||
}
|
||||
});
|
||||
|
||||
$this->newPropertyObjectTypes = array_unique($this->newPropertyObjectTypes);
|
||||
|
||||
return $this->newPropertyObjectTypes;
|
||||
}
|
||||
|
||||
private function convertStaticCallToPropertyMethodCall(StaticCall $staticCall, ObjectType $objectType): MethodCall
|
||||
{
|
||||
// create "$this->someService" instead
|
||||
$propertyName = $this->propertyNaming->fqnToVariableName($objectType);
|
||||
$propertyFetch = new PropertyFetch(new Variable('this'), $propertyName);
|
||||
|
||||
// turn static call to method on property call
|
||||
$methodCall = new MethodCall($propertyFetch, $staticCall->name);
|
||||
$methodCall->args = $staticCall->args;
|
||||
|
||||
return $methodCall;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ObjectType[] $propertyTypes
|
||||
*/
|
||||
private function addNewPropertiesToClass(Class_ $class, array $propertyTypes): Class_
|
||||
{
|
||||
$properties = [];
|
||||
foreach ($propertyTypes as $propertyType) {
|
||||
$propertyName = $this->propertyNaming->fqnToVariableName($propertyType);
|
||||
$properties[] = $this->nodeFactory->createPrivatePropertyFromNameAndType($propertyName, $propertyType);
|
||||
}
|
||||
|
||||
// add property to the start of the class
|
||||
$class->stmts = array_merge($properties, $class->stmts);
|
||||
|
||||
return $class;
|
||||
}
|
||||
|
||||
private function createContainerGetTypeToPropertyAssign(ObjectType $objectType): Expression
|
||||
{
|
||||
$getMethodCall = $this->selfContainerFactory->createGetTypeMethodCall($objectType);
|
||||
|
||||
$propertyName = $this->propertyNaming->fqnToVariableName($objectType);
|
||||
$propertyFetch = new PropertyFetch(new Variable('this'), $propertyName);
|
||||
|
||||
$assign = new Assign($propertyFetch, $getMethodCall);
|
||||
|
||||
return new Expression($assign);
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Transform\Naming;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Stmt\Namespace_;
|
||||
use Rector\Core\PhpParser\Node\BetterNodeFinder;
|
||||
use Rector\NodeNameResolver\NodeNameResolver;
|
||||
|
||||
final class FullyQualifiedNameResolver
|
||||
{
|
||||
public function __construct(
|
||||
private BetterNodeFinder $betterNodeFinder,
|
||||
private NodeNameResolver $nodeNameResolver
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Node[] $nodes
|
||||
*/
|
||||
public function resolveFullyQualifiedName(array $nodes, string $shortClassName): string
|
||||
{
|
||||
$namespace = $this->betterNodeFinder->findFirstInstanceOf($nodes, Namespace_::class);
|
||||
if (! $namespace instanceof Namespace_) {
|
||||
return $shortClassName;
|
||||
}
|
||||
|
||||
$namespaceName = $this->nodeNameResolver->getName($namespace);
|
||||
if ($namespaceName === null) {
|
||||
return $shortClassName;
|
||||
}
|
||||
|
||||
return $namespaceName . '\\' . $shortClassName;
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Transform\NodeFactory;
|
||||
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PhpParser\Node\Stmt\Function_;
|
||||
use Rector\CodingStyle\Naming\ClassNaming;
|
||||
use Symplify\Astral\ValueObject\NodeBuilder\ClassBuilder;
|
||||
|
||||
final class StaticMethodClassFactory
|
||||
{
|
||||
public function __construct(
|
||||
private ClassMethodFactory $classMethodFactory,
|
||||
private ClassNaming $classNaming
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Function_[] $functions
|
||||
*/
|
||||
public function createStaticMethodClass(string $shortClassName, array $functions): Class_
|
||||
{
|
||||
$classBuilder = new ClassBuilder($shortClassName);
|
||||
$classBuilder->makeFinal();
|
||||
|
||||
foreach ($functions as $function) {
|
||||
$staticClassMethod = $this->createStaticMethod($function);
|
||||
$classBuilder->addStmt($staticClassMethod);
|
||||
}
|
||||
|
||||
return $classBuilder->getNode();
|
||||
}
|
||||
|
||||
private function createStaticMethod(Function_ $function): ClassMethod
|
||||
{
|
||||
$methodName = $this->classNaming->createMethodNameFromFunction($function);
|
||||
return $this->classMethodFactory->createClassMethodFromFunction($methodName, $function);
|
||||
}
|
||||
}
|
|
@ -1,131 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Transform\Rector\Expression;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Stmt\Expression;
|
||||
use PhpParser\Node\Stmt\Return_;
|
||||
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\Transform\ValueObject\MethodCallToReturn;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
use Webmozart\Assert\Assert;
|
||||
|
||||
/**
|
||||
* @see \Rector\Tests\Transform\Rector\Expression\MethodCallToReturnRector\MethodCallToReturnRectorTest
|
||||
*/
|
||||
final class MethodCallToReturnRector extends AbstractRector implements ConfigurableRectorInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const METHOD_CALL_WRAPS = 'method_call_wraps';
|
||||
|
||||
/**
|
||||
* @var MethodCallToReturn[]
|
||||
*/
|
||||
private array $methodCallWraps = [];
|
||||
|
||||
public function getRuleDefinition(): RuleDefinition
|
||||
{
|
||||
return new RuleDefinition('Wrap method call to return', [
|
||||
new ConfiguredCodeSample(
|
||||
<<<'CODE_SAMPLE'
|
||||
class SomeClass
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$this->deny();
|
||||
}
|
||||
|
||||
public function deny()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
CODE_SAMPLE
|
||||
,
|
||||
<<<'CODE_SAMPLE'
|
||||
class SomeClass
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
return $this->deny();
|
||||
}
|
||||
|
||||
public function deny()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
CODE_SAMPLE
|
||||
|
||||
,
|
||||
[
|
||||
self::METHOD_CALL_WRAPS => [new MethodCallToReturn('SomeClass', 'deny')],
|
||||
]
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<class-string<Node>>
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [Expression::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Expression $node
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
if (! $node->expr instanceof MethodCall) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$methodCall = $node->expr;
|
||||
|
||||
return $this->refactorMethodCall($methodCall);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, MethodCallToReturn[]> $configuration
|
||||
*/
|
||||
public function configure(array $configuration): void
|
||||
{
|
||||
$methodCallWraps = $configuration[self::METHOD_CALL_WRAPS] ?? [];
|
||||
Assert::allIsInstanceOf($methodCallWraps, MethodCallToReturn::class);
|
||||
$this->methodCallWraps = $methodCallWraps;
|
||||
}
|
||||
|
||||
private function refactorMethodCall(MethodCall $methodCall): ?Node
|
||||
{
|
||||
$parent = $methodCall->getAttribute(AttributeKey::PARENT_NODE);
|
||||
|
||||
foreach ($this->methodCallWraps as $methodCallWrap) {
|
||||
if (! $this->isObjectType($methodCall->var, $methodCallWrap->getObjectType())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! $this->isName($methodCall->name, $methodCallWrap->getMethod())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// already wrapped
|
||||
if ($parent instanceof Return_) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return new Return_($methodCall);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,178 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Transform\Rector\FileWithoutNamespace;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\FuncCall;
|
||||
use PhpParser\Node\Expr\StaticCall;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\Function_;
|
||||
use PhpParser\Node\Stmt\Namespace_;
|
||||
use Rector\CodingStyle\Naming\ClassNaming;
|
||||
use Rector\Core\PhpParser\Node\CustomNode\FileWithoutNamespace;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\FileSystemRector\ValueObject\AddedFileWithNodes;
|
||||
use Rector\Transform\Naming\FullyQualifiedNameResolver;
|
||||
use Rector\Transform\NodeFactory\StaticMethodClassFactory;
|
||||
use Rector\Transform\ValueObject\FunctionToStaticCall;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
|
||||
/**
|
||||
* @see \Rector\Tests\Transform\Rector\FileWithoutNamespace\FunctionToStaticMethodRector\FunctionToStaticMethodRectorTest
|
||||
*/
|
||||
final class FunctionToStaticMethodRector extends AbstractRector
|
||||
{
|
||||
public function __construct(
|
||||
private ClassNaming $classNaming,
|
||||
private StaticMethodClassFactory $staticMethodClassFactory,
|
||||
private FullyQualifiedNameResolver $fullyQualifiedNameResolver
|
||||
) {
|
||||
}
|
||||
|
||||
public function getRuleDefinition(): RuleDefinition
|
||||
{
|
||||
return new RuleDefinition(
|
||||
'Change functions to static calls, so composer can autoload them',
|
||||
[
|
||||
new CodeSample(
|
||||
<<<'CODE_SAMPLE'
|
||||
function some_function()
|
||||
{
|
||||
}
|
||||
|
||||
some_function('lol');
|
||||
CODE_SAMPLE
|
||||
,
|
||||
<<<'CODE_SAMPLE'
|
||||
class SomeUtilsClass
|
||||
{
|
||||
public static function someFunction()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
SomeUtilsClass::someFunction('lol');
|
||||
CODE_SAMPLE
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<class-string<Node>>
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [FileWithoutNamespace::class, Namespace_::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FileWithoutNamespace|Namespace_ $node
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
/** @var Function_[] $functions */
|
||||
$functions = $this->betterNodeFinder->findInstanceOf($node, Function_::class);
|
||||
if ($functions === []) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$smartFileInfo = $this->file->getSmartFileInfo();
|
||||
|
||||
$shortClassName = $this->classNaming->getNameFromFileInfo($smartFileInfo);
|
||||
$class = $this->staticMethodClassFactory->createStaticMethodClass($shortClassName, $functions);
|
||||
|
||||
$stmts = $node->stmts;
|
||||
$this->removeNodes($functions);
|
||||
|
||||
// replace function calls with class static call
|
||||
$functionsToStaticCalls = $this->resolveFunctionsToStaticCalls($stmts, $shortClassName, $functions);
|
||||
$node->stmts = $this->replaceFuncCallsWithStaticCalls($stmts, $functionsToStaticCalls);
|
||||
|
||||
$this->printStaticMethodClass($smartFileInfo, $shortClassName, $node, $class);
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Node[] $stmts
|
||||
* @param Function_[] $functions
|
||||
* @return FunctionToStaticCall[]
|
||||
*/
|
||||
private function resolveFunctionsToStaticCalls(array $stmts, string $shortClassName, array $functions): array
|
||||
{
|
||||
$functionsToStaticCalls = [];
|
||||
|
||||
$className = $this->fullyQualifiedNameResolver->resolveFullyQualifiedName($stmts, $shortClassName);
|
||||
foreach ($functions as $function) {
|
||||
$functionName = $this->getName($function);
|
||||
if ($functionName === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$methodName = $this->classNaming->createMethodNameFromFunction($function);
|
||||
$functionsToStaticCalls[] = new FunctionToStaticCall($functionName, $className, $methodName);
|
||||
}
|
||||
|
||||
return $functionsToStaticCalls;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Node[] $stmts
|
||||
* @param FunctionToStaticCall[] $functionsToStaticCalls
|
||||
* @return Node[]
|
||||
*/
|
||||
private function replaceFuncCallsWithStaticCalls(array $stmts, array $functionsToStaticCalls): array
|
||||
{
|
||||
$this->traverseNodesWithCallable($stmts, function (Node $node) use ($functionsToStaticCalls): ?StaticCall {
|
||||
if (! $node instanceof FuncCall) {
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach ($functionsToStaticCalls as $functionToStaticCall) {
|
||||
if (! $this->isName($node, $functionToStaticCall->getFunction())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$staticCall = $this->nodeFactory->createStaticCall(
|
||||
$functionToStaticCall->getClass(),
|
||||
$functionToStaticCall->getMethod()
|
||||
);
|
||||
$staticCall->args = $node->args;
|
||||
|
||||
return $staticCall;
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
return $stmts;
|
||||
}
|
||||
|
||||
private function printStaticMethodClass(
|
||||
SmartFileInfo $smartFileInfo,
|
||||
string $shortClassName,
|
||||
Namespace_ | FileWithoutNamespace $node,
|
||||
Class_ $class
|
||||
): void {
|
||||
$classFileDestination = $smartFileInfo->getPath() . DIRECTORY_SEPARATOR . $shortClassName . '.php';
|
||||
|
||||
$nodesToPrint = [$this->resolveNodeToPrint($node, $class)];
|
||||
|
||||
$addedFileWithNodes = new AddedFileWithNodes($classFileDestination, $nodesToPrint);
|
||||
$this->removedAndAddedFilesCollector->addAddedFile($addedFileWithNodes);
|
||||
}
|
||||
|
||||
private function resolveNodeToPrint(Namespace_ | FileWithoutNamespace $node, Class_ $class): Namespace_ | Class_
|
||||
{
|
||||
if ($node instanceof Namespace_) {
|
||||
return new Namespace_($node->name, [$class]);
|
||||
}
|
||||
|
||||
return $class;
|
||||
}
|
||||
}
|
|
@ -1,165 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Transform\Rector\MethodCall;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Arg;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Expr\PropertyFetch;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PHPStan\Type\ObjectType;
|
||||
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Naming\Naming\PropertyNaming;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\PostRector\Collector\PropertyToAddCollector;
|
||||
use Rector\PostRector\ValueObject\PropertyMetadata;
|
||||
use Rector\Transform\ValueObject\VariableMethodCallToServiceCall;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
|
||||
/**
|
||||
* @see \Rector\Tests\Transform\Rector\MethodCall\VariableMethodCallToServiceCallRector\VariableMethodCallToServiceCallRectorTest
|
||||
*/
|
||||
final class VariableMethodCallToServiceCallRector extends AbstractRector implements ConfigurableRectorInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const VARIABLE_METHOD_CALLS_TO_SERVICE_CALLS = 'variable_method_calls_to_service_calls';
|
||||
|
||||
/**
|
||||
* @var VariableMethodCallToServiceCall[]
|
||||
*/
|
||||
private array $variableMethodCallsToServiceCalls = [];
|
||||
|
||||
public function __construct(
|
||||
private PropertyNaming $propertyNaming,
|
||||
private PropertyToAddCollector $propertyToAddCollector
|
||||
) {
|
||||
}
|
||||
|
||||
public function getRuleDefinition(): RuleDefinition
|
||||
{
|
||||
return new RuleDefinition('Replace variable method call to a service one', [
|
||||
new ConfiguredCodeSample(
|
||||
<<<'CODE_SAMPLE'
|
||||
use PhpParser\Node;
|
||||
|
||||
class SomeClass
|
||||
{
|
||||
public function run(Node $node)
|
||||
{
|
||||
$phpDocInfo = $node->getAttribute('php_doc_info');
|
||||
}
|
||||
}
|
||||
CODE_SAMPLE
|
||||
,
|
||||
<<<'CODE_SAMPLE'
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
|
||||
use PhpParser\Node;
|
||||
|
||||
class SomeClass
|
||||
{
|
||||
public function __construct(PhpDocInfoFactory $phpDocInfoFactory)
|
||||
{
|
||||
$this->phpDocInfoFactory = $phpDocInfoFactory;
|
||||
}
|
||||
public function run(Node $node)
|
||||
{
|
||||
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node);
|
||||
}
|
||||
}
|
||||
CODE_SAMPLE
|
||||
,
|
||||
[
|
||||
self::VARIABLE_METHOD_CALLS_TO_SERVICE_CALLS => [
|
||||
new VariableMethodCallToServiceCall(
|
||||
'PhpParser\Node',
|
||||
'getAttribute',
|
||||
'php_doc_info',
|
||||
'Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory',
|
||||
'createFromNodeOrEmpty'
|
||||
),
|
||||
],
|
||||
]
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<class-string<Node>>
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [MethodCall::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param MethodCall $node
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
foreach ($this->variableMethodCallsToServiceCalls as $variableMethodCallToServiceCall) {
|
||||
if (! $node->var instanceof Variable) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! $this->isObjectType($node->var, $variableMethodCallToServiceCall->getVariableObjectType())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! $this->isName($node->name, $variableMethodCallToServiceCall->getMethodName())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$firstArgValue = $node->args[0]->value;
|
||||
if (! $this->valueResolver->isValue(
|
||||
$firstArgValue,
|
||||
$variableMethodCallToServiceCall->getArgumentValue()
|
||||
)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$classLike = $node->getAttribute(AttributeKey::CLASS_NODE);
|
||||
if (! $classLike instanceof Class_) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$serviceObjectType = new ObjectType($variableMethodCallToServiceCall->getServiceType());
|
||||
|
||||
$propertyName = $this->propertyNaming->fqnToVariableName($serviceObjectType);
|
||||
$propertyMetadata = new PropertyMetadata($propertyName, $serviceObjectType, Class_::MODIFIER_PRIVATE);
|
||||
$this->propertyToAddCollector->addPropertyToClass($classLike, $propertyMetadata);
|
||||
|
||||
return $this->createServiceMethodCall(
|
||||
$serviceObjectType,
|
||||
$variableMethodCallToServiceCall->getServiceMethodName(),
|
||||
$node
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed[] $configuration
|
||||
*/
|
||||
public function configure(array $configuration): void
|
||||
{
|
||||
$this->variableMethodCallsToServiceCalls = $configuration[self::VARIABLE_METHOD_CALLS_TO_SERVICE_CALLS] ?? [];
|
||||
}
|
||||
|
||||
private function createServiceMethodCall(ObjectType $objectType, string $methodName, MethodCall $node): MethodCall
|
||||
{
|
||||
$propertyName = $this->propertyNaming->fqnToVariableName($objectType);
|
||||
$propertyFetch = new PropertyFetch(new Variable('this'), $propertyName);
|
||||
$methodCall = new MethodCall($propertyFetch, $methodName);
|
||||
$methodCall->args[] = new Arg($node->var);
|
||||
|
||||
return $methodCall;
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Transform\ValueObject;
|
||||
|
||||
use PHPStan\Type\ObjectType;
|
||||
|
||||
final class MethodCallToReturn
|
||||
{
|
||||
public function __construct(
|
||||
private string $class,
|
||||
private string $method
|
||||
) {
|
||||
}
|
||||
|
||||
public function getObjectType(): ObjectType
|
||||
{
|
||||
return new ObjectType($this->class);
|
||||
}
|
||||
|
||||
public function getMethod(): string
|
||||
{
|
||||
return $this->method;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user