mirror of
https://github.com/rectorphp/rector.git
synced 2024-05-31 08:20:53 +00:00
PHPStan updated and static fixes (#192)
This commit is contained in:
parent
7bd6b3a0b9
commit
1a3afef04d
|
@ -181,18 +181,18 @@ Replaces defined map of arguments in defined methods and their calls.
|
|||
- class: [`Rector\Arguments\Rector\ClassMethod\ArgumentDefaultValueReplacerRector`](../rules/Arguments/Rector/ClassMethod/ArgumentDefaultValueReplacerRector.php)
|
||||
|
||||
```php
|
||||
use Rector\Arguments\Rector\ClassMethod\ArgumentDefaultValueReplacerRector;
|
||||
use Rector\Arguments\ValueObject\ArgumentDefaultValueReplacer;
|
||||
use Rector\Arguments\Rector\ClassMethod\ReplaceArgumentDefaultValueRector;
|
||||
use Rector\Arguments\ValueObject\ReplaceArgumentDefaultValue;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
use Symplify\SymfonyPhpConfig\ValueObjectInliner;
|
||||
|
||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services = $containerConfigurator->services();
|
||||
|
||||
$services->set(ArgumentDefaultValueReplacerRector::class)
|
||||
$services->set(ReplaceArgumentDefaultValueRector::class)
|
||||
->call('configure', [[
|
||||
ArgumentDefaultValueReplacerRector::REPLACED_ARGUMENTS => ValueObjectInliner::inline([
|
||||
new ArgumentDefaultValueReplacer('SomeExampleClass', 'someMethod', 0, 'SomeClass::OLD_CONSTANT', false),
|
||||
ReplaceArgumentDefaultValueRector::REPLACED_ARGUMENTS => ValueObjectInliner::inline([
|
||||
new ReplaceArgumentDefaultValue('SomeExampleClass', 'someMethod', 0, 'SomeClass::OLD_CONSTANT', false),
|
||||
]),
|
||||
]]);
|
||||
};
|
||||
|
@ -218,7 +218,7 @@ Streamline the operator arguments of version_compare function
|
|||
|
||||
```php
|
||||
use Rector\Arguments\Rector\FuncCall\FunctionArgumentDefaultValueReplacerRector;
|
||||
use Rector\Arguments\ValueObject\FuncCallArgumentDefaultValueReplacer;
|
||||
use Rector\Arguments\ValueObject\ReplaceFuncCallArgumentDefaultValue;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
use Symplify\SymfonyPhpConfig\ValueObjectInliner;
|
||||
|
||||
|
@ -228,7 +228,7 @@ return static function (ContainerConfigurator $containerConfigurator): void {
|
|||
$services->set(FunctionArgumentDefaultValueReplacerRector::class)
|
||||
->call('configure', [[
|
||||
FunctionArgumentDefaultValueReplacerRector::REPLACED_ARGUMENTS => ValueObjectInliner::inline([
|
||||
new FuncCallArgumentDefaultValueReplacer('version_compare', 2, 'gte', 'ge'),
|
||||
new ReplaceFuncCallArgumentDefaultValue('version_compare', 2, 'gte', 'ge'),
|
||||
]),
|
||||
]]);
|
||||
};
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
"nette/utils": "^3.2",
|
||||
"nikic/php-parser": "4.10.5",
|
||||
"phpstan/phpdoc-parser": "^0.5.4",
|
||||
"phpstan/phpstan": ">=0.12.86 <=0.12.88",
|
||||
"phpstan/phpstan": ">=0.12.86 <=0.12.89",
|
||||
"phpstan/phpstan-phpunit": "^0.12.19",
|
||||
"rector/extension-installer": "^0.10.2",
|
||||
"rector/rector-cakephp": "^0.11.2",
|
||||
|
@ -38,16 +38,16 @@
|
|||
"symfony/http-kernel": "^5.3",
|
||||
"symfony/process": "^5.3",
|
||||
"symfony/yaml": "^5.3",
|
||||
"symplify/astral": "^9.3.15",
|
||||
"symplify/autowire-array-parameter": "^9.3.15",
|
||||
"symplify/composer-json-manipulator": "^9.3.15",
|
||||
"symplify/console-color-diff": "^9.3.15",
|
||||
"symplify/package-builder": "^9.3.15",
|
||||
"symplify/rule-doc-generator-contracts": "^9.3.15",
|
||||
"symplify/simple-php-doc-parser": "^9.3.15",
|
||||
"symplify/skipper": "^9.3.15",
|
||||
"symplify/smart-file-system": "^9.3.10",
|
||||
"symplify/symfony-php-config": "^9.3.10",
|
||||
"symplify/astral": "^9.3.22",
|
||||
"symplify/autowire-array-parameter": "^9.3.22",
|
||||
"symplify/composer-json-manipulator": "^9.3.22",
|
||||
"symplify/console-color-diff": "^9.3.22",
|
||||
"symplify/package-builder": "^9.3.22",
|
||||
"symplify/rule-doc-generator-contracts": "^9.3.22",
|
||||
"symplify/simple-php-doc-parser": "^9.3.22",
|
||||
"symplify/skipper": "^9.3.22",
|
||||
"symplify/smart-file-system": "^9.3.22",
|
||||
"symplify/symfony-php-config": "^9.3.22",
|
||||
"tracy/tracy": "^2.8",
|
||||
"webmozart/assert": "^1.10"
|
||||
},
|
||||
|
@ -57,13 +57,13 @@
|
|||
"phpunit/phpunit": "^9.5",
|
||||
"rector/rector-generator": "^0.1.7",
|
||||
"rector/phpstan-rules": "^0.3",
|
||||
"symplify/coding-standard": "^9.3.15",
|
||||
"symplify/easy-ci": "^9.3.15",
|
||||
"symplify/easy-coding-standard": "^9.3.15",
|
||||
"symplify/easy-testing": "^9.3.15",
|
||||
"symplify/phpstan-extensions": "^9.3.15",
|
||||
"symplify/phpstan-rules": "^9.3.15",
|
||||
"symplify/rule-doc-generator": "^9.3.15"
|
||||
"symplify/coding-standard": "^9.3.22",
|
||||
"symplify/easy-ci": "^9.3.22",
|
||||
"symplify/easy-coding-standard": "^9.3.22",
|
||||
"symplify/easy-testing": "^9.3.22",
|
||||
"symplify/phpstan-extensions": "^9.3.22",
|
||||
"symplify/phpstan-rules": "^9.3.22",
|
||||
"symplify/rule-doc-generator": "^9.3.22"
|
||||
},
|
||||
"replace": {
|
||||
"rector/rector": "self.version"
|
||||
|
|
|
@ -5,7 +5,7 @@ declare(strict_types=1);
|
|||
use Rector\Arguments\Rector\ClassMethod\ArgumentAdderRector;
|
||||
use Rector\Arguments\Rector\FuncCall\FunctionArgumentDefaultValueReplacerRector;
|
||||
use Rector\Arguments\ValueObject\ArgumentAdder;
|
||||
use Rector\Arguments\ValueObject\FuncCallArgumentDefaultValueReplacer;
|
||||
use Rector\Arguments\ValueObject\ReplaceFuncCallArgumentDefaultValue;
|
||||
use Rector\DeadCode\Rector\StaticCall\RemoveParentCallWithoutParentRector;
|
||||
use Rector\Php80\Rector\Catch_\RemoveUnusedVariableInCatchRector;
|
||||
use Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector;
|
||||
|
@ -97,15 +97,15 @@ return static function (ContainerConfigurator $containerConfigurator): void {
|
|||
$services->set(Rector\Arguments\Rector\FuncCall\FunctionArgumentDefaultValueReplacerRector::class)
|
||||
->call('configure', [[
|
||||
FunctionArgumentDefaultValueReplacerRector::REPLACED_ARGUMENTS => ValueObjectInliner::inline([
|
||||
new FuncCallArgumentDefaultValueReplacer('version_compare', 2, 'gte', 'ge'),
|
||||
new FuncCallArgumentDefaultValueReplacer('version_compare', 2, 'lte', 'le'),
|
||||
new FuncCallArgumentDefaultValueReplacer('version_compare', 2, '', '!='),
|
||||
new FuncCallArgumentDefaultValueReplacer('version_compare', 2, '!', '!='),
|
||||
new FuncCallArgumentDefaultValueReplacer('version_compare', 2, 'g', 'gt'),
|
||||
new FuncCallArgumentDefaultValueReplacer('version_compare', 2, 'l', 'lt'),
|
||||
new FuncCallArgumentDefaultValueReplacer('version_compare', 2, 'gte', 'ge'),
|
||||
new FuncCallArgumentDefaultValueReplacer('version_compare', 2, 'lte', 'le'),
|
||||
new FuncCallArgumentDefaultValueReplacer('version_compare', 2, 'n', 'ne'),
|
||||
new ReplaceFuncCallArgumentDefaultValue('version_compare', 2, 'gte', 'ge'),
|
||||
new ReplaceFuncCallArgumentDefaultValue('version_compare', 2, 'lte', 'le'),
|
||||
new ReplaceFuncCallArgumentDefaultValue('version_compare', 2, '', '!='),
|
||||
new ReplaceFuncCallArgumentDefaultValue('version_compare', 2, '!', '!='),
|
||||
new ReplaceFuncCallArgumentDefaultValue('version_compare', 2, 'g', 'gt'),
|
||||
new ReplaceFuncCallArgumentDefaultValue('version_compare', 2, 'l', 'lt'),
|
||||
new ReplaceFuncCallArgumentDefaultValue('version_compare', 2, 'gte', 'ge'),
|
||||
new ReplaceFuncCallArgumentDefaultValue('version_compare', 2, 'lte', 'le'),
|
||||
new ReplaceFuncCallArgumentDefaultValue('version_compare', 2, 'n', 'ne'),
|
||||
]),
|
||||
]]);
|
||||
};
|
||||
|
|
|
@ -9,7 +9,7 @@ use PhpParser\Node\AttributeGroup;
|
|||
use Rector\PhpAttribute\Printer\PhpAttributeGroupFactory;
|
||||
use Rector\Testing\PHPUnit\AbstractTestCase;
|
||||
|
||||
class PhpAttributeGroupFactoryTest extends AbstractTestCase
|
||||
final class PhpAttributeGroupFactoryTest extends AbstractTestCase
|
||||
{
|
||||
private PhpAttributeGroupFactory $phpAttributeGroupFactory;
|
||||
|
||||
|
@ -24,20 +24,23 @@ class PhpAttributeGroupFactoryTest extends AbstractTestCase
|
|||
{
|
||||
$attributeGroup = $this->phpAttributeGroupFactory->createFromClassWithItems(
|
||||
'Symfony\Component\Routing\Annotation\Route',
|
||||
['path' => '/path', 'name' => 'action']
|
||||
[
|
||||
'path' => '/path',
|
||||
'name' => 'action',
|
||||
]
|
||||
);
|
||||
|
||||
self::assertInstanceOf(AttributeGroup::class, $attributeGroup);
|
||||
$this->assertInstanceOf(AttributeGroup::class, $attributeGroup);
|
||||
}
|
||||
|
||||
public function testCreateArgsFromItems(): void
|
||||
{
|
||||
$method = new \ReflectionMethod($this->phpAttributeGroupFactory, 'createArgsFromItems');
|
||||
$method->setAccessible(true);
|
||||
$args = $method->invokeArgs($this->phpAttributeGroupFactory, [['path' => '/path', 'name' => 'action']]);
|
||||
$args = $this->phpAttributeGroupFactory->createArgsFromItems([
|
||||
'path' => '/path',
|
||||
'name' => 'action',
|
||||
]);
|
||||
|
||||
self::assertIsArray($args);
|
||||
self::assertCount(2, $args);
|
||||
self::assertContainsOnlyInstancesOf(Arg::class, $args);
|
||||
$this->assertCount(2, $args);
|
||||
$this->assertContainsOnlyInstancesOf(Arg::class, $args);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ namespace Rector\ListReporting\Output;
|
|||
use Rector\Core\Contract\Console\OutputStyleInterface;
|
||||
use Rector\ListReporting\Contract\Output\ShowOutputFormatterInterface;
|
||||
|
||||
final class ConsoleOutputFormatter implements ShowOutputFormatterInterface
|
||||
final class ConsoleShowOutputFormatter implements ShowOutputFormatterInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
|
@ -67,7 +67,7 @@ final class PhpAttributeGroupFactory
|
|||
* @param mixed[] $items
|
||||
* @return Arg[]
|
||||
*/
|
||||
private function createArgsFromItems(array $items, ?string $silentKey = null): array
|
||||
public function createArgsFromItems(array $items, ?string $silentKey = null): array
|
||||
{
|
||||
$args = [];
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ use PhpParser\Node\Stmt\Expression;
|
|||
use PhpParser\Node\Stmt\Return_;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
|
||||
final class ReadExprAnalyzer
|
||||
final class JustReadExprAnalyzer
|
||||
{
|
||||
public function isReadContext(Expr $expr): bool
|
||||
{
|
|
@ -12,7 +12,7 @@ use Rector\ReadWrite\NodeFinder\NodeUsageFinder;
|
|||
final class PropertyFetchReadNodeAnalyzer implements ReadNodeAnalyzerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private ReadExprAnalyzer $readExprAnalyzer,
|
||||
private JustReadExprAnalyzer $justReadExprAnalyzer,
|
||||
private NodeUsageFinder $nodeUsageFinder
|
||||
) {
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ final class PropertyFetchReadNodeAnalyzer implements ReadNodeAnalyzerInterface
|
|||
{
|
||||
$propertyFetchUsages = $this->nodeUsageFinder->findPropertyFetchUsages($node);
|
||||
foreach ($propertyFetchUsages as $propertyFetchUsage) {
|
||||
if ($this->readExprAnalyzer->isReadContext($propertyFetchUsage)) {
|
||||
if ($this->justReadExprAnalyzer->isReadContext($propertyFetchUsage)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ final class VariableReadNodeAnalyzer implements ReadNodeAnalyzerInterface
|
|||
public function __construct(
|
||||
private ParentScopeFinder $parentScopeFinder,
|
||||
private NodeUsageFinder $nodeUsageFinder,
|
||||
private ReadExprAnalyzer $readExprAnalyzer
|
||||
private JustReadExprAnalyzer $justReadExprAnalyzer
|
||||
) {
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,7 @@ final class VariableReadNodeAnalyzer implements ReadNodeAnalyzerInterface
|
|||
|
||||
$variableUsages = $this->nodeUsageFinder->findVariableUsages((array) $parentScope->stmts, $node);
|
||||
foreach ($variableUsages as $variableUsage) {
|
||||
if ($this->readExprAnalyzer->isReadContext($variableUsage)) {
|
||||
if ($this->justReadExprAnalyzer->isReadContext($variableUsage)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
24
phpstan.neon
24
phpstan.neon
|
@ -164,7 +164,6 @@ parameters:
|
|||
paths:
|
||||
- rules/Renaming/Rector/FileWithoutNamespace/PseudoNamespaceToNamespaceRector.php
|
||||
- rules/CodeQuality/Rector/Concat/JoinStringConcatRector.php
|
||||
- rules/Php80/Rector/Switch_/ChangeSwitchToMatchRector.php
|
||||
- packages/NodeNestingScope/NodeFinder/ScopeAwareNodeFinder.php
|
||||
|
||||
-
|
||||
|
@ -309,11 +308,6 @@ parameters:
|
|||
- '#Parameter \#1 \$stmts of method Rector\\EarlyReturn\\Rector\\Return_\\PreparedValueToEarlyReturnRector\:\:collectIfs\(\) expects array<PhpParser\\Node\\Stmt\\If_\>, array<PhpParser\\Node\\Stmt\> given#'
|
||||
- '#Access to an undefined property PhpParser\\Node\\FunctionLike\|PhpParser\\Node\\Stmt\\If_\:\:\$stmts#'
|
||||
|
||||
-
|
||||
message: '#Function "get_declared_classes\(\)" cannot be used/left in the code#'
|
||||
paths:
|
||||
- rules/Restoration/ClassMap/ExistingClassesProvider.php
|
||||
|
||||
-
|
||||
message: '#Parameter \#1 \$types of method Rector\\Defluent\\NodeAnalyzer\\FluentCallStaticTypeResolver\:\:filterOutAlreadyPresentParentClasses\(\) expects array<class\-string\>, array<int, string\> given#'
|
||||
paths:
|
||||
|
@ -332,8 +326,6 @@ parameters:
|
|||
paths:
|
||||
- src/Console/Command/ProcessCommand.php
|
||||
|
||||
- '#Parameter \#2 \$returnedStrictTypeNode of method Rector\\TypeDeclaration\\Rector\\ClassMethod\\ReturnTypeFromStrictTypedCallRector\:\:refactorSingleReturnType\(\) expects PhpParser\\Node\\Name\|PhpParser\\Node\\NullableType\|PhpParser\\Node\\UnionType, PhpParser\\Node\\Name\|PhpParser\\Node\\NullableType\|PHPStan\\Type\\UnionType given#'
|
||||
|
||||
- '#(.*?) class\-string, string given#'
|
||||
|
||||
# part of refactor() API, node must be returned, or does bring any value
|
||||
|
@ -342,11 +334,6 @@ parameters:
|
|||
paths:
|
||||
- '*Rector.php'
|
||||
|
||||
-
|
||||
message: '#Cannot cast array<string\>\|string\|null to string#'
|
||||
paths:
|
||||
- utils/compiler/src/Command/DowngradePathsCommand.php
|
||||
|
||||
# PHP 7_4 literal syntax
|
||||
- '#Property PhpParser\\Node\\Scalar\\DNumber\:\:\$value \(float\|int\) does not accept string#'
|
||||
|
||||
|
@ -414,21 +401,13 @@ parameters:
|
|||
|
||||
- '#Method Rector\\Core\\PhpParser\\Node\\BetterNodeFinder\:\:findParentTypes\(\) should return T of PhpParser\\Node\|null but returns class\-string<T of PhpParser\\Node\>\|T of PhpParser\\Node#'
|
||||
|
||||
-
|
||||
message: '#Assign in loop is not allowed#'
|
||||
paths:
|
||||
- rules/DowngradePhp72/NodeAnalyzer/ParamContravariantDetector.php
|
||||
|
||||
# doc typo in php-parser
|
||||
- '#Parameter \#2 \$args of class PhpParser\\Node\\Expr\\FuncCall constructor expects array<PhpParser\\Node\\Arg\>, array<int, PhpParser\\Node\\Arg\|null\> given#'
|
||||
|
||||
- '#Class with base "(.*?)" name is already used in "Symplify\\(.*?)", "Rector\\(.*?)"\. Use unique name to make classes easy to recognize#'
|
||||
|
||||
# php-parser bug
|
||||
- '#Parameter \#1 \$type of method PhpParser\\Builder\\FunctionLike\:\:setReturnType\(\) expects PhpParser\\Node\\Name\|PhpParser\\Node\\NullableType\|string, PhpParser\\Node\\Name\|PhpParser\\Node\\NullableType\|PhpParser\\Node\\UnionType given#'
|
||||
|
||||
- '#Method Rector\\Core\\Tests\\DependencyInjection\\ConfigurableRectorImportConfigCallsMergeTest\:\:provideData\(\) return type has no value type specified in iterable type Iterator#'
|
||||
- '#Class with base "PhpVersion" name is already used in "PHPStan\\Php\\PhpVersion", "Rector\\Core\\ValueObject\\PhpVersion"\. Use unique name to make classes easy to recognize#'
|
||||
|
||||
-
|
||||
message: '#Use separate function calls with readable variable names#'
|
||||
|
@ -446,8 +425,6 @@ parameters:
|
|||
paths:
|
||||
- rules/EarlyReturn/Rector/If_/ChangeAndIfToEarlyReturnRector.php
|
||||
|
||||
- '#Class with base "PhpVersionFactory" name is already used in "PHPStan\\Php\\PhpVersionFactory", "Rector\\Core\\Util\\PhpVersionFactory"\. Use unique name to make classes easy to recognize#'
|
||||
|
||||
-
|
||||
message: '#Function "function_exists\(\)" cannot be used/left in the code#'
|
||||
paths:
|
||||
|
@ -466,7 +443,6 @@ parameters:
|
|||
- '#Method Rector\\BetterPhpDocParser\\PhpDocParser\\BetterPhpDocParser\:\:parseChildAndStoreItsPositions\(\) should return PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTagNode\|PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTextNode but returns PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocChildNode#'
|
||||
|
||||
|
||||
- '#Method Rector\\Core\\Application\\VersionResolver\:\:resolvePackageData\(\) return type has no value type specified in iterable type array#'
|
||||
- '#Cognitive complexity for "Rector\\Core\\Rector\\AbstractRector\:\:enterNode\(\)" is \d+, keep it under 9#'
|
||||
|
||||
-
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\Arguments\Rector\ClassMethod\ArgumentDefaultValueReplacerRector\Fixture;
|
||||
namespace Rector\Tests\Arguments\Rector\ClassMethod\ReplaceArgumentDefaultValueRector\Fixture;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
|
||||
|
@ -15,7 +15,7 @@ function argumentDefalutValue()
|
|||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\Arguments\Rector\ClassMethod\ArgumentDefaultValueReplacerRector\Fixture;
|
||||
namespace Rector\Tests\Arguments\Rector\ClassMethod\ReplaceArgumentDefaultValueRector\Fixture;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\Arguments\Rector\ClassMethod\ArgumentDefaultValueReplacerRector\Fixture;
|
||||
namespace Rector\Tests\Arguments\Rector\ClassMethod\ReplaceArgumentDefaultValueRector\Fixture;
|
||||
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
|
@ -16,7 +16,7 @@ function argumentDefaultValue2()
|
|||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\Arguments\Rector\ClassMethod\ArgumentDefaultValueReplacerRector\Fixture;
|
||||
namespace Rector\Tests\Arguments\Rector\ClassMethod\ReplaceArgumentDefaultValueRector\Fixture;
|
||||
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\Arguments\Rector\ClassMethod\ArgumentDefaultValueReplacerRector\Fixture;
|
||||
namespace Rector\Tests\Arguments\Rector\ClassMethod\ReplaceArgumentDefaultValueRector\Fixture;
|
||||
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
|
@ -15,7 +15,7 @@ function argumentDefaultValue3()
|
|||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\Arguments\Rector\ClassMethod\ArgumentDefaultValueReplacerRector\Fixture;
|
||||
namespace Rector\Tests\Arguments\Rector\ClassMethod\ReplaceArgumentDefaultValueRector\Fixture;
|
||||
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
|
@ -2,13 +2,13 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\Arguments\Rector\ClassMethod\ArgumentDefaultValueReplacerRector;
|
||||
namespace Rector\Tests\Arguments\Rector\ClassMethod\ReplaceArgumentDefaultValueRector;
|
||||
|
||||
use Iterator;
|
||||
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
|
||||
final class ArgumentDefaultValueReplacerRectorTest extends AbstractRectorTestCase
|
||||
final class ReplaceArgumentDefaultValueRectorTest extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider provideData()
|
|
@ -2,46 +2,46 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Rector\Arguments\Rector\ClassMethod\ArgumentDefaultValueReplacerRector;
|
||||
use Rector\Arguments\ValueObject\ArgumentDefaultValueReplacer;
|
||||
use Rector\Arguments\Rector\ClassMethod\ReplaceArgumentDefaultValueRector;
|
||||
use Rector\Arguments\ValueObject\ReplaceArgumentDefaultValue;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
use Symplify\SymfonyPhpConfig\ValueObjectInliner;
|
||||
|
||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services = $containerConfigurator->services();
|
||||
$services->set(ArgumentDefaultValueReplacerRector::class)
|
||||
$services->set(ReplaceArgumentDefaultValueRector::class)
|
||||
->call('configure', [[
|
||||
ArgumentDefaultValueReplacerRector::REPLACED_ARGUMENTS => ValueObjectInliner::inline([
|
||||
ReplaceArgumentDefaultValueRector::REPLACED_ARGUMENTS => ValueObjectInliner::inline([
|
||||
|
||||
new ArgumentDefaultValueReplacer(
|
||||
new ReplaceArgumentDefaultValue(
|
||||
'Symfony\Component\DependencyInjection\Definition',
|
||||
'setScope',
|
||||
0,
|
||||
'Symfony\Component\DependencyInjection\ContainerBuilder::SCOPE_PROTOTYPE',
|
||||
false
|
||||
),
|
||||
new ArgumentDefaultValueReplacer('Symfony\Component\Yaml\Yaml', 'parse', 1, [
|
||||
new ReplaceArgumentDefaultValue('Symfony\Component\Yaml\Yaml', 'parse', 1, [
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
], 'Symfony\Component\Yaml\Yaml::PARSE_OBJECT_FOR_MAP'),
|
||||
new ArgumentDefaultValueReplacer('Symfony\Component\Yaml\Yaml', 'parse', 1, [
|
||||
new ReplaceArgumentDefaultValue('Symfony\Component\Yaml\Yaml', 'parse', 1, [
|
||||
false,
|
||||
true,
|
||||
], 'Symfony\Component\Yaml\Yaml::PARSE_OBJECT'),
|
||||
new ArgumentDefaultValueReplacer('Symfony\Component\Yaml\Yaml', 'parse', 1, false, 0),
|
||||
new ArgumentDefaultValueReplacer(
|
||||
new ReplaceArgumentDefaultValue('Symfony\Component\Yaml\Yaml', 'parse', 1, false, 0),
|
||||
new ReplaceArgumentDefaultValue(
|
||||
'Symfony\Component\Yaml\Yaml',
|
||||
'parse',
|
||||
1,
|
||||
true,
|
||||
'Symfony\Component\Yaml\Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE'
|
||||
),
|
||||
new ArgumentDefaultValueReplacer('Symfony\Component\Yaml\Yaml', 'dump', 3, [
|
||||
new ReplaceArgumentDefaultValue('Symfony\Component\Yaml\Yaml', 'dump', 3, [
|
||||
false,
|
||||
true,
|
||||
], 'Symfony\Component\Yaml\Yaml::DUMP_OBJECT'),
|
||||
new ArgumentDefaultValueReplacer(
|
||||
new ReplaceArgumentDefaultValue(
|
||||
'Symfony\Component\Yaml\Yaml',
|
||||
'dump',
|
||||
3,
|
|
@ -3,7 +3,7 @@
|
|||
declare(strict_types=1);
|
||||
|
||||
use Rector\Arguments\Rector\FuncCall\FunctionArgumentDefaultValueReplacerRector;
|
||||
use Rector\Arguments\ValueObject\FuncCallArgumentDefaultValueReplacer;
|
||||
use Rector\Arguments\ValueObject\ReplaceFuncCallArgumentDefaultValue;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
use Symplify\SymfonyPhpConfig\ValueObjectInliner;
|
||||
|
||||
|
@ -12,9 +12,9 @@ return static function (ContainerConfigurator $containerConfigurator): void {
|
|||
$services->set(FunctionArgumentDefaultValueReplacerRector::class)
|
||||
->call('configure', [[
|
||||
FunctionArgumentDefaultValueReplacerRector::REPLACED_ARGUMENTS => ValueObjectInliner::inline([
|
||||
new FuncCallArgumentDefaultValueReplacer('version_compare', 2, 'lte', 'le'),
|
||||
new FuncCallArgumentDefaultValueReplacer('version_compare', 2, '', '!='),
|
||||
new FuncCallArgumentDefaultValueReplacer(
|
||||
new ReplaceFuncCallArgumentDefaultValue('version_compare', 2, 'lte', 'le'),
|
||||
new ReplaceFuncCallArgumentDefaultValue('version_compare', 2, '', '!='),
|
||||
new ReplaceFuncCallArgumentDefaultValue(
|
||||
'some_function',
|
||||
0,
|
||||
true,
|
||||
|
|
|
@ -12,7 +12,7 @@ use PhpParser\Node\Expr\FuncCall;
|
|||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Expr\StaticCall;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use Rector\Arguments\Contract\ArgumentDefaultValueReplacerInterface;
|
||||
use Rector\Arguments\Contract\ReplaceArgumentDefaultValueInterface;
|
||||
use Rector\Core\PhpParser\Node\NodeFactory;
|
||||
use Rector\Core\PhpParser\Node\Value\ValueResolver;
|
||||
|
||||
|
@ -29,14 +29,14 @@ final class ArgumentDefaultValueReplacer
|
|||
*/
|
||||
public function processReplaces(
|
||||
Node $node,
|
||||
ArgumentDefaultValueReplacerInterface $argumentDefaultValueReplacer
|
||||
ReplaceArgumentDefaultValueInterface $replaceArgumentDefaultValue
|
||||
): ?Node {
|
||||
if ($node instanceof ClassMethod) {
|
||||
if (! isset($node->params[$argumentDefaultValueReplacer->getPosition()])) {
|
||||
if (! isset($node->params[$replaceArgumentDefaultValue->getPosition()])) {
|
||||
return null;
|
||||
}
|
||||
} elseif (isset($node->args[$argumentDefaultValueReplacer->getPosition()])) {
|
||||
$this->processArgs($node, $argumentDefaultValueReplacer);
|
||||
} elseif (isset($node->args[$replaceArgumentDefaultValue->getPosition()])) {
|
||||
$this->processArgs($node, $replaceArgumentDefaultValue);
|
||||
}
|
||||
|
||||
return $node;
|
||||
|
@ -45,18 +45,18 @@ final class ArgumentDefaultValueReplacer
|
|||
/**
|
||||
* @param MethodCall|StaticCall|FuncCall $expr
|
||||
*/
|
||||
private function processArgs(Expr $expr, ArgumentDefaultValueReplacerInterface $argumentDefaultValueReplacer): void
|
||||
private function processArgs(Expr $expr, ReplaceArgumentDefaultValueInterface $replaceArgumentDefaultValue): void
|
||||
{
|
||||
$position = $argumentDefaultValueReplacer->getPosition();
|
||||
$position = $replaceArgumentDefaultValue->getPosition();
|
||||
|
||||
$argValue = $this->valueResolver->getValue($expr->args[$position]->value);
|
||||
|
||||
if (is_scalar(
|
||||
$argumentDefaultValueReplacer->getValueBefore()
|
||||
) && $argValue === $argumentDefaultValueReplacer->getValueBefore()) {
|
||||
$expr->args[$position] = $this->normalizeValueToArgument($argumentDefaultValueReplacer->getValueAfter());
|
||||
} elseif (is_array($argumentDefaultValueReplacer->getValueBefore())) {
|
||||
$newArgs = $this->processArrayReplacement($expr->args, $argumentDefaultValueReplacer);
|
||||
$replaceArgumentDefaultValue->getValueBefore()
|
||||
) && $argValue === $replaceArgumentDefaultValue->getValueBefore()) {
|
||||
$expr->args[$position] = $this->normalizeValueToArgument($replaceArgumentDefaultValue->getValueAfter());
|
||||
} elseif (is_array($replaceArgumentDefaultValue->getValueBefore())) {
|
||||
$newArgs = $this->processArrayReplacement($expr->args, $replaceArgumentDefaultValue);
|
||||
|
||||
if ($newArgs) {
|
||||
$expr->args = $newArgs;
|
||||
|
@ -86,21 +86,21 @@ final class ArgumentDefaultValueReplacer
|
|||
*/
|
||||
private function processArrayReplacement(
|
||||
array $argumentNodes,
|
||||
ArgumentDefaultValueReplacerInterface $argumentDefaultValueReplacer
|
||||
ReplaceArgumentDefaultValueInterface $replaceArgumentDefaultValue
|
||||
): ?array {
|
||||
$argumentValues = $this->resolveArgumentValuesToBeforeRecipe($argumentNodes, $argumentDefaultValueReplacer);
|
||||
if ($argumentValues !== $argumentDefaultValueReplacer->getValueBefore()) {
|
||||
$argumentValues = $this->resolveArgumentValuesToBeforeRecipe($argumentNodes, $replaceArgumentDefaultValue);
|
||||
if ($argumentValues !== $replaceArgumentDefaultValue->getValueBefore()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (is_string($argumentDefaultValueReplacer->getValueAfter())) {
|
||||
$argumentNodes[$argumentDefaultValueReplacer->getPosition()] = $this->normalizeValueToArgument(
|
||||
$argumentDefaultValueReplacer->getValueAfter()
|
||||
if (is_string($replaceArgumentDefaultValue->getValueAfter())) {
|
||||
$argumentNodes[$replaceArgumentDefaultValue->getPosition()] = $this->normalizeValueToArgument(
|
||||
$replaceArgumentDefaultValue->getValueAfter()
|
||||
);
|
||||
|
||||
// clear following arguments
|
||||
$argumentCountToClear = count($argumentDefaultValueReplacer->getValueBefore());
|
||||
for ($i = $argumentDefaultValueReplacer->getPosition() + 1; $i <= $argumentDefaultValueReplacer->getPosition() + $argumentCountToClear; ++$i) {
|
||||
$argumentCountToClear = count($replaceArgumentDefaultValue->getValueBefore());
|
||||
for ($i = $replaceArgumentDefaultValue->getPosition() + 1; $i <= $replaceArgumentDefaultValue->getPosition() + $argumentCountToClear; ++$i) {
|
||||
unset($argumentNodes[$i]);
|
||||
}
|
||||
}
|
||||
|
@ -114,20 +114,20 @@ final class ArgumentDefaultValueReplacer
|
|||
*/
|
||||
private function resolveArgumentValuesToBeforeRecipe(
|
||||
array $argumentNodes,
|
||||
ArgumentDefaultValueReplacerInterface $argumentDefaultValueReplacer
|
||||
ReplaceArgumentDefaultValueInterface $replaceArgumentDefaultValue
|
||||
): array {
|
||||
$argumentValues = [];
|
||||
|
||||
/** @var mixed[] $valueBefore */
|
||||
$valueBefore = $argumentDefaultValueReplacer->getValueBefore();
|
||||
$valueBefore = $replaceArgumentDefaultValue->getValueBefore();
|
||||
$beforeArgumentCount = count($valueBefore);
|
||||
|
||||
for ($i = 0; $i < $beforeArgumentCount; ++$i) {
|
||||
if (! isset($argumentNodes[$argumentDefaultValueReplacer->getPosition() + $i])) {
|
||||
if (! isset($argumentNodes[$replaceArgumentDefaultValue->getPosition() + $i])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$nextArg = $argumentNodes[$argumentDefaultValueReplacer->getPosition() + $i];
|
||||
$nextArg = $argumentNodes[$replaceArgumentDefaultValue->getPosition() + $i];
|
||||
$argumentValues[] = $this->valueResolver->getValue($nextArg->value);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace Rector\Arguments\Contract;
|
||||
|
||||
interface ArgumentDefaultValueReplacerInterface
|
||||
interface ReplaceArgumentDefaultValueInterface
|
||||
{
|
||||
public function getPosition(): int;
|
||||
|
|
@ -8,7 +8,8 @@ use PhpParser\Node;
|
|||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Expr\StaticCall;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use Rector\Arguments\ValueObject\ArgumentDefaultValueReplacer;
|
||||
use Rector\Arguments\ArgumentDefaultValueReplacer;
|
||||
use Rector\Arguments\ValueObject\ReplaceArgumentDefaultValue;
|
||||
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample;
|
||||
|
@ -16,9 +17,9 @@ use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
|||
use Webmozart\Assert\Assert;
|
||||
|
||||
/**
|
||||
* @see \Rector\Tests\Arguments\Rector\ClassMethod\ArgumentDefaultValueReplacerRector\ArgumentDefaultValueReplacerRectorTest
|
||||
* @see \Rector\Tests\Arguments\Rector\ClassMethod\ReplaceArgumentDefaultValueRector\ReplaceArgumentDefaultValueRectorTest
|
||||
*/
|
||||
final class ArgumentDefaultValueReplacerRector extends AbstractRector implements ConfigurableRectorInterface
|
||||
final class ReplaceArgumentDefaultValueRector extends AbstractRector implements ConfigurableRectorInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
|
@ -26,12 +27,12 @@ final class ArgumentDefaultValueReplacerRector extends AbstractRector implements
|
|||
public const REPLACED_ARGUMENTS = 'replaced_arguments';
|
||||
|
||||
/**
|
||||
* @var ArgumentDefaultValueReplacer[]
|
||||
* @var ReplaceArgumentDefaultValue[]
|
||||
*/
|
||||
private array $replacedArguments = [];
|
||||
|
||||
public function __construct(
|
||||
private \Rector\Arguments\ArgumentDefaultValueReplacer $argumentDefaultValueReplacer
|
||||
private ArgumentDefaultValueReplacer $argumentDefaultValueReplacer
|
||||
) {
|
||||
}
|
||||
|
||||
|
@ -53,7 +54,7 @@ CODE_SAMPLE
|
|||
,
|
||||
[
|
||||
self::REPLACED_ARGUMENTS => [
|
||||
new ArgumentDefaultValueReplacer(
|
||||
new ReplaceArgumentDefaultValue(
|
||||
'SomeExampleClass',
|
||||
'someMethod',
|
||||
0,
|
||||
|
@ -99,12 +100,12 @@ CODE_SAMPLE
|
|||
}
|
||||
|
||||
/**
|
||||
* @param array<string, ArgumentDefaultValueReplacer[]> $configuration
|
||||
* @param array<string, ReplaceArgumentDefaultValue[]> $configuration
|
||||
*/
|
||||
public function configure(array $configuration): void
|
||||
{
|
||||
$replacedArguments = $configuration[self::REPLACED_ARGUMENTS] ?? [];
|
||||
Assert::allIsInstanceOf($replacedArguments, ArgumentDefaultValueReplacer::class);
|
||||
Assert::allIsInstanceOf($replacedArguments, ReplaceArgumentDefaultValue::class);
|
||||
$this->replacedArguments = $replacedArguments;
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@ namespace Rector\Arguments\Rector\FuncCall;
|
|||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\FuncCall;
|
||||
use Rector\Arguments\ArgumentDefaultValueReplacer;
|
||||
use Rector\Arguments\ValueObject\FuncCallArgumentDefaultValueReplacer;
|
||||
use Rector\Arguments\ValueObject\ReplaceFuncCallArgumentDefaultValue;
|
||||
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample;
|
||||
|
@ -28,7 +28,7 @@ final class FunctionArgumentDefaultValueReplacerRector extends AbstractRector im
|
|||
public const REPLACED_ARGUMENTS = 'replaced_arguments';
|
||||
|
||||
/**
|
||||
* @var FuncCallArgumentDefaultValueReplacer[]
|
||||
* @var ReplaceFuncCallArgumentDefaultValue[]
|
||||
*/
|
||||
private mixed $replacedArguments = [];
|
||||
|
||||
|
@ -52,7 +52,7 @@ CODE_SAMPLE
|
|||
,
|
||||
[
|
||||
self::REPLACED_ARGUMENTS => [
|
||||
new FuncCallArgumentDefaultValueReplacer('version_compare', 2, 'gte', 'ge',),
|
||||
new ReplaceFuncCallArgumentDefaultValue('version_compare', 2, 'gte', 'ge',),
|
||||
],
|
||||
]
|
||||
),
|
||||
|
@ -84,12 +84,12 @@ CODE_SAMPLE
|
|||
}
|
||||
|
||||
/**
|
||||
* @param array<string, FuncCallArgumentDefaultValueReplacer[]> $configuration
|
||||
* @param array<string, ReplaceFuncCallArgumentDefaultValue[]> $configuration
|
||||
*/
|
||||
public function configure(array $configuration): void
|
||||
{
|
||||
$replacedArguments = $configuration[self::REPLACED_ARGUMENTS] ?? [];
|
||||
Assert::allIsInstanceOf($replacedArguments, FuncCallArgumentDefaultValueReplacer::class);
|
||||
Assert::allIsInstanceOf($replacedArguments, ReplaceFuncCallArgumentDefaultValue::class);
|
||||
$this->replacedArguments = $replacedArguments;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,9 +5,9 @@ declare(strict_types=1);
|
|||
namespace Rector\Arguments\ValueObject;
|
||||
|
||||
use PHPStan\Type\ObjectType;
|
||||
use Rector\Arguments\Contract\ArgumentDefaultValueReplacerInterface;
|
||||
use Rector\Arguments\Contract\ReplaceArgumentDefaultValueInterface;
|
||||
|
||||
final class ArgumentDefaultValueReplacer implements ArgumentDefaultValueReplacerInterface
|
||||
final class ReplaceArgumentDefaultValue implements ReplaceArgumentDefaultValueInterface
|
||||
{
|
||||
/**
|
||||
* @param mixed $valueBefore
|
|
@ -4,9 +4,9 @@ declare(strict_types=1);
|
|||
|
||||
namespace Rector\Arguments\ValueObject;
|
||||
|
||||
use Rector\Arguments\Contract\ArgumentDefaultValueReplacerInterface;
|
||||
use Rector\Arguments\Contract\ReplaceArgumentDefaultValueInterface;
|
||||
|
||||
final class FuncCallArgumentDefaultValueReplacer implements ArgumentDefaultValueReplacerInterface
|
||||
final class ReplaceFuncCallArgumentDefaultValue implements ReplaceArgumentDefaultValueInterface
|
||||
{
|
||||
/**
|
||||
* @param mixed $valueBefore
|
|
@ -1,92 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\CodeQuality\NodeFactory;
|
||||
|
||||
use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Expr\Closure;
|
||||
use PhpParser\Node\Expr\ClosureUse;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Expr\PropertyFetch;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use PhpParser\Node\Param;
|
||||
use PhpParser\Node\Stmt\Expression;
|
||||
use PhpParser\Node\Stmt\Return_;
|
||||
use PHPStan\Reflection\FunctionVariantWithPhpDocs;
|
||||
use PHPStan\Reflection\ParameterReflection;
|
||||
use PHPStan\Reflection\Php\PhpMethodReflection;
|
||||
use PHPStan\Type\MixedType;
|
||||
use PHPStan\Type\VoidType;
|
||||
use Rector\Core\PhpParser\Node\NodeFactory;
|
||||
use Rector\NodeNameResolver\NodeNameResolver;
|
||||
use Rector\StaticTypeMapper\StaticTypeMapper;
|
||||
|
||||
final class AnonymousFunctionFactory
|
||||
{
|
||||
public function __construct(
|
||||
private NodeFactory $nodeFactory,
|
||||
private NodeNameResolver $nodeNameResolver,
|
||||
private StaticTypeMapper $staticTypeMapper
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Variable|PropertyFetch $expr
|
||||
*/
|
||||
public function create(PhpMethodReflection $phpMethodReflection, Expr $expr): Closure
|
||||
{
|
||||
/** @var FunctionVariantWithPhpDocs $functionVariantWithPhpDoc */
|
||||
$functionVariantWithPhpDoc = $phpMethodReflection->getVariants()[0];
|
||||
|
||||
$anonymousFunction = new Closure();
|
||||
$newParams = $this->createParams($functionVariantWithPhpDoc->getParameters());
|
||||
|
||||
$anonymousFunction->params = $newParams;
|
||||
|
||||
$innerMethodCall = new MethodCall($expr, $phpMethodReflection->getName());
|
||||
$innerMethodCall->args = $this->nodeFactory->createArgsFromParams($newParams);
|
||||
|
||||
if (! $functionVariantWithPhpDoc->getReturnType() instanceof MixedType) {
|
||||
$returnType = $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode(
|
||||
$functionVariantWithPhpDoc->getReturnType()
|
||||
);
|
||||
$anonymousFunction->returnType = $returnType;
|
||||
}
|
||||
|
||||
// does method return something?
|
||||
|
||||
if (! $functionVariantWithPhpDoc->getReturnType() instanceof VoidType) {
|
||||
$anonymousFunction->stmts[] = new Return_($innerMethodCall);
|
||||
} else {
|
||||
$anonymousFunction->stmts[] = new Expression($innerMethodCall);
|
||||
}
|
||||
|
||||
if ($expr instanceof Variable && ! $this->nodeNameResolver->isName($expr, 'this')) {
|
||||
$anonymousFunction->uses[] = new ClosureUse($expr);
|
||||
}
|
||||
|
||||
return $anonymousFunction;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ParameterReflection[] $parameterReflections
|
||||
* @return Param[]
|
||||
*/
|
||||
private function createParams(array $parameterReflections): array
|
||||
{
|
||||
$params = [];
|
||||
foreach ($parameterReflections as $parameterReflection) {
|
||||
$param = new Param(new Variable($parameterReflection->getName()));
|
||||
|
||||
if (! $parameterReflection->getType() instanceof MixedType) {
|
||||
$paramType = $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode($parameterReflection->getType());
|
||||
$param->type = $paramType;
|
||||
}
|
||||
|
||||
$params[] = $param;
|
||||
}
|
||||
|
||||
return $params;
|
||||
}
|
||||
}
|
|
@ -14,9 +14,9 @@ use PhpParser\Node\Expr\Variable;
|
|||
use PhpParser\Node\Scalar\String_;
|
||||
use PHPStan\Reflection\Php\PhpMethodReflection;
|
||||
use Rector\CodeQuality\NodeAnalyzer\CallableClassMethodMatcher;
|
||||
use Rector\CodeQuality\NodeFactory\AnonymousFunctionFactory;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\Php72\NodeFactory\AnonymousFunctionFactory;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
|
||||
|
@ -125,7 +125,7 @@ CODE_SAMPLE
|
|||
return null;
|
||||
}
|
||||
|
||||
return $this->anonymousFunctionFactory->create($phpMethodReflection, $objectVariable);
|
||||
return $this->anonymousFunctionFactory->createFromPhpMethodReflection($phpMethodReflection, $objectVariable);
|
||||
}
|
||||
|
||||
private function shouldSkipArray(Array_ $array): bool
|
||||
|
|
|
@ -10,8 +10,8 @@ use PhpParser\Node\Expr\FuncCall;
|
|||
use PhpParser\Node\Expr\Variable;
|
||||
use PhpParser\Node\Stmt\For_;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Naming\Naming\VariableNaming;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\Php70\NodeAnalyzer\VariableNaming;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
|
||||
|
|
|
@ -20,8 +20,8 @@ use PHPStan\Type\ObjectType;
|
|||
use PHPStan\Type\Type;
|
||||
use Rector\Core\Exception\ShouldNotHappenException;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Naming\Naming\VariableNaming;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\Php70\NodeAnalyzer\VariableNaming;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
use Traversable;
|
||||
|
|
|
@ -21,8 +21,8 @@ use PhpParser\Node\Expr\Variable;
|
|||
use PhpParser\Node\Name;
|
||||
use PhpParser\Node\Scalar\String_;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Naming\Naming\VariableNaming;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\Php70\NodeAnalyzer\VariableNaming;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
|
||||
|
|
|
@ -147,7 +147,7 @@ CODE_SAMPLE
|
|||
$stmts = [];
|
||||
|
||||
if ($node instanceof Expression) {
|
||||
/** @var Assign */
|
||||
/** @var Assign $assign */
|
||||
$assign = $node->expr;
|
||||
$stmts[] = new Expression(new Assign($assign->var, $matchArm->body));
|
||||
$stmts[] = new Break_();
|
||||
|
|
|
@ -13,8 +13,8 @@ use PhpParser\Node\Expr\PropertyFetch;
|
|||
use PhpParser\Node\Expr\Ternary;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Naming\Naming\VariableNaming;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\Php70\NodeAnalyzer\VariableNaming;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
|
||||
|
|
|
@ -4,8 +4,10 @@ declare(strict_types=1);
|
|||
|
||||
namespace Rector\Naming\Naming;
|
||||
|
||||
use Nette\Utils\Strings;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Arg;
|
||||
use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Expr\ArrayDimFetch;
|
||||
use PhpParser\Node\Expr\Cast;
|
||||
use PhpParser\Node\Expr\FuncCall;
|
||||
|
@ -18,6 +20,7 @@ use PhpParser\Node\Expr\Ternary;
|
|||
use PhpParser\Node\Name;
|
||||
use PhpParser\Node\Scalar;
|
||||
use PhpParser\Node\Scalar\String_;
|
||||
use PHPStan\Analyser\Scope;
|
||||
use PHPStan\Type\ThisType;
|
||||
use PHPStan\Type\Type;
|
||||
use Rector\Core\Exception\NotImplementedYetException;
|
||||
|
@ -31,15 +34,15 @@ final class VariableNaming
|
|||
public function __construct(
|
||||
private NodeNameResolver $nodeNameResolver,
|
||||
private ValueResolver $valueResolver,
|
||||
private NodeTypeResolver $nodeTypeResolver
|
||||
private NodeTypeResolver $nodeTypeResolver,
|
||||
) {
|
||||
}
|
||||
|
||||
public function resolveFromNode(Node $node): ?string
|
||||
{
|
||||
$nodeType = $this->nodeTypeResolver->getStaticType($node);
|
||||
return $this->resolveFromNodeAndType($node, $nodeType);
|
||||
}
|
||||
// public function resolveFromNode(Node $node): ?string
|
||||
// {
|
||||
// $nodeType = $this->nodeTypeResolver->getStaticType($node);
|
||||
// return $this->resolveFromNodeAndType($node, $nodeType);
|
||||
// }
|
||||
|
||||
public function resolveFromNodeAndType(Node $node, Type $type): ?string
|
||||
{
|
||||
|
@ -58,6 +61,79 @@ final class VariableNaming
|
|||
return (string) $stringy->camelize();
|
||||
}
|
||||
|
||||
public function resolveFromNodeWithScopeCountAndFallbackName(
|
||||
Expr $expr,
|
||||
Scope $scope,
|
||||
string $fallbackName
|
||||
): string {
|
||||
$name = $this->resolveFromNode($expr);
|
||||
if ($name === null) {
|
||||
$name = $fallbackName;
|
||||
}
|
||||
|
||||
if (\str_contains($name, '\\')) {
|
||||
$name = (string) Strings::after($name, '\\', - 1);
|
||||
}
|
||||
|
||||
$countedValueName = $this->createCountedValueName($name, $scope);
|
||||
return lcfirst($countedValueName);
|
||||
}
|
||||
|
||||
public function createCountedValueName(string $valueName, ?Scope $scope): string
|
||||
{
|
||||
if ($scope === null) {
|
||||
return $valueName;
|
||||
}
|
||||
|
||||
// make sure variable name is unique
|
||||
if (! $scope->hasVariableType($valueName)->yes()) {
|
||||
return $valueName;
|
||||
}
|
||||
|
||||
// we need to add number suffix until the variable is unique
|
||||
$i = 2;
|
||||
$countedValueNamePart = $valueName;
|
||||
while ($scope->hasVariableType($valueName)->yes()) {
|
||||
$valueName = $countedValueNamePart . $i;
|
||||
++$i;
|
||||
}
|
||||
|
||||
return $valueName;
|
||||
}
|
||||
|
||||
public function resolveFromFuncCallFirstArgumentWithSuffix(
|
||||
FuncCall $funcCall,
|
||||
string $suffix,
|
||||
string $fallbackName,
|
||||
?Scope $scope
|
||||
): string {
|
||||
$bareName = $this->resolveBareFuncCallArgumentName($funcCall, $fallbackName, $suffix);
|
||||
return $this->createCountedValueName($bareName, $scope);
|
||||
}
|
||||
|
||||
// private function resolveFromNodeAndType(Node $node, Type $type): ?string
|
||||
// {
|
||||
// $variableName = $this->resolveBareFromNode($node);
|
||||
// if ($variableName === null) {
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// // adjust static to specific class
|
||||
// if ($variableName === 'this' && $type instanceof ThisType) {
|
||||
// $shortClassName = $this->nodeNameResolver->getShortName($type->getClassName());
|
||||
// $variableName = lcfirst($shortClassName);
|
||||
// }
|
||||
//
|
||||
// $stringy = new Stringy($variableName);
|
||||
// return (string) $stringy->camelize();
|
||||
// }
|
||||
|
||||
public function resolveFromNode(Node $node): ?string
|
||||
{
|
||||
$nodeType = $this->nodeTypeResolver->getStaticType($node);
|
||||
return $this->resolveFromNodeAndType($node, $nodeType);
|
||||
}
|
||||
|
||||
private function resolveBareFromNode(Node $node): ?string
|
||||
{
|
||||
$node = $this->unwrapNode($node);
|
||||
|
@ -98,22 +174,22 @@ final class VariableNaming
|
|||
return null;
|
||||
}
|
||||
|
||||
private function unwrapNode(Node $node): ?Node
|
||||
{
|
||||
if ($node instanceof Arg) {
|
||||
return $node->value;
|
||||
}
|
||||
|
||||
if ($node instanceof Cast) {
|
||||
return $node->expr;
|
||||
}
|
||||
|
||||
if ($node instanceof Ternary) {
|
||||
return $node->if;
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
// private function unwrapNode(Node $node): ?Node
|
||||
// {
|
||||
// if ($node instanceof Arg) {
|
||||
// return $node->value;
|
||||
// }
|
||||
//
|
||||
// if ($node instanceof Cast) {
|
||||
// return $node->expr;
|
||||
// }
|
||||
//
|
||||
// if ($node instanceof Ternary) {
|
||||
// return $node->if;
|
||||
// }
|
||||
//
|
||||
// return $node;
|
||||
// }
|
||||
|
||||
private function resolveParamNameFromArrayDimFetch(ArrayDimFetch $arrayDimFetch): ?string
|
||||
{
|
||||
|
@ -179,4 +255,145 @@ final class VariableNaming
|
|||
|
||||
throw new NotImplementedYetException();
|
||||
}
|
||||
|
||||
private function unwrapNode(Node $node): ?Node
|
||||
{
|
||||
if ($node instanceof Arg) {
|
||||
return $node->value;
|
||||
}
|
||||
|
||||
if ($node instanceof Cast) {
|
||||
return $node->expr;
|
||||
}
|
||||
|
||||
if ($node instanceof Ternary) {
|
||||
return $node->if;
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
// private function resolveParamNameFromArrayDimFetch(ArrayDimFetch $arrayDimFetch): ?string
|
||||
// {
|
||||
// while ($arrayDimFetch instanceof ArrayDimFetch) {
|
||||
// if ($arrayDimFetch->dim instanceof Scalar) {
|
||||
// $valueName = $this->nodeNameResolver->getName($arrayDimFetch->var);
|
||||
// $dimName = $this->valueResolver->getValue($arrayDimFetch->dim);
|
||||
//
|
||||
// $stringy = new Stringy($dimName);
|
||||
// $dimName = (string) $stringy->upperCamelize();
|
||||
//
|
||||
// return $valueName . $dimName;
|
||||
// }
|
||||
//
|
||||
// $arrayDimFetch = $arrayDimFetch->var;
|
||||
// }
|
||||
//
|
||||
// return $this->resolveBareFromNode($arrayDimFetch);
|
||||
// }
|
||||
|
||||
// private function resolveBareFromNode(Node $node): ?string
|
||||
// {
|
||||
// $node = $this->unwrapNode($node);
|
||||
//
|
||||
// if ($node instanceof ArrayDimFetch) {
|
||||
// return $this->resolveParamNameFromArrayDimFetch($node);
|
||||
// }
|
||||
//
|
||||
// if ($node instanceof PropertyFetch) {
|
||||
// return $this->resolveFromPropertyFetch($node);
|
||||
// }
|
||||
//
|
||||
// if ($node instanceof MethodCall || $node instanceof NullsafeMethodCall || $node instanceof StaticCall) {
|
||||
// return $this->resolveFromMethodCall($node);
|
||||
// }
|
||||
//
|
||||
// if ($node instanceof New_) {
|
||||
// return $this->resolveFromNew($node);
|
||||
// }
|
||||
//
|
||||
// if ($node instanceof FuncCall) {
|
||||
// return $this->resolveFromNode($node->name);
|
||||
// }
|
||||
//
|
||||
// if (! $node instanceof Node) {
|
||||
// throw new NotImplementedYetException();
|
||||
// }
|
||||
//
|
||||
// $paramName = $this->nodeNameResolver->getName($node);
|
||||
// if ($paramName !== null) {
|
||||
// return $paramName;
|
||||
// }
|
||||
//
|
||||
// if ($node instanceof String_) {
|
||||
// return $node->value;
|
||||
// }
|
||||
//
|
||||
// return null;
|
||||
// }
|
||||
|
||||
// private function resolveFromNew(New_ $new): string
|
||||
// {
|
||||
// if ($new->class instanceof Name) {
|
||||
// $className = $this->nodeNameResolver->getName($new->class);
|
||||
// return $this->nodeNameResolver->getShortName($className);
|
||||
// }
|
||||
//
|
||||
// throw new NotImplementedYetException();
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * @param MethodCall|NullsafeMethodCall|StaticCall $node
|
||||
// */
|
||||
// private function resolveFromMethodCall(Node $node): ?string
|
||||
// {
|
||||
// if ($node->name instanceof MethodCall) {
|
||||
// return $this->resolveFromMethodCall($node->name);
|
||||
// }
|
||||
//
|
||||
// $methodName = $this->nodeNameResolver->getName($node->name);
|
||||
// if (! is_string($methodName)) {
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// return $methodName;
|
||||
// }
|
||||
//
|
||||
// private function resolveFromPropertyFetch(PropertyFetch $propertyFetch): string
|
||||
// {
|
||||
// $varName = $this->nodeNameResolver->getName($propertyFetch->var);
|
||||
// if (! is_string($varName)) {
|
||||
// throw new NotImplementedYetException();
|
||||
// }
|
||||
//
|
||||
// $propertyName = $this->nodeNameResolver->getName($propertyFetch->name);
|
||||
// if (! is_string($propertyName)) {
|
||||
// throw new NotImplementedYetException();
|
||||
// }
|
||||
//
|
||||
// if ($varName === 'this') {
|
||||
// return $propertyName;
|
||||
// }
|
||||
//
|
||||
// return $varName . ucfirst($propertyName);
|
||||
// }
|
||||
|
||||
private function resolveBareFuncCallArgumentName(
|
||||
FuncCall $funcCall,
|
||||
string $fallbackName,
|
||||
string $suffix
|
||||
): string {
|
||||
$argumentValue = $funcCall->args[0]->value;
|
||||
if ($argumentValue instanceof MethodCall || $argumentValue instanceof StaticCall) {
|
||||
$name = $this->nodeNameResolver->getName($argumentValue->name);
|
||||
} else {
|
||||
$name = $this->nodeNameResolver->getName($argumentValue);
|
||||
}
|
||||
|
||||
if ($name === null) {
|
||||
return $fallbackName;
|
||||
}
|
||||
|
||||
return $name . $suffix;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Php55\NodeFactory;
|
||||
|
||||
use Nette\Utils\Strings;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Expr\ArrayDimFetch;
|
||||
use PhpParser\Node\Expr\Closure;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use PhpParser\Node\Param;
|
||||
use PhpParser\Node\Scalar\LNumber;
|
||||
use PhpParser\Node\Scalar\String_;
|
||||
use PhpParser\Node\Stmt\Expression;
|
||||
use PhpParser\Node\Stmt\Return_;
|
||||
use PhpParser\Parser;
|
||||
use Rector\Core\Exception\ShouldNotHappenException;
|
||||
use Symplify\Astral\NodeTraverser\SimpleCallableNodeTraverser;
|
||||
|
||||
final class AnonymousFunctionNodeFactory
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
* @see https://regex101.com/r/jkLLlM/2
|
||||
*/
|
||||
private const DIM_FETCH_REGEX = '#(\\$|\\\\|\\x0)(?<number>\d+)#';
|
||||
|
||||
public function __construct(
|
||||
private SimpleCallableNodeTraverser $simpleCallableNodeTraverser,
|
||||
private Parser $parser
|
||||
) {
|
||||
}
|
||||
|
||||
public function createAnonymousFunctionFromString(Expr $expr): ?Closure
|
||||
{
|
||||
if (! $expr instanceof String_) {
|
||||
// not supported yet
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
$phpCode = '<?php ' . $expr->value . ';';
|
||||
$contentNodes = (array) $this->parser->parse($phpCode);
|
||||
|
||||
$anonymousFunction = new Closure();
|
||||
|
||||
$firstNode = $contentNodes[0] ?? null;
|
||||
if (! $firstNode instanceof Expression) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$stmt = $firstNode->expr;
|
||||
|
||||
$this->simpleCallableNodeTraverser->traverseNodesWithCallable($stmt, function (Node $node): Node {
|
||||
if (! $node instanceof String_) {
|
||||
return $node;
|
||||
}
|
||||
|
||||
$match = Strings::match($node->value, self::DIM_FETCH_REGEX);
|
||||
if (! $match) {
|
||||
return $node;
|
||||
}
|
||||
|
||||
$matchesVariable = new Variable('matches');
|
||||
|
||||
return new ArrayDimFetch($matchesVariable, new LNumber((int) $match['number']));
|
||||
});
|
||||
|
||||
$anonymousFunction->stmts[] = new Return_($stmt);
|
||||
$anonymousFunction->params[] = new Param(new Variable('matches'));
|
||||
|
||||
return $anonymousFunction;
|
||||
}
|
||||
}
|
|
@ -10,8 +10,8 @@ use PhpParser\Node\Expr\Closure;
|
|||
use PhpParser\Node\Expr\FuncCall;
|
||||
use PhpParser\Node\Name;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Php55\NodeFactory\AnonymousFunctionNodeFactory;
|
||||
use Rector\Php55\RegexMatcher;
|
||||
use Rector\Php72\NodeFactory\AnonymousFunctionFactory;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
|
||||
|
@ -23,7 +23,7 @@ use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
|||
final class PregReplaceEModifierRector extends AbstractRector
|
||||
{
|
||||
public function __construct(
|
||||
private AnonymousFunctionNodeFactory $anonymousFunctionNodeFactory,
|
||||
private AnonymousFunctionFactory $anonymousFunctionFactory,
|
||||
private RegexMatcher $regexMatcher
|
||||
) {
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ CODE_SAMPLE
|
|||
}
|
||||
|
||||
$secondArgumentValue = $node->args[1]->value;
|
||||
$anonymousFunction = $this->anonymousFunctionNodeFactory->createAnonymousFunctionFromString(
|
||||
$anonymousFunction = $this->anonymousFunctionFactory->createAnonymousFunctionFromString(
|
||||
$secondArgumentValue
|
||||
);
|
||||
if (! $anonymousFunction instanceof Closure) {
|
||||
|
|
|
@ -1,257 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Php70\NodeAnalyzer;
|
||||
|
||||
use Nette\Utils\Strings;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Arg;
|
||||
use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Expr\ArrayDimFetch;
|
||||
use PhpParser\Node\Expr\Cast;
|
||||
use PhpParser\Node\Expr\FuncCall;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Expr\New_;
|
||||
use PhpParser\Node\Expr\NullsafeMethodCall;
|
||||
use PhpParser\Node\Expr\PropertyFetch;
|
||||
use PhpParser\Node\Expr\StaticCall;
|
||||
use PhpParser\Node\Expr\Ternary;
|
||||
use PhpParser\Node\Name;
|
||||
use PhpParser\Node\Scalar;
|
||||
use PhpParser\Node\Scalar\String_;
|
||||
use PHPStan\Analyser\Scope;
|
||||
use PHPStan\Type\ThisType;
|
||||
use PHPStan\Type\Type;
|
||||
use Rector\Core\Exception\NotImplementedYetException;
|
||||
use Rector\Core\PhpParser\Node\Value\ValueResolver;
|
||||
use Rector\NodeNameResolver\NodeNameResolver;
|
||||
use Rector\NodeTypeResolver\NodeTypeResolver;
|
||||
use Stringy\Stringy;
|
||||
|
||||
/**
|
||||
* @todo extract to own service with collector
|
||||
*/
|
||||
final class VariableNaming
|
||||
{
|
||||
public function __construct(
|
||||
private NodeTypeResolver $nodeTypeResolver,
|
||||
private NodeNameResolver $nodeNameResolver,
|
||||
private ValueResolver $valueResolver
|
||||
) {
|
||||
}
|
||||
|
||||
public function resolveFromNodeWithScopeCountAndFallbackName(
|
||||
Expr $expr,
|
||||
Scope $scope,
|
||||
string $fallbackName
|
||||
): string {
|
||||
$name = $this->resolveFromNode($expr);
|
||||
if ($name === null) {
|
||||
$name = $fallbackName;
|
||||
}
|
||||
|
||||
if (\str_contains($name, '\\')) {
|
||||
$name = (string) Strings::after($name, '\\', - 1);
|
||||
}
|
||||
|
||||
$countedValueName = $this->createCountedValueName($name, $scope);
|
||||
return lcfirst($countedValueName);
|
||||
}
|
||||
|
||||
public function createCountedValueName(string $valueName, ?Scope $scope): string
|
||||
{
|
||||
if ($scope === null) {
|
||||
return $valueName;
|
||||
}
|
||||
|
||||
// make sure variable name is unique
|
||||
if (! $scope->hasVariableType($valueName)->yes()) {
|
||||
return $valueName;
|
||||
}
|
||||
|
||||
// we need to add number suffix until the variable is unique
|
||||
$i = 2;
|
||||
$countedValueNamePart = $valueName;
|
||||
while ($scope->hasVariableType($valueName)->yes()) {
|
||||
$valueName = $countedValueNamePart . $i;
|
||||
++$i;
|
||||
}
|
||||
|
||||
return $valueName;
|
||||
}
|
||||
|
||||
public function resolveFromNodeAndType(Node $node, Type $type): ?string
|
||||
{
|
||||
$variableName = $this->resolveBareFromNode($node);
|
||||
if ($variableName === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// adjust static to specific class
|
||||
if ($variableName === 'this' && $type instanceof ThisType) {
|
||||
$shortClassName = $this->nodeNameResolver->getShortName($type->getClassName());
|
||||
$variableName = lcfirst($shortClassName);
|
||||
}
|
||||
|
||||
$stringy = new Stringy($variableName);
|
||||
return (string) $stringy->camelize();
|
||||
}
|
||||
|
||||
public function resolveFromFuncCallFirstArgumentWithSuffix(
|
||||
FuncCall $funcCall,
|
||||
string $suffix,
|
||||
string $fallbackName,
|
||||
?Scope $scope
|
||||
): string {
|
||||
$bareName = $this->resolveBareFuncCallArgumentName($funcCall, $fallbackName, $suffix);
|
||||
return $this->createCountedValueName($bareName, $scope);
|
||||
}
|
||||
|
||||
private function resolveFromNode(Node $node): ?string
|
||||
{
|
||||
$nodeType = $this->nodeTypeResolver->getStaticType($node);
|
||||
return $this->resolveFromNodeAndType($node, $nodeType);
|
||||
}
|
||||
|
||||
private function unwrapNode(Node $node): ?Node
|
||||
{
|
||||
if ($node instanceof Arg) {
|
||||
return $node->value;
|
||||
}
|
||||
|
||||
if ($node instanceof Cast) {
|
||||
return $node->expr;
|
||||
}
|
||||
|
||||
if ($node instanceof Ternary) {
|
||||
return $node->if;
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
private function resolveParamNameFromArrayDimFetch(ArrayDimFetch $arrayDimFetch): ?string
|
||||
{
|
||||
while ($arrayDimFetch instanceof ArrayDimFetch) {
|
||||
if ($arrayDimFetch->dim instanceof Scalar) {
|
||||
$valueName = $this->nodeNameResolver->getName($arrayDimFetch->var);
|
||||
$dimName = $this->valueResolver->getValue($arrayDimFetch->dim);
|
||||
|
||||
$stringy = new Stringy($dimName);
|
||||
$dimName = (string) $stringy->upperCamelize();
|
||||
|
||||
return $valueName . $dimName;
|
||||
}
|
||||
|
||||
$arrayDimFetch = $arrayDimFetch->var;
|
||||
}
|
||||
|
||||
return $this->resolveBareFromNode($arrayDimFetch);
|
||||
}
|
||||
|
||||
private function resolveBareFromNode(Node $node): ?string
|
||||
{
|
||||
$node = $this->unwrapNode($node);
|
||||
|
||||
if ($node instanceof ArrayDimFetch) {
|
||||
return $this->resolveParamNameFromArrayDimFetch($node);
|
||||
}
|
||||
|
||||
if ($node instanceof PropertyFetch) {
|
||||
return $this->resolveFromPropertyFetch($node);
|
||||
}
|
||||
|
||||
if ($node instanceof MethodCall || $node instanceof NullsafeMethodCall || $node instanceof StaticCall) {
|
||||
return $this->resolveFromMethodCall($node);
|
||||
}
|
||||
|
||||
if ($node instanceof New_) {
|
||||
return $this->resolveFromNew($node);
|
||||
}
|
||||
|
||||
if ($node instanceof FuncCall) {
|
||||
return $this->resolveFromNode($node->name);
|
||||
}
|
||||
|
||||
if (! $node instanceof Node) {
|
||||
throw new NotImplementedYetException();
|
||||
}
|
||||
|
||||
$paramName = $this->nodeNameResolver->getName($node);
|
||||
if ($paramName !== null) {
|
||||
return $paramName;
|
||||
}
|
||||
|
||||
if ($node instanceof String_) {
|
||||
return $node->value;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function resolveFromNew(New_ $new): string
|
||||
{
|
||||
if ($new->class instanceof Name) {
|
||||
$className = $this->nodeNameResolver->getName($new->class);
|
||||
return $this->nodeNameResolver->getShortName($className);
|
||||
}
|
||||
|
||||
throw new NotImplementedYetException();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param MethodCall|NullsafeMethodCall|StaticCall $node
|
||||
*/
|
||||
private function resolveFromMethodCall(Node $node): ?string
|
||||
{
|
||||
if ($node->name instanceof MethodCall) {
|
||||
return $this->resolveFromMethodCall($node->name);
|
||||
}
|
||||
|
||||
$methodName = $this->nodeNameResolver->getName($node->name);
|
||||
if (! is_string($methodName)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $methodName;
|
||||
}
|
||||
|
||||
private function resolveFromPropertyFetch(PropertyFetch $propertyFetch): string
|
||||
{
|
||||
$varName = $this->nodeNameResolver->getName($propertyFetch->var);
|
||||
if (! is_string($varName)) {
|
||||
throw new NotImplementedYetException();
|
||||
}
|
||||
|
||||
$propertyName = $this->nodeNameResolver->getName($propertyFetch->name);
|
||||
if (! is_string($propertyName)) {
|
||||
throw new NotImplementedYetException();
|
||||
}
|
||||
|
||||
if ($varName === 'this') {
|
||||
return $propertyName;
|
||||
}
|
||||
|
||||
return $varName . ucfirst($propertyName);
|
||||
}
|
||||
|
||||
private function resolveBareFuncCallArgumentName(
|
||||
FuncCall $funcCall,
|
||||
string $fallbackName,
|
||||
string $suffix
|
||||
): string {
|
||||
$argumentValue = $funcCall->args[0]->value;
|
||||
if ($argumentValue instanceof MethodCall || $argumentValue instanceof StaticCall) {
|
||||
$name = $this->nodeNameResolver->getName($argumentValue->name);
|
||||
} else {
|
||||
$name = $this->nodeNameResolver->getName($argumentValue);
|
||||
}
|
||||
|
||||
if ($name === null) {
|
||||
return $fallbackName;
|
||||
}
|
||||
|
||||
return $name . $suffix;
|
||||
}
|
||||
}
|
|
@ -24,9 +24,9 @@ use PHPStan\Reflection\ParametersAcceptor;
|
|||
use PHPStan\Type\MixedType;
|
||||
use Rector\Core\PHPStan\Reflection\CallReflectionResolver;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Naming\Naming\VariableNaming;
|
||||
use Rector\NodeNestingScope\ParentScopeFinder;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\Php70\NodeAnalyzer\VariableNaming;
|
||||
use Rector\Php70\ValueObject\VariableAssignPair;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
|
@ -77,7 +77,7 @@ final class NonVariableToVariableOnFunctionCallRector extends AbstractRector
|
|||
}
|
||||
|
||||
$currentScope = $scopeNode->getAttribute(AttributeKey::SCOPE);
|
||||
if (! $currentScope instanceof MutatingScope) {
|
||||
if (! $currentScope instanceof Scope) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -147,24 +147,22 @@ final class NonVariableToVariableOnFunctionCallRector extends AbstractRector
|
|||
return $arguments;
|
||||
}
|
||||
|
||||
private function getReplacementsFor(Expr $expr, MutatingScope $mutatingScope, Node $scopeNode): VariableAssignPair
|
||||
private function getReplacementsFor(Expr $expr, Scope $scope, Node $scopeNode): VariableAssignPair
|
||||
{
|
||||
/** @var Assign|AssignOp|AssignRef $expr */
|
||||
if ($this->isAssign($expr) && $this->isVariableLikeNode($expr->var)) {
|
||||
return new VariableAssignPair($expr->var, $expr);
|
||||
}
|
||||
|
||||
$variableName = $this->variableNaming->resolveFromNodeWithScopeCountAndFallbackName(
|
||||
$expr,
|
||||
$mutatingScope,
|
||||
'tmp'
|
||||
);
|
||||
$variableName = $this->variableNaming->resolveFromNodeWithScopeCountAndFallbackName($expr, $scope, 'tmp');
|
||||
|
||||
$variable = new Variable($variableName);
|
||||
|
||||
// add a new scope with this variable
|
||||
$newVariableAwareScope = $mutatingScope->assignExpression($variable, new MixedType());
|
||||
$scopeNode->setAttribute(AttributeKey::SCOPE, $newVariableAwareScope);
|
||||
if ($scope instanceof MutatingScope) {
|
||||
$mutatingScope = $scope->assignExpression($variable, new MixedType());
|
||||
$scopeNode->setAttribute(AttributeKey::SCOPE, $mutatingScope);
|
||||
}
|
||||
|
||||
return new VariableAssignPair($variable, new Assign($variable, $expr));
|
||||
}
|
||||
|
|
|
@ -4,26 +4,55 @@ declare(strict_types=1);
|
|||
|
||||
namespace Rector\Php72\NodeFactory;
|
||||
|
||||
use Nette\Utils\Strings;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Expr\ArrayDimFetch;
|
||||
use PhpParser\Node\Expr\Assign;
|
||||
use PhpParser\Node\Expr\Closure;
|
||||
use PhpParser\Node\Expr\ClosureUse;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Expr\PropertyFetch;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use PhpParser\Node\Identifier;
|
||||
use PhpParser\Node\Name;
|
||||
use PhpParser\Node\NullableType;
|
||||
use PhpParser\Node\Param;
|
||||
use PhpParser\Node\Scalar\LNumber;
|
||||
use PhpParser\Node\Scalar\String_;
|
||||
use PhpParser\Node\Stmt;
|
||||
use PhpParser\Node\Stmt\Expression;
|
||||
use PhpParser\Node\Stmt\Return_;
|
||||
use PhpParser\Node\UnionType;
|
||||
use PhpParser\Parser;
|
||||
use PHPStan\Reflection\FunctionVariantWithPhpDocs;
|
||||
use PHPStan\Reflection\ParameterReflection;
|
||||
use PHPStan\Reflection\Php\PhpMethodReflection;
|
||||
use PHPStan\Type\MixedType;
|
||||
use PHPStan\Type\VoidType;
|
||||
use Rector\Core\Exception\ShouldNotHappenException;
|
||||
use Rector\Core\PhpParser\Node\BetterNodeFinder;
|
||||
use Rector\Core\PhpParser\Node\NodeFactory;
|
||||
use Rector\NodeNameResolver\NodeNameResolver;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\StaticTypeMapper\StaticTypeMapper;
|
||||
use Symplify\Astral\NodeTraverser\SimpleCallableNodeTraverser;
|
||||
|
||||
final class AnonymousFunctionFactory
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
* @see https://regex101.com/r/jkLLlM/2
|
||||
*/
|
||||
private const DIM_FETCH_REGEX = '#(\\$|\\\\|\\x0)(?<number>\d+)#';
|
||||
|
||||
public function __construct(
|
||||
private NodeNameResolver $nodeNameResolver,
|
||||
private BetterNodeFinder $betterNodeFinder
|
||||
private BetterNodeFinder $betterNodeFinder,
|
||||
private NodeFactory $nodeFactory,
|
||||
private StaticTypeMapper $staticTypeMapper,
|
||||
private SimpleCallableNodeTraverser $simpleCallableNodeTraverser,
|
||||
private Parser $parser
|
||||
) {
|
||||
}
|
||||
|
||||
|
@ -51,6 +80,84 @@ final class AnonymousFunctionFactory
|
|||
return $anonymousFunctionNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Variable|PropertyFetch $expr
|
||||
*/
|
||||
public function createFromPhpMethodReflection(PhpMethodReflection $phpMethodReflection, Expr $expr): Closure
|
||||
{
|
||||
/** @var FunctionVariantWithPhpDocs $functionVariantWithPhpDoc */
|
||||
$functionVariantWithPhpDoc = $phpMethodReflection->getVariants()[0];
|
||||
|
||||
$anonymousFunction = new Closure();
|
||||
$newParams = $this->createParams($functionVariantWithPhpDoc->getParameters());
|
||||
|
||||
$anonymousFunction->params = $newParams;
|
||||
|
||||
$innerMethodCall = new MethodCall($expr, $phpMethodReflection->getName());
|
||||
$innerMethodCall->args = $this->nodeFactory->createArgsFromParams($newParams);
|
||||
|
||||
if (! $functionVariantWithPhpDoc->getReturnType() instanceof MixedType) {
|
||||
$returnType = $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode(
|
||||
$functionVariantWithPhpDoc->getReturnType()
|
||||
);
|
||||
$anonymousFunction->returnType = $returnType;
|
||||
}
|
||||
|
||||
// does method return something?
|
||||
|
||||
if (! $functionVariantWithPhpDoc->getReturnType() instanceof VoidType) {
|
||||
$anonymousFunction->stmts[] = new Return_($innerMethodCall);
|
||||
} else {
|
||||
$anonymousFunction->stmts[] = new Expression($innerMethodCall);
|
||||
}
|
||||
|
||||
if ($expr instanceof Variable && ! $this->nodeNameResolver->isName($expr, 'this')) {
|
||||
$anonymousFunction->uses[] = new ClosureUse($expr);
|
||||
}
|
||||
|
||||
return $anonymousFunction;
|
||||
}
|
||||
|
||||
public function createAnonymousFunctionFromString(Expr $expr): ?Closure
|
||||
{
|
||||
if (! $expr instanceof String_) {
|
||||
// not supported yet
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
$phpCode = '<?php ' . $expr->value . ';';
|
||||
$contentNodes = (array) $this->parser->parse($phpCode);
|
||||
|
||||
$anonymousFunction = new Closure();
|
||||
|
||||
$firstNode = $contentNodes[0] ?? null;
|
||||
if (! $firstNode instanceof Expression) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$stmt = $firstNode->expr;
|
||||
|
||||
$this->simpleCallableNodeTraverser->traverseNodesWithCallable($stmt, function (Node $node): Node {
|
||||
if (! $node instanceof String_) {
|
||||
return $node;
|
||||
}
|
||||
|
||||
$match = Strings::match($node->value, self::DIM_FETCH_REGEX);
|
||||
if (! $match) {
|
||||
return $node;
|
||||
}
|
||||
|
||||
$matchesVariable = new Variable('matches');
|
||||
|
||||
return new ArrayDimFetch($matchesVariable, new LNumber((int) $match['number']));
|
||||
});
|
||||
|
||||
$anonymousFunction->stmts[] = new Return_($stmt);
|
||||
$anonymousFunction->params[] = new Param(new Variable('matches'));
|
||||
|
||||
return $anonymousFunction;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Node[] $nodes
|
||||
* @param Param[] $paramNodes
|
||||
|
@ -97,4 +204,25 @@ final class AnonymousFunctionFactory
|
|||
|
||||
return $filteredVariables;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ParameterReflection[] $parameterReflections
|
||||
* @return Param[]
|
||||
*/
|
||||
private function createParams(array $parameterReflections): array
|
||||
{
|
||||
$params = [];
|
||||
foreach ($parameterReflections as $parameterReflection) {
|
||||
$param = new Param(new Variable($parameterReflection->getName()));
|
||||
|
||||
if (! $parameterReflection->getType() instanceof MixedType) {
|
||||
$paramType = $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode($parameterReflection->getType());
|
||||
$param->type = $paramType;
|
||||
}
|
||||
|
||||
$params[] = $param;
|
||||
}
|
||||
|
||||
return $params;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Php80\NodeResolver;
|
||||
namespace Rector\Php80\NodeAnalyzer;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\Assign;
|
||||
|
@ -23,7 +23,7 @@ use Rector\NodeTypeResolver\TypeComparator\TypeComparator;
|
|||
use Rector\Php80\ValueObject\PropertyPromotionCandidate;
|
||||
use Rector\TypeDeclaration\TypeInferer\PropertyTypeInferer;
|
||||
|
||||
final class PromotedPropertyResolver
|
||||
final class PromotedPropertyCandidateResolver
|
||||
{
|
||||
public function __construct(
|
||||
private NodeNameResolver $nodeNameResolver,
|
||||
|
@ -48,7 +48,8 @@ final class PromotedPropertyResolver
|
|||
|
||||
$propertyPromotionCandidates = [];
|
||||
foreach ($class->getProperties() as $property) {
|
||||
if (count($property->props) !== 1) {
|
||||
$propertyCount = count($property->props);
|
||||
if ($propertyCount !== 1) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -18,7 +18,7 @@ use Rector\Core\ValueObject\PhpVersionFeature;
|
|||
use Rector\DeadCode\PhpDoc\TagRemover\VarTagRemover;
|
||||
use Rector\Naming\VariableRenamer;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\Php80\NodeResolver\PromotedPropertyResolver;
|
||||
use Rector\Php80\NodeAnalyzer\PromotedPropertyCandidateResolver;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
|
||||
|
@ -30,7 +30,7 @@ use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
|||
final class ClassPropertyAssignToConstructorPromotionRector extends AbstractRector
|
||||
{
|
||||
public function __construct(
|
||||
private PromotedPropertyResolver $promotedPropertyResolver,
|
||||
private PromotedPropertyCandidateResolver $promotedPropertyResolver,
|
||||
private VariableRenamer $variableRenamer,
|
||||
private VarTagRemover $varTagRemover
|
||||
) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user