rector/vendor/rector/rector-phpunit/src/NodeFinder/DataProviderClassMethodFinder.php
Tomas Votruba f397ad92ed Updated Rector to commit e68c8d23cbbdb9dbfef66133af6bb4f1857015ad
e68c8d23cb Fix CallableTypeParameterNode and IdentifierTypeParameterNode crash (#3353)
2023-02-07 12:32:23 +00:00

105 lines
3.8 KiB
PHP

<?php
declare (strict_types=1);
namespace Rector\PHPUnit\NodeFinder;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PHPStan\PhpDocParser\Ast\PhpDoc\GenericTagValueNode;
use PHPStan\Reflection\ClassReflection;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
use Rector\Core\PhpParser\AstResolver;
use Rector\Core\Reflection\ReflectionResolver;
final class DataProviderClassMethodFinder
{
/**
* @readonly
* @var \Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory
*/
private $phpDocInfoFactory;
/**
* @readonly
* @var \Rector\Core\Reflection\ReflectionResolver
*/
private $reflectionResolver;
/**
* @readonly
* @var \Rector\Core\PhpParser\AstResolver
*/
private $astResolver;
public function __construct(PhpDocInfoFactory $phpDocInfoFactory, ReflectionResolver $reflectionResolver, AstResolver $astResolver)
{
$this->phpDocInfoFactory = $phpDocInfoFactory;
$this->reflectionResolver = $reflectionResolver;
$this->astResolver = $astResolver;
}
/**
* @return ClassMethod[]
*/
public function find(Class_ $class) : array
{
$parentAbstractClasses = $this->resolveParentAbstractClasses($class);
$targetClasses = \array_merge([$class], $parentAbstractClasses);
// foreach to find method names
$dataProviderMethodNames = [];
foreach ($targetClasses as $targetClass) {
$dataProviderMethodNames = \array_merge($dataProviderMethodNames, $this->resolverDataProviderClassMethodNames($targetClass));
}
$dataProviderClassMethods = [];
foreach ($dataProviderMethodNames as $dataProviderMethodName) {
$dataProviderClassMethod = $class->getMethod($dataProviderMethodName);
if (!$dataProviderClassMethod instanceof ClassMethod) {
continue;
}
$dataProviderClassMethods[] = $dataProviderClassMethod;
}
return $dataProviderClassMethods;
}
/**
* @return string[]
*/
private function resolverDataProviderClassMethodNames(Class_ $class) : array
{
$dataProviderMethodNames = [];
foreach ($class->getMethods() as $classMethod) {
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($classMethod);
$dataProviderTagValueNodes = $phpDocInfo->getTagsByName('dataProvider');
if ($dataProviderTagValueNodes === []) {
continue;
}
foreach ($dataProviderTagValueNodes as $dataProviderTagValueNode) {
if (!$dataProviderTagValueNode->value instanceof GenericTagValueNode) {
continue;
}
$dataProviderMethodNames[] = $this->resolveMethodName($dataProviderTagValueNode->value);
}
}
return $dataProviderMethodNames;
}
private function resolveMethodName(GenericTagValueNode $genericTagValueNode) : string
{
$rawValue = $genericTagValueNode->value;
return \trim($rawValue, '()');
}
/**
* @return Class_[]
*/
private function resolveParentAbstractClasses(Class_ $class) : array
{
// resolve from parent one?
$classReflection = $this->reflectionResolver->resolveClassReflection($class);
if (!$classReflection instanceof ClassReflection) {
return [];
}
$parentClasses = [];
foreach ($classReflection->getParents() as $parentClassReflection) {
// is the top parent class? stop
if ($parentClassReflection->getName() === 'PHPUnit\\Framework\\TestCase') {
break;
}
$parentClasses[] = $this->astResolver->resolveClassFromClassReflection($parentClassReflection);
}
return $parentClasses;
}
}