Skip to content

Commit 88c095d

Browse files
committed
Updated Rector to commit a52f12049fab1c9bfda7f117e921ca42dc3a80e1
rectorphp/rector-src@a52f120 [tdd] Add AddReturnDocblockForDimFetchArrayFromAssignsRector (#7792)
1 parent 63815f9 commit 88c095d

File tree

5 files changed

+209
-2
lines changed

5 files changed

+209
-2
lines changed
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
<?php
2+
3+
declare (strict_types=1);
4+
namespace Rector\TypeDeclarationDocblocks\Rector\ClassMethod;
5+
6+
use PhpParser\Node;
7+
use PhpParser\Node\Expr\Array_;
8+
use PhpParser\Node\Expr\Assign;
9+
use PhpParser\Node\Expr\Variable;
10+
use PhpParser\Node\Stmt\ClassMethod;
11+
use PhpParser\Node\Stmt\Expression;
12+
use PhpParser\Node\Stmt\Return_;
13+
use PHPStan\Type\Constant\ConstantArrayType;
14+
use PHPStan\Type\Type;
15+
use PHPStan\Type\UnionType;
16+
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
17+
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger;
18+
use Rector\Rector\AbstractRector;
19+
use Rector\TypeDeclarationDocblocks\NodeFinder\ReturnNodeFinder;
20+
use Rector\TypeDeclarationDocblocks\TagNodeAnalyzer\UsefulArrayTagNodeAnalyzer;
21+
use Rector\TypeDeclarationDocblocks\TypeResolver\ConstantArrayTypeGeneralizer;
22+
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
23+
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
24+
/**
25+
* @see \Rector\Tests\TypeDeclarationDocblocks\Rector\ClassMethod\AddReturnDocblockForDimFetchArrayFromAssignsRector\AddReturnDocblockForDimFetchArrayFromAssignsRectorTest
26+
*/
27+
final class AddReturnDocblockForDimFetchArrayFromAssignsRector extends AbstractRector
28+
{
29+
/**
30+
* @readonly
31+
*/
32+
private PhpDocInfoFactory $phpDocInfoFactory;
33+
/**
34+
* @readonly
35+
*/
36+
private UsefulArrayTagNodeAnalyzer $usefulArrayTagNodeAnalyzer;
37+
/**
38+
* @readonly
39+
*/
40+
private ReturnNodeFinder $returnNodeFinder;
41+
/**
42+
* @readonly
43+
*/
44+
private ConstantArrayTypeGeneralizer $constantArrayTypeGeneralizer;
45+
/**
46+
* @readonly
47+
*/
48+
private PhpDocTypeChanger $phpDocTypeChanger;
49+
public function __construct(PhpDocInfoFactory $phpDocInfoFactory, UsefulArrayTagNodeAnalyzer $usefulArrayTagNodeAnalyzer, ReturnNodeFinder $returnNodeFinder, ConstantArrayTypeGeneralizer $constantArrayTypeGeneralizer, PhpDocTypeChanger $phpDocTypeChanger)
50+
{
51+
$this->phpDocInfoFactory = $phpDocInfoFactory;
52+
$this->usefulArrayTagNodeAnalyzer = $usefulArrayTagNodeAnalyzer;
53+
$this->returnNodeFinder = $returnNodeFinder;
54+
$this->constantArrayTypeGeneralizer = $constantArrayTypeGeneralizer;
55+
$this->phpDocTypeChanger = $phpDocTypeChanger;
56+
}
57+
public function getRuleDefinition(): RuleDefinition
58+
{
59+
return new RuleDefinition('Add @return docblock for methods returning array from dim fetch of assigned arrays', [new CodeSample(<<<'CODE_SAMPLE'
60+
final class SomeClass
61+
{
62+
public function toArray(): array
63+
{
64+
$items = [];
65+
66+
if (mt_rand(0, 1)) {
67+
$items['key'] = 'value';
68+
}
69+
70+
if (mt_rand(0, 1)) {
71+
$items['another_key'] = 'another_value';
72+
}
73+
74+
return $items;
75+
}
76+
}
77+
CODE_SAMPLE
78+
, <<<'CODE_SAMPLE'
79+
final class SomeClass
80+
{
81+
/**
82+
* @return array<string, string>
83+
*/
84+
public function toArray()
85+
{
86+
$items = [];
87+
88+
if (mt_rand(0, 1)) {
89+
$items['key'] = 'value';
90+
}
91+
92+
if (mt_rand(0, 1)) {
93+
$items['another_key'] = 'another_value';
94+
}
95+
96+
return $items;
97+
}
98+
}
99+
CODE_SAMPLE
100+
)]);
101+
}
102+
public function getNodeTypes(): array
103+
{
104+
return [ClassMethod::class];
105+
}
106+
/**
107+
* @param ClassMethod $node
108+
*/
109+
public function refactor(Node $node): ?ClassMethod
110+
{
111+
if ($node->stmts === null) {
112+
return null;
113+
}
114+
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node);
115+
if ($this->usefulArrayTagNodeAnalyzer->isUsefulArrayTag($phpDocInfo->getReturnTagValue())) {
116+
return null;
117+
}
118+
$soleReturn = $this->returnNodeFinder->findOnlyReturnWithExpr($node);
119+
if (!$soleReturn instanceof Return_) {
120+
return null;
121+
}
122+
// only variable
123+
if (!$soleReturn->expr instanceof Variable) {
124+
return null;
125+
}
126+
// @todo check type here
127+
$returnedExprType = $this->getType($soleReturn->expr);
128+
if (!$this->isConstantArrayType($returnedExprType)) {
129+
return null;
130+
}
131+
// find stmts with $item = [];
132+
$returnedVariableName = $this->getName($soleReturn->expr);
133+
if (!is_string($returnedVariableName)) {
134+
return null;
135+
}
136+
if (!$this->isVariableInstantiated($node, $returnedVariableName)) {
137+
return null;
138+
}
139+
if ($returnedExprType->getReferencedClasses() !== []) {
140+
// better handled by shared-interface/class rule, to avoid turning objects to mixed
141+
return null;
142+
}
143+
// conditional assign
144+
$genericUnionedTypeNodes = [];
145+
if ($returnedExprType instanceof UnionType) {
146+
foreach ($returnedExprType->getTypes() as $unionedType) {
147+
if ($unionedType instanceof ConstantArrayType) {
148+
// skip empty array
149+
if ($unionedType->getKeyTypes() === [] && $unionedType->getValueTypes() === []) {
150+
continue;
151+
}
152+
$genericUnionedTypeNode = $this->constantArrayTypeGeneralizer->generalize($unionedType);
153+
$genericUnionedTypeNodes[] = $genericUnionedTypeNode;
154+
}
155+
}
156+
} else {
157+
/** @var ConstantArrayType $returnedExprType */
158+
$genericTypeNode = $this->constantArrayTypeGeneralizer->generalize($returnedExprType);
159+
$this->phpDocTypeChanger->changeReturnTypeNode($node, $phpDocInfo, $genericTypeNode);
160+
return $node;
161+
}
162+
// @todo handle multiple type nodes
163+
$this->phpDocTypeChanger->changeReturnTypeNode($node, $phpDocInfo, $genericUnionedTypeNodes[0]);
164+
return $node;
165+
}
166+
private function isVariableInstantiated(ClassMethod $classMethod, string $returnedVariableName): bool
167+
{
168+
foreach ((array) $classMethod->stmts as $stmt) {
169+
if (!$stmt instanceof Expression) {
170+
continue;
171+
}
172+
if (!$stmt->expr instanceof Assign) {
173+
continue;
174+
}
175+
$assign = $stmt->expr;
176+
if (!$assign->var instanceof Variable) {
177+
continue;
178+
}
179+
if (!$this->isName($assign->var, $returnedVariableName)) {
180+
continue;
181+
}
182+
// must be array assignment
183+
if (!$assign->expr instanceof Array_) {
184+
continue;
185+
}
186+
return \true;
187+
}
188+
return \false;
189+
}
190+
private function isConstantArrayType(Type $returnedExprType): bool
191+
{
192+
if ($returnedExprType instanceof UnionType) {
193+
foreach ($returnedExprType->getTypes() as $unionedType) {
194+
if (!$unionedType instanceof ConstantArrayType) {
195+
return \false;
196+
}
197+
}
198+
return \true;
199+
}
200+
return $returnedExprType instanceof ConstantArrayType;
201+
}
202+
}

src/Application/VersionResolver.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ final class VersionResolver
1919
* @api
2020
* @var string
2121
*/
22-
public const PACKAGE_VERSION = '9116b3e9de65f5e4723746d0db790de0cd005b99';
22+
public const PACKAGE_VERSION = 'a52f12049fab1c9bfda7f117e921ca42dc3a80e1';
2323
/**
2424
* @api
2525
* @var string
2626
*/
27-
public const RELEASE_DATE = '2026-01-02 13:40:46';
27+
public const RELEASE_DATE = '2026-01-02 16:27:23';
2828
/**
2929
* @var int
3030
*/

src/Config/Level/TypeDeclarationDocblocksLevel.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use Rector\TypeDeclarationDocblocks\Rector\ClassMethod\AddParamArrayDocblockFromDimFetchAccessRector;
1919
use Rector\TypeDeclarationDocblocks\Rector\ClassMethod\AddReturnDocblockForArrayDimAssignedObjectRector;
2020
use Rector\TypeDeclarationDocblocks\Rector\ClassMethod\AddReturnDocblockForCommonObjectDenominatorRector;
21+
use Rector\TypeDeclarationDocblocks\Rector\ClassMethod\AddReturnDocblockForDimFetchArrayFromAssignsRector;
2122
use Rector\TypeDeclarationDocblocks\Rector\ClassMethod\AddReturnDocblockForJsonArrayRector;
2223
use Rector\TypeDeclarationDocblocks\Rector\ClassMethod\DocblockGetterReturnArrayFromPropertyDocblockVarRector;
2324
use Rector\TypeDeclarationDocblocks\Rector\ClassMethod\DocblockReturnArrayFromDirectArrayInstanceRector;
@@ -52,5 +53,7 @@ final class TypeDeclarationDocblocksLevel
5253
DocblockVarArrayFromGetterReturnRector::class,
5354
// return
5455
DocblockGetterReturnArrayFromPropertyDocblockVarRector::class,
56+
// run latter after other rules, as more generic
57+
AddReturnDocblockForDimFetchArrayFromAssignsRector::class,
5558
];
5659
}

vendor/composer/autoload_classmap.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2755,6 +2755,7 @@
27552755
'Rector\\TypeDeclarationDocblocks\\Rector\\ClassMethod\\AddParamArrayDocblockFromDimFetchAccessRector' => $baseDir . '/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddParamArrayDocblockFromDimFetchAccessRector.php',
27562756
'Rector\\TypeDeclarationDocblocks\\Rector\\ClassMethod\\AddReturnDocblockForArrayDimAssignedObjectRector' => $baseDir . '/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddReturnDocblockForArrayDimAssignedObjectRector.php',
27572757
'Rector\\TypeDeclarationDocblocks\\Rector\\ClassMethod\\AddReturnDocblockForCommonObjectDenominatorRector' => $baseDir . '/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddReturnDocblockForCommonObjectDenominatorRector.php',
2758+
'Rector\\TypeDeclarationDocblocks\\Rector\\ClassMethod\\AddReturnDocblockForDimFetchArrayFromAssignsRector' => $baseDir . '/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddReturnDocblockForDimFetchArrayFromAssignsRector.php',
27582759
'Rector\\TypeDeclarationDocblocks\\Rector\\ClassMethod\\AddReturnDocblockForJsonArrayRector' => $baseDir . '/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddReturnDocblockForJsonArrayRector.php',
27592760
'Rector\\TypeDeclarationDocblocks\\Rector\\ClassMethod\\DocblockGetterReturnArrayFromPropertyDocblockVarRector' => $baseDir . '/rules/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockGetterReturnArrayFromPropertyDocblockVarRector.php',
27602761
'Rector\\TypeDeclarationDocblocks\\Rector\\ClassMethod\\DocblockReturnArrayFromDirectArrayInstanceRector' => $baseDir . '/rules/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockReturnArrayFromDirectArrayInstanceRector.php',

vendor/composer/autoload_static.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3015,6 +3015,7 @@ class ComposerStaticInit8feb715f5d726b0b23c2b018f39541bb
30153015
'Rector\\TypeDeclarationDocblocks\\Rector\\ClassMethod\\AddParamArrayDocblockFromDimFetchAccessRector' => __DIR__ . '/../..' . '/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddParamArrayDocblockFromDimFetchAccessRector.php',
30163016
'Rector\\TypeDeclarationDocblocks\\Rector\\ClassMethod\\AddReturnDocblockForArrayDimAssignedObjectRector' => __DIR__ . '/../..' . '/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddReturnDocblockForArrayDimAssignedObjectRector.php',
30173017
'Rector\\TypeDeclarationDocblocks\\Rector\\ClassMethod\\AddReturnDocblockForCommonObjectDenominatorRector' => __DIR__ . '/../..' . '/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddReturnDocblockForCommonObjectDenominatorRector.php',
3018+
'Rector\\TypeDeclarationDocblocks\\Rector\\ClassMethod\\AddReturnDocblockForDimFetchArrayFromAssignsRector' => __DIR__ . '/../..' . '/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddReturnDocblockForDimFetchArrayFromAssignsRector.php',
30183019
'Rector\\TypeDeclarationDocblocks\\Rector\\ClassMethod\\AddReturnDocblockForJsonArrayRector' => __DIR__ . '/../..' . '/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddReturnDocblockForJsonArrayRector.php',
30193020
'Rector\\TypeDeclarationDocblocks\\Rector\\ClassMethod\\DocblockGetterReturnArrayFromPropertyDocblockVarRector' => __DIR__ . '/../..' . '/rules/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockGetterReturnArrayFromPropertyDocblockVarRector.php',
30203021
'Rector\\TypeDeclarationDocblocks\\Rector\\ClassMethod\\DocblockReturnArrayFromDirectArrayInstanceRector' => __DIR__ . '/../..' . '/rules/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockReturnArrayFromDirectArrayInstanceRector.php',

0 commit comments

Comments
 (0)