Skip to content

Commit 7371b58

Browse files
committed
extract ParameterTypeFromDataProviderResolver
1 parent 8f25178 commit 7371b58

4 files changed

Lines changed: 289 additions & 155 deletions

File tree

rules-tests/TypeDeclarationDocblocks/Rector/ClassMethod/AddParamArrayDocblockFromDataProviderRector/Fixture/some_test_with_data_provider.php

Lines changed: 0 additions & 21 deletions
This file was deleted.

rules/TypeDeclaration/Rector/ClassMethod/AddParamTypeBasedOnPHPUnitDataProviderRector.php

Lines changed: 110 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,14 @@
55
namespace Rector\TypeDeclaration\Rector\ClassMethod;
66

77
use PhpParser\Node;
8-
use PhpParser\Node\ArrayItem;
9-
use PhpParser\Node\Expr\Array_;
10-
use PhpParser\Node\Expr\Yield_;
118
use PhpParser\Node\Stmt\Class_;
129
use PhpParser\Node\Stmt\ClassMethod;
13-
use PhpParser\Node\Stmt\Return_;
14-
use PHPStan\Type\Constant\ConstantArrayType;
1510
use PHPStan\Type\MixedType;
16-
use PHPStan\Type\Type;
17-
use PHPStan\Type\TypeCombinator;
18-
use Rector\NodeTypeResolver\PHPStan\Type\TypeFactory;
19-
use Rector\PhpParser\Node\BetterNodeFinder;
2011
use Rector\PHPStanStaticTypeMapper\Enum\TypeKind;
2112
use Rector\PHPUnit\NodeAnalyzer\TestsNodeAnalyzer;
2213
use Rector\Rector\AbstractRector;
2314
use Rector\StaticTypeMapper\StaticTypeMapper;
15+
use Rector\TypeDeclaration\TypeAnalyzer\ParameterTypeFromDataProviderResolver;
2416
use Rector\TypeDeclaration\ValueObject\DataProviderNodes;
2517
use Rector\TypeDeclarationDocblocks\NodeFinder\DataProviderMethodsFinder;
2618
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
@@ -37,10 +29,9 @@ final class AddParamTypeBasedOnPHPUnitDataProviderRector extends AbstractRector
3729
private const ERROR_MESSAGE = 'Adds param type declaration based on PHPUnit provider return type declaration';
3830

3931
public function __construct(
40-
private readonly TypeFactory $typeFactory,
4132
private readonly TestsNodeAnalyzer $testsNodeAnalyzer,
4233
private readonly DataProviderMethodsFinder $dataProviderMethodsFinder,
43-
private readonly BetterNodeFinder $betterNodeFinder,
34+
private readonly ParameterTypeFromDataProviderResolver $parameterTypeFromDataProviderResolver,
4435
private readonly StaticTypeMapper $staticTypeMapper,
4536
) {
4637
}
@@ -136,110 +127,110 @@ public function refactor(Node $node): ?Node
136127
return null;
137128
}
138129

139-
private function inferParam(int $parameterPosition, ClassMethod $dataProviderClassMethod): Type
140-
{
141-
$returns = $this->betterNodeFinder->findReturnsScoped($dataProviderClassMethod);
142-
if ($returns !== []) {
143-
return $this->resolveReturnStaticArrayTypeByParameterPosition($returns, $parameterPosition);
144-
}
145-
146-
/** @var Yield_[] $yields */
147-
$yields = $this->betterNodeFinder->findInstancesOfInFunctionLikeScoped($dataProviderClassMethod, Yield_::class);
148-
return $this->resolveYieldStaticArrayTypeByParameterPosition($yields, $parameterPosition);
149-
}
150-
151-
/**
152-
* @param Return_[] $returns
153-
*/
154-
private function resolveReturnStaticArrayTypeByParameterPosition(array $returns, int $parameterPosition): Type
155-
{
156-
$firstReturnedExpr = $returns[0]->expr;
157-
158-
if (! $firstReturnedExpr instanceof Array_) {
159-
return new MixedType();
160-
}
161-
162-
$paramOnPositionTypes = $this->resolveParamOnPositionTypes($firstReturnedExpr, $parameterPosition);
163-
if ($paramOnPositionTypes === []) {
164-
return new MixedType();
165-
}
166-
167-
return $this->typeFactory->createMixedPassedOrUnionType($paramOnPositionTypes);
168-
}
169-
170-
/**
171-
* @param Yield_[] $yields
172-
*/
173-
private function resolveYieldStaticArrayTypeByParameterPosition(array $yields, int $parameterPosition): Type
174-
{
175-
$paramOnPositionTypes = [];
176-
177-
foreach ($yields as $yield) {
178-
if (! $yield->value instanceof Array_) {
179-
continue;
180-
}
181-
182-
$type = $this->getTypeFromClassMethodYield($yield->value);
183-
184-
if (! $type instanceof ConstantArrayType) {
185-
return $type;
186-
}
187-
188-
foreach ($type->getValueTypes() as $position => $valueType) {
189-
if ($position !== $parameterPosition) {
190-
continue;
191-
}
192-
193-
$paramOnPositionTypes[] = $valueType;
194-
}
195-
}
196-
197-
if ($paramOnPositionTypes === []) {
198-
return new MixedType();
199-
}
200-
201-
return $this->typeFactory->createMixedPassedOrUnionType($paramOnPositionTypes);
202-
}
203-
204-
private function getTypeFromClassMethodYield(Array_ $classMethodYieldArray): MixedType | ConstantArrayType
205-
{
206-
$arrayType = $this->nodeTypeResolver->getType($classMethodYieldArray);
207-
208-
// impossible to resolve
209-
if (! $arrayType instanceof ConstantArrayType) {
210-
return new MixedType();
211-
}
212-
213-
return $arrayType;
214-
}
215-
216-
/**
217-
* @return Type[]
218-
*/
219-
private function resolveParamOnPositionTypes(Array_ $array, int $parameterPosition): array
220-
{
221-
$paramOnPositionTypes = [];
222-
223-
foreach ($array->items as $singleDataProvidedSet) {
224-
if (! $singleDataProvidedSet instanceof ArrayItem || ! $singleDataProvidedSet->value instanceof Array_) {
225-
return [];
226-
}
227-
228-
foreach ($singleDataProvidedSet->value->items as $position => $singleDataProvidedSetItem) {
229-
if ($position !== $parameterPosition) {
230-
continue;
231-
}
232-
233-
if (! $singleDataProvidedSetItem instanceof ArrayItem) {
234-
continue;
235-
}
236-
237-
$paramOnPositionTypes[] = $this->nodeTypeResolver->getType($singleDataProvidedSetItem->value);
238-
}
239-
}
240-
241-
return $paramOnPositionTypes;
242-
}
130+
// private function inferParam(int $parameterPosition, ClassMethod $dataProviderClassMethod): Type
131+
// {
132+
// $returns = $this->betterNodeFinder->findReturnsScoped($dataProviderClassMethod);
133+
// if ($returns !== []) {
134+
// return $this->resolveReturnStaticArrayTypeByParameterPosition($returns, $parameterPosition);
135+
// }
136+
//
137+
// /** @var Yield_[] $yields */
138+
// $yields = $this->betterNodeFinder->findInstancesOfInFunctionLikeScoped($dataProviderClassMethod, Yield_::class);
139+
// return $this->resolveYieldStaticArrayTypeByParameterPosition($yields, $parameterPosition);
140+
// }
141+
//
142+
// /**
143+
// * @param Return_[] $classMethod
144+
// */
145+
// private function resolveReturnStaticArrayTypeByParameterPosition(array $returns, int $parameterPosition): Type
146+
// {
147+
// $firstReturnedExpr = $returns[0]->expr;
148+
//
149+
// if (! $firstReturnedExpr instanceof Array_) {
150+
// return new MixedType();
151+
// }
152+
//
153+
// $paramOnPositionTypes = $this->resolveParamOnPositionTypes($firstReturnedExpr, $parameterPosition);
154+
// if ($paramOnPositionTypes === []) {
155+
// return new MixedType();
156+
// }
157+
//
158+
// return $this->typeFactory->createMixedPassedOrUnionType($paramOnPositionTypes);
159+
// }
160+
//
161+
// /**
162+
// * @param Yield_[] $classMethod
163+
// */
164+
// private function resolveYieldStaticArrayTypeByParameterPosition(array $yields, int $parameterPosition): Type
165+
// {
166+
// $paramOnPositionTypes = [];
167+
//
168+
// foreach ($yields as $yield) {
169+
// if (! $yield->value instanceof Array_) {
170+
// continue;
171+
// }
172+
//
173+
// $type = $this->getTypeFromClassMethodYield($yield->value);
174+
//
175+
// if (! $type instanceof ConstantArrayType) {
176+
// return $type;
177+
// }
178+
//
179+
// foreach ($type->getValueTypes() as $position => $valueType) {
180+
// if ($position !== $parameterPosition) {
181+
// continue;
182+
// }
183+
//
184+
// $paramOnPositionTypes[] = $valueType;
185+
// }
186+
// }
187+
//
188+
// if ($paramOnPositionTypes === []) {
189+
// return new MixedType();
190+
// }
191+
//
192+
// return $this->typeFactory->createMixedPassedOrUnionType($paramOnPositionTypes);
193+
// }
194+
//
195+
// private function getTypeFromClassMethodYield(Array_ $classMethodYieldArray): MixedType | ConstantArrayType
196+
// {
197+
// $arrayType = $this->nodeTypeResolver->getType($classMethodYieldArray);
198+
//
199+
// // impossible to resolve
200+
// if (! $arrayType instanceof ConstantArrayType) {
201+
// return new MixedType();
202+
// }
203+
//
204+
// return $arrayType;
205+
// }
206+
//
207+
// /**
208+
// * @return Type[]
209+
// */
210+
// private function resolveParamOnPositionTypes(Array_ $array, int $parameterPosition): array
211+
// {
212+
// $paramOnPositionTypes = [];
213+
//
214+
// foreach ($array->items as $singleDataProvidedSet) {
215+
// if (! $singleDataProvidedSet instanceof ArrayItem || ! $singleDataProvidedSet->value instanceof Array_) {
216+
// return [];
217+
// }
218+
//
219+
// foreach ($singleDataProvidedSet->value->items as $position => $singleDataProvidedSetItem) {
220+
// if ($position !== $parameterPosition) {
221+
// continue;
222+
// }
223+
//
224+
// if (! $singleDataProvidedSetItem instanceof ArrayItem) {
225+
// continue;
226+
// }
227+
//
228+
// $paramOnPositionTypes[] = $this->nodeTypeResolver->getType($singleDataProvidedSetItem->value);
229+
// }
230+
// }
231+
//
232+
// return $paramOnPositionTypes;
233+
// }
243234

244235
private function refactorClassMethod(ClassMethod $classMethod, DataProviderNodes $dataProviderNodes): bool
245236
{
@@ -254,12 +245,11 @@ private function refactorClassMethod(ClassMethod $classMethod, DataProviderNodes
254245
continue;
255246
}
256247

257-
$paramTypes = [];
258-
foreach ($dataProviderNodes->getClassMethods() as $dataProviderClassMethod) {
259-
$paramTypes[] = $this->inferParam($parameterPosition, $dataProviderClassMethod);
260-
}
248+
$paramTypeDeclaration = $this->parameterTypeFromDataProviderResolver->resolve(
249+
$parameterPosition,
250+
$dataProviderNodes->getClassMethods()
251+
);
261252

262-
$paramTypeDeclaration = TypeCombinator::union(...$paramTypes);
263253
if ($paramTypeDeclaration instanceof MixedType) {
264254
continue;
265255
}

0 commit comments

Comments
 (0)