From 801d367f34aff122d69072dda92a7a34211f815b Mon Sep 17 00:00:00 2001 From: Jean-Luc Herren Date: Fri, 29 Sep 2023 09:25:25 +0200 Subject: [PATCH] AddParamTypeBasedOnPHPUnitDataProviderRector: Check all data providers (#5068) --- .../PhpDocInfo/PhpDocInfo.php | 3 ++ .../Fixture/check_all_providers.php.inc | 26 +++++++++++++++++ ...amTypeBasedOnPHPUnitDataProviderRector.php | 28 +++++++++++++------ 3 files changed, 49 insertions(+), 8 deletions(-) create mode 100644 rules-tests/TypeDeclaration/Rector/ClassMethod/AddParamTypeBasedOnPHPUnitDataProviderRector/Fixture/check_all_providers.php.inc diff --git a/packages/BetterPhpDocParser/PhpDocInfo/PhpDocInfo.php b/packages/BetterPhpDocParser/PhpDocInfo/PhpDocInfo.php index 8b6e9031587..635af403c23 100644 --- a/packages/BetterPhpDocParser/PhpDocInfo/PhpDocInfo.php +++ b/packages/BetterPhpDocParser/PhpDocInfo/PhpDocInfo.php @@ -189,6 +189,9 @@ public function hasByName(string $name): bool return (bool) $this->getTagsByName($name); } + /** + * @api + */ public function getByName(string $name): ?Node { return $this->getTagsByName($name)[0] ?? null; diff --git a/rules-tests/TypeDeclaration/Rector/ClassMethod/AddParamTypeBasedOnPHPUnitDataProviderRector/Fixture/check_all_providers.php.inc b/rules-tests/TypeDeclaration/Rector/ClassMethod/AddParamTypeBasedOnPHPUnitDataProviderRector/Fixture/check_all_providers.php.inc new file mode 100644 index 00000000000..d0f324c3c11 --- /dev/null +++ b/rules-tests/TypeDeclaration/Rector/ClassMethod/AddParamTypeBasedOnPHPUnitDataProviderRector/Fixture/check_all_providers.php.inc @@ -0,0 +1,26 @@ + diff --git a/rules/TypeDeclaration/Rector/ClassMethod/AddParamTypeBasedOnPHPUnitDataProviderRector.php b/rules/TypeDeclaration/Rector/ClassMethod/AddParamTypeBasedOnPHPUnitDataProviderRector.php index 39b2c71eda8..792d9bf7eb4 100644 --- a/rules/TypeDeclaration/Rector/ClassMethod/AddParamTypeBasedOnPHPUnitDataProviderRector.php +++ b/rules/TypeDeclaration/Rector/ClassMethod/AddParamTypeBasedOnPHPUnitDataProviderRector.php @@ -18,6 +18,7 @@ use PHPStan\Type\Constant\ConstantArrayType; use PHPStan\Type\MixedType; use PHPStan\Type\Type; +use PHPStan\Type\TypeCombinator; use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo; use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory; use Rector\Core\Exception\ShouldNotHappenException; @@ -127,12 +128,12 @@ public function refactor(Node $node): ?Node continue; } - $dataProviderPhpDocTagNode = $this->resolveDataProviderPhpDocTagNode($classMethod); - if (! $dataProviderPhpDocTagNode instanceof PhpDocTagNode) { + $dataProviderPhpDocTagNodes = $this->resolveDataProviderPhpDocTagNode($classMethod); + if ($dataProviderPhpDocTagNodes === []) { return null; } - $hasClassMethodChanged = $this->refactorClassMethod($classMethod, $node, $dataProviderPhpDocTagNode); + $hasClassMethodChanged = $this->refactorClassMethod($classMethod, $node, $dataProviderPhpDocTagNodes); if ($hasClassMethodChanged) { $hasChanged = true; } @@ -279,20 +280,26 @@ private function resolveParamOnPositionTypes(Array_ $array, int $parameterPositi return $paramOnPositionTypes; } - private function resolveDataProviderPhpDocTagNode(ClassMethod $classMethod): ?PhpDocTagNode + /** + * @return array + */ + private function resolveDataProviderPhpDocTagNode(ClassMethod $classMethod): array { $classMethodPhpDocInfo = $this->phpDocInfoFactory->createFromNode($classMethod); if (! $classMethodPhpDocInfo instanceof PhpDocInfo) { - return null; + return []; } - return $classMethodPhpDocInfo->getByName('@dataProvider'); + return $classMethodPhpDocInfo->getTagsByName('@dataProvider'); } + /** + * @param array $dataProviderPhpDocTagNodes + */ private function refactorClassMethod( ClassMethod $classMethod, Class_ $class, - PhpDocTagNode $dataProviderPhpDocTagNode + array $dataProviderPhpDocTagNodes ): bool { $hasChanged = false; @@ -301,7 +308,12 @@ private function refactorClassMethod( continue; } - $paramTypeDeclaration = $this->inferParam($class, $param, $dataProviderPhpDocTagNode); + $paramTypes = []; + foreach ($dataProviderPhpDocTagNodes as $phpDocTagNode) { + $paramTypes[] = $this->inferParam($class, $param, $phpDocTagNode); + } + $paramTypeDeclaration = TypeCombinator::union(...$paramTypes); + if ($paramTypeDeclaration instanceof MixedType) { continue; }