From 2a697f79ecd82e4b59091f59927d8b9315113c18 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Thu, 7 Sep 2023 02:37:03 +0700 Subject: [PATCH] [TypeDeclaration] Add fallback return direct array support on ReturnTypeFromStrictNewArrayRector (#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 --- .../Fixture/fallback_return_array.php.inc | 58 +++++++++++++++++++ .../ReturnTypeFromStrictNewArrayRector.php | 24 ++++++-- rules/TypeDeclaration/TypeNormalizer.php | 14 ----- 3 files changed, 77 insertions(+), 19 deletions(-) create mode 100644 rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictNewArrayRector/Fixture/fallback_return_array.php.inc diff --git a/rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictNewArrayRector/Fixture/fallback_return_array.php.inc b/rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictNewArrayRector/Fixture/fallback_return_array.php.inc new file mode 100644 index 00000000000..0f09067b69b --- /dev/null +++ b/rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictNewArrayRector/Fixture/fallback_return_array.php.inc @@ -0,0 +1,58 @@ +groupid.'--'.$offer->tarifid] = $offer; + $groupedOffers[$offer->groupid.'--'.$offer->tarifid]->groupedOffers = $groupOffers; + } + + return $groupedOffers; + } +} + +?> +----- +groupid.'--'.$offer->tarifid] = $offer; + $groupedOffers[$offer->groupid.'--'.$offer->tarifid]->groupedOffers = $groupOffers; + } + + return $groupedOffers; + } +} + +?> diff --git a/rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictNewArrayRector.php b/rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictNewArrayRector.php index 08a36217117..d4fce8594ce 100644 --- a/rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictNewArrayRector.php +++ b/rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictNewArrayRector.php @@ -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; @@ -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; @@ -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 ) { } @@ -108,7 +111,7 @@ 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; } @@ -116,20 +119,31 @@ public function refactorWithScope(Node $node, Scope $scope): ?Node 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); } diff --git a/rules/TypeDeclaration/TypeNormalizer.php b/rules/TypeDeclaration/TypeNormalizer.php index bb58f3032e7..ef0c509587e 100644 --- a/rules/TypeDeclaration/TypeNormalizer.php +++ b/rules/TypeDeclaration/TypeNormalizer.php @@ -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); @@ -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) {