Skip to content

Commit

Permalink
[TypeDeclaration] Add fallback return direct array support on ReturnT…
Browse files Browse the repository at this point in the history
…ypeFromStrictNewArrayRector (#4928)

* [TypeDeclaration] Add fallback return array support on ReturnTypeFromStrictNewArrayRector

* [ci-review] Rector Rectify

* Fix phpstan

* Fix phpstan

* [ci-review] Rector Rectify

---------

Co-authored-by: GitHub Action <actions@github.com>
  • Loading branch information
samsonasik and actions-user committed Sep 6, 2023
1 parent 10eb09f commit 2a697f7
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

declare(strict_types=1);

namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictNewArrayRector\Fixture;

final class FallbackReturnArray
{
public function groupOffers($offers)
{
if (count($offers) == 0) {
return [];
}

$groupOffers = [];

$groupedOffers = [];
foreach ($offers as $offer) {
$groupedOffers[$offer->groupid.'--'.$offer->tarifid] = $offer;
$groupedOffers[$offer->groupid.'--'.$offer->tarifid]->groupedOffers = $groupOffers;
}

return $groupedOffers;
}
}

?>
-----
<?php

declare(strict_types=1);

namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictNewArrayRector\Fixture;

final class FallbackReturnArray
{
/**
* @return mixed[]
*/
public function groupOffers($offers): array
{
if (count($offers) == 0) {
return [];
}

$groupOffers = [];

$groupedOffers = [];
foreach ($offers as $offer) {
$groupedOffers[$offer->groupid.'--'.$offer->tarifid] = $offer;
$groupedOffers[$offer->groupid.'--'.$offer->tarifid]->groupedOffers = $groupOffers;
}

return $groupedOffers;
}
}

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

namespace Rector\TypeDeclaration\Rector\ClassMethod;

use PHPStan\Type\Type;
use PhpParser\Node;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Expr\Assign;
Expand All @@ -25,6 +26,7 @@
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger;
use Rector\Core\Rector\AbstractScopeAwareRector;
use Rector\Core\ValueObject\PhpVersion;
use Rector\TypeDeclaration\TypeInferer\ReturnTypeInferer;
use Rector\VendorLocker\NodeVendorLocker\ClassMethodReturnTypeOverrideGuard;
use Rector\VersionBonding\Contract\MinPhpVersionInterface;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
Expand All @@ -37,7 +39,8 @@ final class ReturnTypeFromStrictNewArrayRector extends AbstractScopeAwareRector
{
public function __construct(
private readonly PhpDocTypeChanger $phpDocTypeChanger,
private readonly ClassMethodReturnTypeOverrideGuard $classMethodReturnTypeOverrideGuard
private readonly ClassMethodReturnTypeOverrideGuard $classMethodReturnTypeOverrideGuard,
private readonly ReturnTypeInferer $returnTypeInferer
) {
}

Expand Down Expand Up @@ -108,28 +111,39 @@ public function refactorWithScope(Node $node, Scope $scope): ?Node

/** @var Return_[] $returns */
$returns = $this->betterNodeFinder->findInstancesOfInFunctionLikeScoped($node, Return_::class);
if (count($returns) !== 1) {
if ($returns === []) {
return null;
}

if ($this->isVariableOverriddenWithNonArray($node, $variable)) {
return null;
}

if (count($returns) > 1) {
$returnType = $this->returnTypeInferer->inferFunctionLike($node);
return $this->processAddArrayReturnType($node, $returnType);
}

$onlyReturn = $returns[0];
if (! $onlyReturn->expr instanceof Variable) {
return null;
}

$returnType = $this->nodeTypeResolver->getNativeType($onlyReturn->expr);
if (! $returnType instanceof ArrayType) {
return $this->processAddArrayReturnType($node, $returnType);
}

private function processAddArrayReturnType(ClassMethod|Function_|Closure $node, Type $returnType): ClassMethod|Function_|Closure|null
{
if (! $returnType->isArray()->yes()) {
return null;
}

// 3. always returns array
// always returns array
$node->returnType = new Identifier('array');

// 4. add more precise array type if suitable
// add more precise array type if suitable
/** @var ArrayType $returnType */
if ($this->shouldAddReturnArrayDocType($returnType)) {
$this->changeReturnType($node, $returnType);
}
Expand Down
14 changes: 0 additions & 14 deletions rules/TypeDeclaration/TypeNormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,6 @@ public function normalizeArrayTypeAndArrayNever(Type $type): Type
$traversedTypeTypes = $traversedType->getTypes();
$countTraversedTypes = count($traversedTypeTypes);

if ($this->isUnionMixedArrayNeverType($countTraversedTypes, $traversedTypeTypes)) {
return new MixedType();
}

$collectedTypes = $this->getCollectedTypes($traversedTypeTypes);
$countCollectedTypes = count($collectedTypes);

Expand Down Expand Up @@ -136,16 +132,6 @@ private function getCollectedTypes(array $traversedTypeTypes): array
return $collectedTypes;
}

/**
* @param Type[] $traversedTypeTypes
*/
private function isUnionMixedArrayNeverType(int $countTraversedTypes, array $traversedTypeTypes): bool
{
return $countTraversedTypes === 2 && ($this->isArrayNeverType(
$traversedTypeTypes[0]
) || $this->isArrayNeverType($traversedTypeTypes[1]));
}

private function collectNestedArrayTypeFromUnionType(UnionType $unionType, int $arrayNesting): void
{
foreach ($unionType->getTypes() as $unionedType) {
Expand Down

0 comments on commit 2a697f7

Please sign in to comment.