Skip to content

Commit 85d29ad

Browse files
committed
extract NodeDocblockTypeDecorator
1 parent 8e7aeef commit 85d29ad

File tree

3 files changed

+84
-52
lines changed

3 files changed

+84
-52
lines changed

rules/TypeDeclarationDocblocks/NodeDocblockTypeDecorator.php

Lines changed: 70 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,16 @@
44

55
namespace Rector\TypeDeclarationDocblocks;
66

7+
use PhpParser\Node\Stmt\ClassMethod;
78
use PhpParser\Node\Stmt\Property;
9+
use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode;
810
use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
11+
use PHPStan\PhpDocParser\Ast\Type\ArrayTypeNode;
12+
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
913
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
14+
use PHPStan\Type\ArrayType;
15+
use PHPStan\Type\IntegerType;
16+
use PHPStan\Type\MixedType;
1017
use PHPStan\Type\Type;
1118
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
1219
use Rector\Comments\NodeDocBlock\DocBlockUpdater;
@@ -15,37 +22,92 @@
1522

1623
final readonly class NodeDocblockTypeDecorator
1724
{
18-
public function __construct(
25+
public function __construct(
1926
private TypeNormalizer $typeNormalizer,
2027
private StaticTypeMapper $staticTypeMapper,
2128
private DocBlockUpdater $docBlockUpdater,
2229
) {
2330
}
2431

25-
public function decorateGenericIterableVarType(
32+
public function decorateGenericIterableParamType(
2633
Type $type,
2734
PhpDocInfo $phpDocInfo,
28-
Property $property
29-
): void {
35+
ClassMethod $classMethod,
36+
string $parameterName
37+
): bool {
38+
if ($this->isBareMixedType($type)) {
39+
// no value
40+
return false;
41+
}
42+
43+
$normalizedType = $this->typeNormalizer->generalizeConstantTypes($type);
44+
$typeNode = $this->createTypeNode($normalizedType);
45+
46+
$paramTagValueNode = new ParamTagValueNode($typeNode, false, '$' . $parameterName, '', false);
47+
48+
$this->addTagValueNodeAndUpdatePhpDocInfo($phpDocInfo, $paramTagValueNode, $classMethod);
49+
50+
return true;
51+
}
52+
53+
public function decorateGenericIterableVarType(Type $type, PhpDocInfo $phpDocInfo, Property $property): bool
54+
{
3055
$typeNode = $this->createTypeNode($type);
3156

57+
if ($this->isBareMixedType($type)) {
58+
// no value
59+
return false;
60+
}
61+
3262
$varTagValueNode = new VarTagValueNode($typeNode, '', '');
3363

3464
$this->addTagValueNodeAndUpdatePhpDocInfo($phpDocInfo, $varTagValueNode, $property);
65+
66+
return true;
3567
}
3668

3769
private function createTypeNode(Type $type): TypeNode
3870
{
3971
$generalizedReturnType = $this->typeNormalizer->generalizeConstantTypes($type);
4072

4173
// turn into rather generic short return type, to keep it open to extension later and readable to human
42-
return $this->staticTypeMapper->mapPHPStanTypeToPHPStanPhpDocTypeNode($generalizedReturnType);
74+
$typeNode = $this->staticTypeMapper->mapPHPStanTypeToPHPStanPhpDocTypeNode($generalizedReturnType);
75+
76+
if ($typeNode instanceof IdentifierTypeNode && $typeNode->name === 'mixed') {
77+
return new ArrayTypeNode($typeNode);
78+
}
79+
80+
return $typeNode;
81+
}
82+
83+
private function addTagValueNodeAndUpdatePhpDocInfo(
84+
PhpDocInfo $phpDocInfo,
85+
ParamTagValueNode|VarTagValueNode $tagValueNode,
86+
Property|ClassMethod $stmt
87+
): void {
88+
$phpDocInfo->addTagValueNode($tagValueNode);
89+
90+
$this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($stmt);
4391
}
4492

45-
private function addTagValueNodeAndUpdatePhpDocInfo(PhpDocInfo $phpDocInfo, VarTagValueNode $varTagValueNode, Property $property): void
93+
private function isBareMixedType(Type $type): bool
4694
{
47-
$phpDocInfo->addTagValueNode($varTagValueNode);
95+
$normalizedResolvedParameterType = $this->typeNormalizer->generalizeConstantTypes($type);
96+
97+
// most likely mixed, skip
98+
return $this->isArrayMixed($normalizedResolvedParameterType);
99+
}
100+
101+
private function isArrayMixed(Type $type): bool
102+
{
103+
if (! $type instanceof ArrayType) {
104+
return false;
105+
}
106+
107+
if (! $type->getItemType() instanceof MixedType) {
108+
return false;
109+
}
48110

49-
$this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($property);
111+
return $type->getKeyType() instanceof IntegerType;
50112
}
51113
}

rules/TypeDeclarationDocblocks/Rector/Class_/ClassMethodArrayDocblockParamFromLocalCallsRector.php

Lines changed: 9 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,12 @@
77
use PhpParser\Node;
88
use PhpParser\Node\Stmt\Class_;
99
use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode;
10-
use PHPStan\PhpDocParser\Ast\Type\ArrayTypeNode;
11-
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
12-
use PHPStan\Type\ArrayType;
13-
use PHPStan\Type\IntegerType;
14-
use PHPStan\Type\MixedType;
1510
use PHPStan\Type\Type;
1611
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
17-
use Rector\Comments\NodeDocBlock\DocBlockUpdater;
1812
use Rector\PhpParser\NodeFinder\LocalMethodCallFinder;
19-
use Rector\Privatization\TypeManipulator\TypeNormalizer;
2013
use Rector\Rector\AbstractRector;
21-
use Rector\StaticTypeMapper\StaticTypeMapper;
2214
use Rector\TypeDeclaration\NodeAnalyzer\CallTypesResolver;
15+
use Rector\TypeDeclarationDocblocks\NodeDocblockTypeDecorator;
2316
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
2417
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
2518

@@ -30,11 +23,9 @@ final class ClassMethodArrayDocblockParamFromLocalCallsRector extends AbstractRe
3023
{
3124
public function __construct(
3225
private readonly PhpDocInfoFactory $phpDocInfoFactory,
33-
private readonly DocBlockUpdater $docBlockUpdater,
34-
private readonly StaticTypeMapper $staticTypeMapper,
3526
private readonly CallTypesResolver $callTypesResolver,
3627
private readonly LocalMethodCallFinder $localMethodCallFinder,
37-
private readonly TypeNormalizer $typeNormalizer
28+
private readonly NodeDocblockTypeDecorator $nodeDocblockTypeDecorator
3829
) {
3930
}
4031

@@ -121,28 +112,16 @@ public function refactor(Node $node): ?Node
121112
continue;
122113
}
123114

124-
$normalizedResolvedParameterType = $this->typeNormalizer->generalizeConstantTypes(
125-
$resolvedParameterType
115+
$hasClassMethodChanged = $this->nodeDocblockTypeDecorator->decorateGenericIterableParamType(
116+
$resolvedParameterType,
117+
$classMethodPhpDocInfo,
118+
$classMethod,
119+
$parameterName
126120
);
127121

128-
// most likely mixed, skip
129-
if ($this->isArrayMixed($normalizedResolvedParameterType)) {
130-
continue;
122+
if ($hasClassMethodChanged) {
123+
$hasChanged = true;
131124
}
132-
133-
$arrayDocTypeNode = $this->staticTypeMapper->mapPHPStanTypeToPHPStanPhpDocTypeNode(
134-
$normalizedResolvedParameterType
135-
);
136-
137-
if ($arrayDocTypeNode instanceof IdentifierTypeNode && $arrayDocTypeNode->name === 'mixed') {
138-
$arrayDocTypeNode = new ArrayTypeNode($arrayDocTypeNode);
139-
}
140-
141-
$paramTagValueNode = new ParamTagValueNode($arrayDocTypeNode, false, '$' . $parameterName, '', false);
142-
$classMethodPhpDocInfo->addTagValueNode($paramTagValueNode);
143-
144-
$hasChanged = true;
145-
$this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($classMethod);
146125
}
147126
}
148127

@@ -152,17 +131,4 @@ public function refactor(Node $node): ?Node
152131

153132
return $node;
154133
}
155-
156-
private function isArrayMixed(Type $type): bool
157-
{
158-
if (! $type instanceof ArrayType) {
159-
return false;
160-
}
161-
162-
if (! $type->getItemType() instanceof MixedType) {
163-
return false;
164-
}
165-
166-
return $type->getKeyType() instanceof IntegerType;
167-
}
168134
}

rules/TypeDeclarationDocblocks/Rector/Class_/DocblockVarArrayFromPropertyDefaultsRector.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,11 @@ public function refactor(Node $node): ?Node
8989
continue;
9090
}
9191

92-
$this->nodeDocblockTypeDecorator->decorateGenericIterableVarType($propertyDefaultType, $propertyPhpDocInfo, $property);
92+
$this->nodeDocblockTypeDecorator->decorateGenericIterableVarType(
93+
$propertyDefaultType,
94+
$propertyPhpDocInfo,
95+
$property
96+
);
9397
$hasChanged = true;
9498
}
9599

0 commit comments

Comments
 (0)