Skip to content

Commit

Permalink
[DowngradePhp81] Handle New_ inside array on DowngradeNewInInitialize…
Browse files Browse the repository at this point in the history
…rRector (#1508)

* [DowngradePhp81] Handle New_ inside array on DowngradeNewInInitializerRector

* add failing fixture

* Fixed 🎉

* [ci-review] Rector Rectify

* phpstan

* [ci-review] Rector Rectify

Co-authored-by: GitHub Action <action@github.com>
  • Loading branch information
samsonasik and actions-user authored Dec 15, 2021
1 parent 59089f4 commit e0ba9a3
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace Rector\Tests\DowngradePhp81\Rector\FunctionLike\DowngradeNewInInitializerRector\Fixture;

use stdClass;

class NewInArray
{
public function __construct(public array $property = [
'a' => new stdClass()
])
{
}
}

?>
-----
<?php

namespace Rector\Tests\DowngradePhp81\Rector\FunctionLike\DowngradeNewInInitializerRector\Fixture;

use stdClass;

class NewInArray
{
public function __construct(public ?array $property = null)
{
$this->property = $property ?? [
'a' => new stdClass()
];
}
}

?>
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use PhpParser\Comment;
use PhpParser\Node;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
Expand Down Expand Up @@ -208,7 +209,11 @@ private function createPropertiesFromParams(array $params): array
$property->type = $param->type;
$this->decoratePropertyWithParamDocInfo($param, $property);

if ($param->default !== null) {
$hasNew = $param->default === null
? false
: (bool) $this->betterNodeFinder->findFirstInstanceOf($param->default, New_::class);

if ($param->default !== null && ! $hasNew) {
$property->props[0]->default = $param->default;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use PhpParser\Node;
use PhpParser\Node\ComplexType;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\ArrowFunction;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\AssignOp\Coalesce as AssignCoalesce;
Expand All @@ -18,6 +19,7 @@
use PhpParser\Node\IntersectionType;
use PhpParser\Node\Name;
use PhpParser\Node\NullableType;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Expression;
use PhpParser\Node\Stmt\Return_;
Expand Down Expand Up @@ -95,11 +97,7 @@ public function refactor(Node $node): ?FunctionLike
private function shouldSkip(FunctionLike $functionLike): bool
{
foreach ($functionLike->getParams() as $param) {
if (! $param->default instanceof New_) {
continue;
}

if ($param->type instanceof IntersectionType) {
if ($this->isParamSkipped($param)) {
continue;
}

Expand All @@ -125,27 +123,44 @@ private function convertArrowFunctionToClosure(FunctionLike $functionLike): Func
);
}

private function isParamSkipped(Param $param): bool
{
if ($param->default === null) {
return true;
}

$hasNew = (bool) $this->betterNodeFinder->findFirstInstanceOf($param->default, New_::class);
if (! $hasNew) {
return true;
}

return $param->type instanceof IntersectionType;
}

private function replaceNewInParams(FunctionLike $functionLike): FunctionLike
{
$isConstructor = $functionLike instanceof ClassMethod && $this->isName($functionLike, MethodName::CONSTRUCT);

$stmts = [];
foreach ($functionLike->getParams() as $param) {
if (! $param->default instanceof New_) {
if ($this->isParamSkipped($param)) {
continue;
}

/** @var Expr $default */
$default = $param->default;

// check for property promotion
if ($isConstructor && $param->flags > 0) {
$propertyFetch = new PropertyFetch(new Variable('this'), $param->var->name);
$coalesce = new Coalesce($param->var, $param->default);
$coalesce = new Coalesce($param->var, $default);
$assign = new Assign($propertyFetch, $coalesce);

if ($param->type !== null) {
$param->type = $this->ensureNullableType($param->type);
}
} else {
$assign = new AssignCoalesce($param->var, $param->default);
$assign = new AssignCoalesce($param->var, $default);
}

$stmts[] = new Expression($assign);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);

namespace Rector\Core\Tests\Issues\DowngradeNewInArrayInitializerPromotion;

use Iterator;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
use Symplify\SmartFileSystem\SmartFileInfo;

final class DowngradeNewInArrayInitializerPromotionTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(SmartFileInfo $fileInfo): void
{
$this->doTestFileInfo($fileInfo);
}

/**
* @return Iterator<SmartFileInfo>
*/
public function provideData(): Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}

public function provideConfigFilePath(): string
{
return __DIR__ . '/config/configured_rule.php';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

namespace Rector\Core\Tests\Issues\DowngradeNewInArrayInitializerPromotion\Fixture;

use stdClass;

class NewInArray
{
/**
* @param array<string, object> $property
*/
public function __construct(public array $property = [
'a' => new stdClass()
])
{
}
}

?>
-----
<?php

namespace Rector\Core\Tests\Issues\DowngradeNewInArrayInitializerPromotion\Fixture;

use stdClass;

class NewInArray
{
/**
* @var array<string, object>
*/
public $property;
/**
* @param array<string, object> $property
*/
public function __construct(array $property = null)
{
$property ??= [
'a' => new stdClass()
];
$this->property = $property;
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

use Rector\DowngradePhp74\Rector\Property\DowngradeTypedPropertyRector;
use Rector\DowngradePhp80\Rector\Class_\DowngradePropertyPromotionRector;
use Rector\DowngradePhp81\Rector\FunctionLike\DowngradeNewInInitializerRector;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
$services->set(DowngradeNewInInitializerRector::class);
$services->set(DowngradePropertyPromotionRector::class);
$services->set(DowngradeTypedPropertyRector::class);
};

0 comments on commit e0ba9a3

Please sign in to comment.