55namespace Rector \TypeDeclaration \Rector \ClassMethod ;
66
77use PhpParser \Node ;
8- use PhpParser \Node \ArrayItem ;
9- use PhpParser \Node \Expr \Array_ ;
10- use PhpParser \Node \Expr \Yield_ ;
118use PhpParser \Node \Stmt \Class_ ;
129use PhpParser \Node \Stmt \ClassMethod ;
13- use PhpParser \Node \Stmt \Return_ ;
14- use PHPStan \Type \Constant \ConstantArrayType ;
1510use 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 ;
2011use Rector \PHPStanStaticTypeMapper \Enum \TypeKind ;
2112use Rector \PHPUnit \NodeAnalyzer \TestsNodeAnalyzer ;
2213use Rector \Rector \AbstractRector ;
2314use Rector \StaticTypeMapper \StaticTypeMapper ;
15+ use Rector \TypeDeclaration \TypeAnalyzer \ParameterTypeFromDataProviderResolver ;
2416use Rector \TypeDeclaration \ValueObject \DataProviderNodes ;
2517use Rector \TypeDeclarationDocblocks \NodeFinder \DataProviderMethodsFinder ;
2618use 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