mirror of
https://github.com/rectorphp/rector.git
synced 2025-01-17 21:38:22 +01:00
[Nette] Add TranslateClassMethodToVariadicsRector
This commit is contained in:
parent
94088334c7
commit
5859625d5d
@ -255,7 +255,8 @@
|
||||
"rules/coding-style/tests/Rector/Namespace_/ImportFullyQualifiedNamesRector/Source/Function_/count.php",
|
||||
"rules/coding-style/tests/Rector/Namespace_/ImportFullyQualifiedNamesRector/Source/AnotherClass.php",
|
||||
"rules/coding-style/tests/Rector/Namespace_/ImportFullyQualifiedNamesRector/Source/YetAnotherClass.php",
|
||||
"rules/solid/tests/Rector/ClassMethod/UseInterfaceOverImplementationInConstructorRector/Source/Coconut.php"
|
||||
"rules/solid/tests/Rector/ClassMethod/UseInterfaceOverImplementationInConstructorRector/Source/Coconut.php",
|
||||
"stubs/Nette/Localization/ITranslation.php"
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
|
@ -10,7 +10,7 @@ use Rector\Core\RectorDefinition\CodeSample;
|
||||
use Rector\Core\RectorDefinition\RectorDefinition;
|
||||
|
||||
/**
|
||||
_Source_
|
||||
__Source__
|
||||
* @see \Rector\__Package__\Tests\Rector\__Category__\__Name__\__Name__Test
|
||||
*/
|
||||
final class __Name__ extends AbstractRector
|
||||
|
@ -0,0 +1,142 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Nette\Rector\ClassMethod;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\ArrayDimFetch;
|
||||
use PhpParser\Node\Expr\Assign;
|
||||
use PhpParser\Node\Expr\BinaryOp\Coalesce;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use PhpParser\Node\Identifier;
|
||||
use PhpParser\Node\Param;
|
||||
use PhpParser\Node\Scalar\LNumber;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PhpParser\NodeTraverser;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Core\RectorDefinition\CodeSample;
|
||||
use Rector\Core\RectorDefinition\RectorDefinition;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
|
||||
/**
|
||||
* @see https://github.com/nette/utils/pull/178
|
||||
* @see https://github.com/contributte/translation/commit/d374c4c05b57dff1e5b327bb9bf98c392769806c
|
||||
*
|
||||
* @see \Rector\Nette\Tests\Rector\ClassMethod\TranslateClassMethodToVariadicsRector\TranslateClassMethodToVariadicsRectorTest
|
||||
* @note must be run before "composer update nette/utils:^3.0", because param contract break causes fatal error
|
||||
*/
|
||||
final class TranslateClassMethodToVariadicsRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private const PARAMETERS = 'parameters';
|
||||
|
||||
public function getDefinition(): RectorDefinition
|
||||
{
|
||||
return new RectorDefinition('Change translate() method call 2nd arg to variadic', [
|
||||
new CodeSample(
|
||||
<<<'PHP'
|
||||
use Nette\Localization\ITranslator;
|
||||
|
||||
final class SomeClass implements ITranslator
|
||||
{
|
||||
public function translate($message, $count = null)
|
||||
{
|
||||
return [$message, $count];
|
||||
}
|
||||
}
|
||||
PHP
|
||||
,
|
||||
<<<'PHP'
|
||||
use Nette\Localization\ITranslator;
|
||||
|
||||
final class SomeClass implements ITranslator
|
||||
{
|
||||
public function translate($message, ... $parameters)
|
||||
{
|
||||
$count = $parameters[0] ?? null;
|
||||
return [$message, $count];
|
||||
}
|
||||
}
|
||||
PHP
|
||||
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [ClassMethod::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ClassMethod $node
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
if (! $this->isMethodStaticCallOrClassMethodObjectType($node, 'Nette\Localization\ITranslator')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! $this->isName($node->name, 'translate')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! isset($node->params[1])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$secondParam = $node->params[1];
|
||||
if (! $secondParam->var instanceof Variable) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($secondParam->variadic) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->replaceSecondParamInClassMethodBody($node, $secondParam);
|
||||
|
||||
$secondParam->default = null;
|
||||
$secondParam->variadic = true;
|
||||
$secondParam->var = new Identifier('$' . self::PARAMETERS);
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
private function replaceSecondParamInClassMethodBody(ClassMethod $classMethod, Param $param): void
|
||||
{
|
||||
$paramName = $this->getName($param->var);
|
||||
|
||||
$this->traverseNodesWithCallable((array) $classMethod->stmts, function (Node $node) use ($paramName) {
|
||||
if (! $node instanceof Variable) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! $this->isName($node, $paramName)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// instantiate
|
||||
$assign = $this->createCoalesceAssign($paramName, $node);
|
||||
|
||||
$currentStmt = $node->getAttribute(AttributeKey::CURRENT_STATEMENT);
|
||||
$this->addNodeBeforeNode($assign, $currentStmt);
|
||||
|
||||
return NodeTraverser::STOP_TRAVERSAL;
|
||||
});
|
||||
}
|
||||
|
||||
private function createCoalesceAssign(string $paramName, Variable $variable): Assign
|
||||
{
|
||||
$arrayDimFetch = new ArrayDimFetch(new Variable(self::PARAMETERS), new LNumber(0));
|
||||
$coalesce = new Coalesce($arrayDimFetch, $this->createNull());
|
||||
|
||||
return new Assign(new Variable($variable->name), $coalesce);
|
||||
}
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Nette\Rector\MethodCall;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Core\RectorDefinition\CodeSample;
|
||||
use Rector\Core\RectorDefinition\RectorDefinition;
|
||||
|
||||
/**
|
||||
_Source_
|
||||
* @see \Rector\Nette\Tests\Rector\MethodCall\TranslateClassMethodToVariadicsRector\TranslateClassMethodToVariadicsRectorTest
|
||||
*/
|
||||
final class TranslateClassMethodToVariadicsRector extends AbstractRector
|
||||
{
|
||||
public function getDefinition(): RectorDefinition
|
||||
{
|
||||
return new RectorDefinition('Change translate() method call 2nd arg to variadic', [
|
||||
new CodeSample(
|
||||
<<<'PHP'
|
||||
use Nette\Localization\ITranslator;
|
||||
|
||||
final class SomeClass implements ITranslator
|
||||
{
|
||||
public function translate($message, $count = null)
|
||||
{
|
||||
return [$message, $count];
|
||||
}
|
||||
}
|
||||
PHP
|
||||
,
|
||||
<<<'PHP'
|
||||
use Nette\Localization\ITranslator;
|
||||
|
||||
final class SomeClass implements ITranslator
|
||||
{
|
||||
public function translate($message, ... $parameters)
|
||||
{
|
||||
$count = $parameters[0] ?? null;
|
||||
return [$message, $count];
|
||||
}
|
||||
}
|
||||
PHP
|
||||
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [MethodCall::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param MethodCall $node
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
// change the node
|
||||
|
||||
return $node;
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Nette\Tests\Rector\ClassMethod\TranslateClassMethodToVariadicsRector\Fixture;
|
||||
|
||||
use Nette\Localization\ITranslator;
|
||||
|
||||
final class SomeClass implements ITranslator
|
||||
{
|
||||
public function translate($message, $count = null)
|
||||
{
|
||||
return [$message, $count];
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Nette\Tests\Rector\ClassMethod\TranslateClassMethodToVariadicsRector\Fixture;
|
||||
|
||||
use Nette\Localization\ITranslator;
|
||||
|
||||
final class SomeClass implements ITranslator
|
||||
{
|
||||
public function translate($message, ...$parameters)
|
||||
{
|
||||
$count = $parameters[0] ?? null;
|
||||
return [$message, $count];
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -2,11 +2,12 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Nette\Tests\Rector\MethodCall\TranslateClassMethodToVariadicsRector;
|
||||
namespace Rector\Nette\Tests\Rector\ClassMethod\TranslateClassMethodToVariadicsRector;
|
||||
|
||||
use Iterator;
|
||||
use Nette\Utils\FileSystem;
|
||||
use Rector\Core\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
use Rector\Nette\Rector\MethodCall\TranslateClassMethodToVariadicsRector;
|
||||
use Rector\Nette\Rector\ClassMethod\TranslateClassMethodToVariadicsRector;
|
||||
use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
|
||||
final class TranslateClassMethodToVariadicsRectorTest extends AbstractRectorTestCase
|
||||
@ -16,6 +17,14 @@ final class TranslateClassMethodToVariadicsRectorTest extends AbstractRectorTest
|
||||
*/
|
||||
public function test(SmartFileInfo $fileInfo): void
|
||||
{
|
||||
$localFilePath = __DIR__ . '/../../../../../../vendor/nette/utils/src/Utils/ITranslator.php';
|
||||
if (file_exists($localFilePath)) {
|
||||
FileSystem::delete($localFilePath);
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/../../../../../../stubs/Nette/Localization/ITranslation.php';
|
||||
|
||||
// to make test work with fixture
|
||||
$this->doTestFileInfo($fileInfo);
|
||||
}
|
||||
|
@ -4,9 +4,9 @@ sonar.projectKey=rectorphp_rector
|
||||
|
||||
# relative paths to source
|
||||
# wildcards don't work :(
|
||||
sonar.sources=compiler/src,src,rules/autodiscovery/src,rules/architecture/src,packages/attribute-aware-php-doc/src,packages/better-php-doc-parser/src,rules/cakephp/src,rules/code-quality/src,rules/coding-style/src,packages/console-differ/src,rules/dead-code/src,rules/doctrine/src,rules/doctrine-code-quality/src,rules/framework-migration/src,packages/file-system-rector/src,rules/guzzle/src,rules/laravel/src,rules/legacy/src,rules/mysql-to-mysqli/src,rules/nette-tester-to-phpunit/src,rules/nette-to-symfony/src,rules/nette/src,packages/node-collector/src,packages/node-type-resolver/src,packages/node-name-resolver/src,rules/phpstan/src,packages/phpstan-static-type-mapper/src,rules/phpunit-symfony/src,rules/phpunit/src,rules/psr4/src,rules/php-spec-to-phpunit/src,rules/php52/src,rules/php53/src,rules/php54/src,rules/php55/src,rules/php56/src,rules/php70/src,rules/php71/src,rules/php72/src,rules/php73/src,rules/php74/src,rules/php80/src,rules/removing-static/src,rules/renaming/src,rules/restoration/src,rules/solid/src,rules/sensio/src,packages/static-type-mapper/src,rules/symfony-code-quality/src,rules/symfony-phpunit/src,rules/symfony/src,rules/twig/src,rules/type-declaration/src,packages/vendor-locker/src,packages/rector-generator/src,rules/strict-code-quality/src,packages/dynamic-type-analysis/src,rules/php-deglobalize/src,rules/phalcon/src,rules/doctrine-gedmo-to-knplabs/src,packages/polyfill/src
|
||||
sonar.sources=compiler/src,src,rules/autodiscovery/src,rules/architecture/src,packages/attribute-aware-php-doc/src,packages/better-php-doc-parser/src,rules/cakephp/src,rules/code-quality/src,rules/coding-style/src,packages/console-differ/src,rules/dead-code/src,rules/doctrine/src,rules/doctrine-code-quality/src,rules/framework-migration/src,packages/file-system-rector/src,rules/guzzle/src,rules/laravel/src,rules/legacy/src,rules/mysql-to-mysqli/src,rules/nette-tester-to-phpunit/src,rules/nette-to-symfony/src,rules/nette/src,packages/node-collector/src,packages/node-type-resolver/src,packages/node-name-resolver/src,rules/phpstan/src,packages/phpstan-static-type-mapper/src,rules/phpunit-symfony/src,rules/phpunit/src,rules/psr4/src,rules/php-spec-to-phpunit/src,rules/php52/src,rules/php53/src,rules/php54/src,rules/php55/src,rules/php56/src,rules/php70/src,rules/php71/src,rules/php72/src,rules/php73/src,rules/php74/src,rules/php80/src,rules/removing-static/src,rules/renaming/src,rules/restoration/src,rules/solid/src,rules/sensio/src,packages/static-type-mapper/src,rules/symfony-code-quality/src,rules/symfony-phpunit/src,rules/symfony/src,rules/twig/src,rules/type-declaration/src,packages/vendor-locker/src,packages/rector-generator/src,rules/strict-code-quality/src,packages/dynamic-type-analysis/src,rules/php-deglobalize/src,rules/phalcon/src,rules/doctrine-gedmo-to-knplabs/src,packages/polyfill/src,rules/generic/src
|
||||
|
||||
sonar.tests=tests,rules/autodiscovery/tests,rules/architecture/tests,packages/better-php-doc-parser/tests,rules/cakephp/tests,rules/code-quality/tests,rules/coding-style/tests,rules/dead-code/tests,rules/doctrine/tests,rules/doctrine-code-quality/tests,rules/guzzle/tests,rules/laravel/tests,rules/legacy/tests,rules/mysql-to-mysqli/tests,rules/nette-tester-to-phpunit/tests,rules/nette-to-symfony/tests,rules/nette/tests,packages/node-type-resolver/tests,utils/phpstan-extensions/src,rules/phpstan/tests,rules/phpunit-symfony/tests,rules/phpunit/tests,rules/psr4/tests,rules/php-spec-to-phpunit/tests,rules/php52/tests,rules/php53/tests,rules/php54/tests,rules/php55/tests,rules/php56/tests,rules/php70/tests,rules/php71/tests,rules/php72/tests,rules/php73/tests,rules/php74/tests,rules/php80/tests,rules/removing-static/tests,rules/renaming/tests,rules/restoration/tests,rules/solid/tests,rules/sensio/tests,rules/symfony-code-quality/tests,rules/symfony-phpunit/tests,rules/symfony/tests,rules/twig/tests,rules/type-declaration/tests,rules/strict-code-quality/tests,packages/dynamic-type-analysis/tests,rules/php-deglobalize/tests,rules/phalcon/tests,utils/documentation-generator/src,utils/phpstan-attribute-type-syncer/src,utils/phpstan-static-type-mapper-checker/src,rules/doctrine-gedmo-to-knplabs/tests,packages/polyfill/tests,rules/downgrade/tests
|
||||
sonar.tests=tests,rules/autodiscovery/tests,rules/architecture/tests,packages/better-php-doc-parser/tests,rules/cakephp/tests,rules/code-quality/tests,rules/coding-style/tests,rules/dead-code/tests,rules/doctrine/tests,rules/doctrine-code-quality/tests,rules/guzzle/tests,rules/laravel/tests,rules/legacy/tests,rules/mysql-to-mysqli/tests,rules/nette-tester-to-phpunit/tests,rules/nette-to-symfony/tests,rules/nette/tests,packages/node-type-resolver/tests,utils/phpstan-extensions/src,rules/phpstan/tests,rules/phpunit-symfony/tests,rules/phpunit/tests,rules/psr4/tests,rules/php-spec-to-phpunit/tests,rules/php52/tests,rules/php53/tests,rules/php54/tests,rules/php55/tests,rules/php56/tests,rules/php70/tests,rules/php71/tests,rules/php72/tests,rules/php73/tests,rules/php74/tests,rules/php80/tests,rules/removing-static/tests,rules/renaming/tests,rules/restoration/tests,rules/solid/tests,rules/sensio/tests,rules/symfony-code-quality/tests,rules/symfony-phpunit/tests,rules/symfony/tests,rules/twig/tests,rules/type-declaration/tests,rules/strict-code-quality/tests,packages/dynamic-type-analysis/tests,rules/php-deglobalize/tests,rules/phalcon/tests,utils/documentation-generator/src,utils/phpstan-attribute-type-syncer/src,utils/phpstan-static-type-mapper-checker/src,rules/doctrine-gedmo-to-knplabs/tests,packages/polyfill/tests,rules/downgrade/tests,rules/generic/tests
|
||||
|
||||
# see https://docs.sonarqube.org/latest/project-administration/narrowing-the-focus/#NarrowingtheFocus-patterns
|
||||
sonar.exclusions=src/**/*.php.inc,rules/**/*.php.inc,packages/**/*.php.inc,packages/**/Fixture/**/*,rules/**/Fixture/**/*,tests/**/Source/**/*
|
||||
|
14
stubs/Nette/Localization/ITranslation.php
Normal file
14
stubs/Nette/Localization/ITranslation.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Nette\Localization;
|
||||
|
||||
if (interface_exists('Nette\Localization\ITranslator')) {
|
||||
return;
|
||||
}
|
||||
|
||||
interface ITranslator
|
||||
{
|
||||
public function translate($message, $count = null);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user