Skip to content

Commit c7053b2

Browse files
authored
cleanup REmvoeUnsuedPrivateMethodRector (#7643)
1 parent bca5850 commit c7053b2

File tree

1 file changed

+47
-117
lines changed

1 file changed

+47
-117
lines changed

rules/DeadCode/Rector/ClassMethod/RemoveUnusedPrivateMethodRector.php

Lines changed: 47 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,13 @@
99
use PhpParser\Node\Expr\Variable;
1010
use PhpParser\Node\Stmt\Class_;
1111
use PhpParser\Node\Stmt\ClassMethod;
12-
use PHPStan\PhpDocParser\Ast\PhpDoc\GenericTagValueNode;
13-
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
1412
use PHPStan\Reflection\ClassReflection;
15-
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
16-
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
1713
use Rector\DeadCode\NodeAnalyzer\IsClassMethodUsedAnalyzer;
18-
use Rector\NodeTypeResolver\Node\AttributeKey;
19-
use Rector\Php80\NodeAnalyzer\PhpAttributeAnalyzer;
2014
use Rector\PhpParser\Node\BetterNodeFinder;
2115
use Rector\PHPStan\ScopeFetcher;
2216
use Rector\Rector\AbstractRector;
2317
use Rector\Reflection\ReflectionResolver;
18+
use Rector\TypeDeclarationDocblocks\NodeFinder\DataProviderMethodsFinder;
2419
use Rector\ValueObject\MethodName;
2520
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
2621
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
@@ -34,8 +29,7 @@ public function __construct(
3429
private readonly IsClassMethodUsedAnalyzer $isClassMethodUsedAnalyzer,
3530
private readonly ReflectionResolver $reflectionResolver,
3631
private readonly BetterNodeFinder $betterNodeFinder,
37-
private readonly PhpDocInfoFactory $phpDocInfoFactory,
38-
private readonly PhpAttributeAnalyzer $phpAttributeAnalyzer
32+
private readonly DataProviderMethodsFinder $dataProviderMethodsFinder
3933
) {
4034
}
4135

@@ -84,51 +78,47 @@ public function getNodeTypes(): array
8478
*/
8579
public function refactor(Node $node): ?Node
8680
{
87-
$classMethods = $node->getMethods();
88-
if ($classMethods === []) {
81+
if ($node->getMethods() === []) {
8982
return null;
9083
}
9184

92-
$privateMethods = array_filter(
93-
$classMethods,
94-
fn (ClassMethod $classMethod): bool => $classMethod->isPrivate()
95-
);
96-
97-
if ($privateMethods === []) {
98-
return null;
99-
}
100-
101-
if ($this->hasDynamicMethodCallOnFetchThis($classMethods)) {
102-
return null;
103-
}
85+
$hasChanged = false;
10486

10587
$classReflection = $this->reflectionResolver->resolveClassReflection($node);
10688
if (! $classReflection instanceof ClassReflection) {
10789
return null;
10890
}
10991

110-
$collectionTestMethodsUsesPrivateProvider = $this->collectTestMethodsUsesPrivateDataProvider(
111-
$classReflection,
112-
$node,
113-
$classMethods
114-
);
92+
$dataProviderMethodNames = $this->resolveDataProviderMethodNames($node);
11593

116-
$hasChanged = false;
117-
$scope = ScopeFetcher::fetch($node);
118-
foreach ($privateMethods as $privateMethod) {
119-
if ($this->shouldSkip($privateMethod, $classReflection)) {
94+
foreach ($node->stmts as $classStmtKey => $classStmt) {
95+
if (! $classStmt instanceof ClassMethod) {
96+
continue;
97+
}
98+
99+
if (! $classStmt->isPrivate()) {
120100
continue;
121101
}
122102

123-
if ($this->isClassMethodUsedAnalyzer->isClassMethodUsed($node, $privateMethod, $scope)) {
103+
$classMethod = $classStmt;
104+
if ($this->hasDynamicMethodCallOnFetchThis($classStmt)) {
124105
continue;
125106
}
126107

127-
if (in_array($this->getName($privateMethod), $collectionTestMethodsUsesPrivateProvider, true)) {
108+
$scope = ScopeFetcher::fetch($node);
109+
if ($this->shouldSkip($classStmt, $classReflection)) {
128110
continue;
129111
}
130112

131-
unset($node->stmts[$privateMethod->getAttribute(AttributeKey::STMT_KEY)]);
113+
if ($this->isClassMethodUsedAnalyzer->isClassMethodUsed($node, $classStmt, $scope)) {
114+
continue;
115+
}
116+
117+
if ($this->isNames($classMethod, $dataProviderMethodNames)) {
118+
continue;
119+
}
120+
121+
unset($node->stmts[$classStmtKey]);
132122
$hasChanged = true;
133123
}
134124

@@ -137,69 +127,11 @@ public function refactor(Node $node): ?Node
137127
}
138128

139129
return null;
140-
}
141130

142-
/**
143-
* @param ClassMethod[] $classMethods
144-
* @return string[]
145-
*/
146-
private function collectTestMethodsUsesPrivateDataProvider(
147-
ClassReflection $classReflection,
148-
Class_ $class,
149-
array $classMethods
150-
): array {
151-
if (! $classReflection->is('PHPUnit\Framework\TestCase')) {
152-
return [];
153-
}
154-
155-
$privateMethods = [];
156-
foreach ($classMethods as $classMethod) {
157-
// test method only public, but may use private data provider
158-
// so verify @dataProvider and #[\PHPUnit\Framework\Attributes\DataProvider] only on public methods
159-
if (! $classMethod->isPublic()) {
160-
continue;
161-
}
162-
163-
$phpDocInfo = $this->phpDocInfoFactory->createFromNode($classMethod);
164-
if ($phpDocInfo instanceof PhpDocInfo && $phpDocInfo->hasByName('dataProvider')) {
165-
$dataProvider = $phpDocInfo->getByName('dataProvider');
166-
if ($dataProvider instanceof PhpDocTagNode && $dataProvider->value instanceof GenericTagValueNode) {
167-
$dataProviderMethod = $class->getMethod($dataProvider->value->value);
168-
if ($dataProviderMethod instanceof ClassMethod && $dataProviderMethod->isPrivate()) {
169-
$privateMethods[] = $dataProvider->value->value;
170-
}
171-
}
172-
}
173-
174-
if ($this->phpAttributeAnalyzer->hasPhpAttribute(
175-
$classMethod,
176-
'PHPUnit\Framework\Attributes\DataProvider'
177-
)) {
178-
foreach ($classMethod->attrGroups as $attrGroup) {
179-
foreach ($attrGroup->attrs as $attr) {
180-
if ($attr->name->toString() === 'PHPUnit\Framework\Attributes\DataProvider') {
181-
$argValue = $attr->args[0]->value->value ?? '';
182-
if (is_string($argValue)) {
183-
$dataProviderMethod = $class->getMethod($argValue);
184-
if ($dataProviderMethod instanceof ClassMethod && $dataProviderMethod->isPrivate()) {
185-
$privateMethods[] = $argValue;
186-
}
187-
}
188-
}
189-
}
190-
}
191-
}
192-
}
193-
194-
return $privateMethods;
195131
}
196132

197-
private function shouldSkip(ClassMethod $classMethod, ?ClassReflection $classReflection): bool
133+
private function shouldSkip(ClassMethod $classMethod, ClassReflection $classReflection): bool
198134
{
199-
if (! $classReflection instanceof ClassReflection) {
200-
return true;
201-
}
202-
203135
// unreliable to detect trait, interface, anonymous class: doesn't make sense
204136
if ($classReflection->isTrait()) {
205137
return true;
@@ -221,36 +153,34 @@ private function shouldSkip(ClassMethod $classMethod, ?ClassReflection $classRef
221153
return $classReflection->hasMethod(MethodName::CALL);
222154
}
223155

224-
/**
225-
* @param ClassMethod[] $classMethods
226-
*/
227-
private function hasDynamicMethodCallOnFetchThis(array $classMethods): bool
156+
private function hasDynamicMethodCallOnFetchThis(ClassMethod $classMethod): bool
228157
{
229-
foreach ($classMethods as $classMethod) {
230-
$isFound = (bool) $this->betterNodeFinder->findFirst(
231-
(array) $classMethod->getStmts(),
232-
function (Node $subNode): bool {
233-
if (! $subNode instanceof MethodCall) {
234-
return false;
235-
}
236-
237-
if (! $subNode->var instanceof Variable) {
238-
return false;
239-
}
158+
return (bool) $this->betterNodeFinder->findFirst(
159+
(array) $classMethod->stmts,
160+
function (Node $subNode): bool {
161+
if (! $subNode instanceof MethodCall) {
162+
return false;
163+
}
240164

241-
if (! $this->isName($subNode->var, 'this')) {
242-
return false;
243-
}
165+
if (! $subNode->var instanceof Variable) {
166+
return false;
167+
}
244168

245-
return $subNode->name instanceof Variable;
169+
if (! $this->isName($subNode->var, 'this')) {
170+
return false;
246171
}
247-
);
248172

249-
if ($isFound) {
250-
return true;
173+
return $subNode->name instanceof Variable;
251174
}
252-
}
175+
);
176+
}
253177

254-
return false;
178+
/**
179+
* @return string[]
180+
*/
181+
private function resolveDataProviderMethodNames(Class_ $class): array
182+
{
183+
$dataProviderClassMethods = $this->dataProviderMethodsFinder->findDataProviderNodesInClass($class);
184+
return $this->nodeNameResolver->getNames($dataProviderClassMethods);
255185
}
256186
}

0 commit comments

Comments
 (0)