Updated Rector to commit 12b471059bc5717e3f87cf1e811f05396e3571cf

12b471059b [DeadCode] Skip private dataProvider method on RemoveUnusedPrivateMethodRector (#6509)
This commit is contained in:
Tomas Votruba 2024-11-25 14:22:30 +00:00
parent 3e6e8074c1
commit c5a315e2c4
2 changed files with 65 additions and 3 deletions

View File

@ -8,9 +8,13 @@ use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PHPStan\PhpDocParser\Ast\PhpDoc\GenericTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
use PHPStan\Reflection\ClassReflection;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
use Rector\DeadCode\NodeAnalyzer\IsClassMethodUsedAnalyzer;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\Php80\NodeAnalyzer\PhpAttributeAnalyzer;
use Rector\PhpParser\Node\BetterNodeFinder;
use Rector\PHPStan\ScopeFetcher;
use Rector\Rector\AbstractRector;
@ -35,11 +39,21 @@ final class RemoveUnusedPrivateMethodRector extends AbstractRector
* @readonly
*/
private BetterNodeFinder $betterNodeFinder;
public function __construct(IsClassMethodUsedAnalyzer $isClassMethodUsedAnalyzer, ReflectionResolver $reflectionResolver, BetterNodeFinder $betterNodeFinder)
/**
* @readonly
*/
private PhpDocInfoFactory $phpDocInfoFactory;
/**
* @readonly
*/
private PhpAttributeAnalyzer $phpAttributeAnalyzer;
public function __construct(IsClassMethodUsedAnalyzer $isClassMethodUsedAnalyzer, ReflectionResolver $reflectionResolver, BetterNodeFinder $betterNodeFinder, PhpDocInfoFactory $phpDocInfoFactory, PhpAttributeAnalyzer $phpAttributeAnalyzer)
{
$this->isClassMethodUsedAnalyzer = $isClassMethodUsedAnalyzer;
$this->reflectionResolver = $reflectionResolver;
$this->betterNodeFinder = $betterNodeFinder;
$this->phpDocInfoFactory = $phpDocInfoFactory;
$this->phpAttributeAnalyzer = $phpAttributeAnalyzer;
}
public function getRuleDefinition() : RuleDefinition
{
@ -95,6 +109,7 @@ CODE_SAMPLE
}
$hasChanged = \false;
$classReflection = $this->reflectionResolver->resolveClassReflection($node);
$collectionTestMethodsUsesPrivateProvider = $this->collectTestMethodsUsesPrivateDataProvider($classReflection, $node, $classMethods);
foreach ($privateMethods as $privateMethod) {
if ($this->shouldSkip($privateMethod, $classReflection)) {
continue;
@ -102,6 +117,9 @@ CODE_SAMPLE
if ($this->isClassMethodUsedAnalyzer->isClassMethodUsed($node, $privateMethod, $scope)) {
continue;
}
if (\in_array($this->getName($privateMethod), $collectionTestMethodsUsesPrivateProvider, \true)) {
continue;
}
unset($node->stmts[$privateMethod->getAttribute(AttributeKey::STMT_KEY)]);
$hasChanged = \true;
}
@ -110,6 +128,50 @@ CODE_SAMPLE
}
return null;
}
/**
* @param ClassMethod[] $classMethods
* @return string[]
*/
private function collectTestMethodsUsesPrivateDataProvider(ClassReflection $classReflection, Class_ $class, array $classMethods) : array
{
if (!$classReflection->isSubClassOf('PHPUnit\\Framework\\TestCase')) {
return [];
}
$privateMethods = [];
foreach ($classMethods as $classMethod) {
// test method only public, but may use private data provider
// so verify @dataProvider and #[\PHPUnit\Framework\Attributes\DataProvider] only on public methods
if (!$classMethod->isPublic()) {
continue;
}
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($classMethod);
if ($phpDocInfo->hasByName('dataProvider')) {
$dataProvider = $phpDocInfo->getByName('dataProvider');
if ($dataProvider instanceof PhpDocTagNode && $dataProvider->value instanceof GenericTagValueNode) {
$dataProviderMethod = $class->getMethod($dataProvider->value->value);
if ($dataProviderMethod instanceof ClassMethod && $dataProviderMethod->isPrivate()) {
$privateMethods[] = $dataProvider->value->value;
}
}
}
if ($this->phpAttributeAnalyzer->hasPhpAttribute($classMethod, 'PHPUnit\\Framework\\Attributes\\DataProvider')) {
foreach ($classMethod->attrGroups as $attrGroup) {
foreach ($attrGroup->attrs as $attr) {
if ($attr->name->toString() === 'PHPUnit\\Framework\\Attributes\\DataProvider') {
$argValue = $attr->args[0]->value->value ?? '';
if (\is_string($argValue)) {
$dataProviderMethod = $class->getMethod($argValue);
if ($dataProviderMethod instanceof ClassMethod && $dataProviderMethod->isPrivate()) {
$privateMethods[] = $argValue;
}
}
}
}
}
}
}
return $privateMethods;
}
private function shouldSkip(ClassMethod $classMethod, ?ClassReflection $classReflection) : bool
{
if (!$classReflection instanceof ClassReflection) {

View File

@ -19,12 +19,12 @@ final class VersionResolver
* @api
* @var string
*/
public const PACKAGE_VERSION = '1ec42bcc33f0607533e08d75c47b589d89e7649e';
public const PACKAGE_VERSION = '12b471059bc5717e3f87cf1e811f05396e3571cf';
/**
* @api
* @var string
*/
public const RELEASE_DATE = '2024-11-24 18:23:37';
public const RELEASE_DATE = '2024-11-25 21:20:15';
/**
* @var int
*/