[Symfony] Add ArrayArgumentProcessRector

This commit is contained in:
Tomas Votruba 2018-10-31 23:31:31 +01:00
parent a2ef38c472
commit c4aa54142f
11 changed files with 204 additions and 0 deletions

View File

@ -0,0 +1,3 @@
services:
# https://symfony.com/blog/new-in-symfony-4-2-important-deprecations
Rector\Symfony\Rector\New_\StringToArrayArgumentProcessRector: ~

View File

@ -0,0 +1,110 @@
<?php declare(strict_types=1);
namespace Rector\Symfony\Rector\New_;
use Nette\Utils\Strings;
use PhpParser\Node;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Scalar\String_;
use Rector\Node\NodeFactory;
use Rector\Rector\AbstractRector;
use Rector\RectorDefinition\CodeSample;
use Rector\RectorDefinition\RectorDefinition;
/**
* @see https://github.com/symfony/symfony/pull/27821/files
*/
final class StringToArrayArgumentProcessRector extends AbstractRector
{
/**
* @var string
*/
private $processClass;
/**
* @var NodeFactory
*/
private $nodeFactory;
/**
* @var string
*/
private $processHelperClass;
public function __construct(
NodeFactory $nodeFactory,
string $processClass = 'Symfony\Component\Process\Process',
string $processHelperClass = 'Symfony\Component\Console\Helper\ProcessHelper'
) {
$this->nodeFactory = $nodeFactory;
$this->processClass = $processClass;
$this->processHelperClass = $processHelperClass;
}
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Changes Process string argument to an array', [
new CodeSample(
<<<'CODE_SAMPLE'
use Symfony\Component\Process\Process;
$process = new Process('ls -l');
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
use Symfony\Component\Process\Process;
$process = new Process(['ls', '-l']);
CODE_SAMPLE
),
]);
}
/**
* @return string[]
*/
public function getNodeTypes(): array
{
return [New_::class, MethodCall::class];
}
/**
* @param New_ $node
*/
public function refactor(Node $node): ?Node
{
if ($this->isType($node, $this->processClass)) {
return $this->processArgumentPosition($node, 0);
}
if ($this->isType($node, $this->processHelperClass)) {
return $this->processArgumentPosition($node, 1);
}
return null;
}
/**
* @param New_|MethodCall $node
*/
private function processArgumentPosition(Node $node, int $argumentPosition): ?Node
{
if (! isset($node->args[$argumentPosition])) {
return null;
}
$firstArgument = $node->args[$argumentPosition]->value;
if ($firstArgument instanceof Array_) {
return null;
}
if (! $firstArgument instanceof String_) {
return null;
}
$parts = Strings::split($firstArgument->value, '# #');
$node->args[$argumentPosition]->value = $this->nodeFactory->createArray(...$parts);
return $node;
}
}

View File

@ -0,0 +1,10 @@
<?php
use Rector\Symfony\Tests\Rector\New_\StringToArrayArgumentProcessRector\Source\Process;
$process = new Process(['ls', '-l']);
$process = new Process(['ls', '-l']);
$value = 123;
$process = new Process($value);

View File

@ -0,0 +1,9 @@
<?php
use Rector\Symfony\Tests\Rector\New_\StringToArrayArgumentProcessRector\Source\ProcessHelper;
use Symfony\Component\Console\Output\ConsoleOutput;
$procesHelper = new ProcessHelper();
$output = new ConsoleOutput();
$procesHelper->run($output, ['ls', '-l']);

View File

@ -0,0 +1,8 @@
<?php declare(strict_types=1);
namespace Rector\Symfony\Tests\Rector\New_\StringToArrayArgumentProcessRector\Source;
final class Process
{
}

View File

@ -0,0 +1,8 @@
<?php declare(strict_types=1);
namespace Rector\Symfony\Tests\Rector\New_\StringToArrayArgumentProcessRector\Source;
final class ProcessHelper
{
}

View File

@ -0,0 +1,31 @@
<?php declare(strict_types=1);
namespace Rector\Symfony\Tests\Rector\New_\StringToArrayArgumentProcessRector;
use Iterator;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
/**
* @covers \Rector\Symfony\Rector\New_\StringToArrayArgumentProcessRector
*/
final class StringToArrayArgumentProcessRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideWrongToFixedFiles()
*/
public function test(string $wrong, string $fixed): void
{
$this->doTestFileMatchesExpectedContent($wrong, $fixed);
}
public function provideWrongToFixedFiles(): Iterator
{
yield [__DIR__ . '/Wrong/wrong.php.inc', __DIR__ . '/Correct/correct.php.inc'];
yield [__DIR__ . '/Wrong/wrong2.php.inc', __DIR__ . '/Correct/correct2.php.inc'];
}
protected function provideConfig(): string
{
return __DIR__ . '/config.yml';
}
}

View File

@ -0,0 +1,10 @@
<?php
use Rector\Symfony\Tests\Rector\New_\StringToArrayArgumentProcessRector\Source\Process;
$process = new Process('ls -l');
$process = new Process(['ls', '-l']);
$value = 123;
$process = new Process($value);

View File

@ -0,0 +1,9 @@
<?php
use Rector\Symfony\Tests\Rector\New_\StringToArrayArgumentProcessRector\Source\ProcessHelper;
use Symfony\Component\Console\Output\ConsoleOutput;
$procesHelper = new ProcessHelper();
$output = new ConsoleOutput();
$procesHelper->run($output, 'ls -l');

View File

@ -0,0 +1,4 @@
services:
Rector\Symfony\Rector\New_\StringToArrayArgumentProcessRector:
$processClass: 'Rector\Symfony\Tests\Rector\New_\StringToArrayArgumentProcessRector\Source\Process'
$processHelperClass: 'Rector\Symfony\Tests\Rector\New_\StringToArrayArgumentProcessRector\Source\ProcessHelper'

View File

@ -119,6 +119,8 @@ final class NodeFactory
} elseif ($item instanceof Identifier) {
$string = new String_($item->toString());
$arrayItems[] = new ArrayItem($string);
} elseif (is_scalar($item)) {
$arrayItems[] = new ArrayItem(BuilderHelpers::normalizeValue($item));
} else {
throw new NotImplementedException(sprintf(
'Not implemented yet. Go to "%s()" and add check for "%s" node.',