Skip to content

Commit c6db9a9

Browse files
authored
Fix unused private property is not sometimes detected
1 parent 3310724 commit c6db9a9

File tree

6 files changed

+84
-2
lines changed

6 files changed

+84
-2
lines changed

src/Rules/DeadCode/UnusedPrivateMethodRule.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,16 @@ public function processNode(Node $node, Scope $scope): array
8484
$methodNameType = $callScope->getType($methodCallNode->name);
8585
$strings = $methodNameType->getConstantStrings();
8686
if (count($strings) === 0) {
87-
return [];
87+
// handle subtractions of a dynamic method call
88+
foreach ($methods as $lowerMethodName => $method) {
89+
if ((new ConstantStringType($method->getNode()->name->toString()))->isSuperTypeOf($methodNameType)->no()) {
90+
continue;
91+
}
92+
93+
unset($methods[$lowerMethodName]);
94+
}
95+
96+
continue;
8897
}
8998

9099
$methodNames = array_map(static fn (ConstantStringType $type): string => $type->getValue(), $strings);

src/Rules/DeadCode/UnusedPrivatePropertyRule.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,16 @@ public function processNode(Node $node, Scope $scope): array
120120
$propertyNameType = $usage->getScope()->getType($fetch->name);
121121
$strings = $propertyNameType->getConstantStrings();
122122
if (count($strings) === 0) {
123-
return [];
123+
// handle subtractions of a dynamic property fetch
124+
foreach ($properties as $propertyName => $data) {
125+
if ((new ConstantStringType($propertyName))->isSuperTypeOf($propertyNameType)->no()) {
126+
continue;
127+
}
128+
129+
unset($properties[$propertyName]);
130+
}
131+
132+
continue;
124133
}
125134

126135
$propertyNames = array_map(static fn (ConstantStringType $type): string => $type->getValue(), $strings);

tests/PHPStan/Rules/DeadCode/UnusedPrivateMethodRuleTest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,4 +133,14 @@ public function testBug9765(): void
133133
$this->analyse([__DIR__ . '/data/bug-9765.php'], []);
134134
}
135135

136+
public function testBug11802(): void
137+
{
138+
$this->analyse([__DIR__ . '/data/bug-11802b.php'], [
139+
[
140+
'Method Bug11802b\HelloWorld::doBar() is unused.',
141+
10,
142+
],
143+
]);
144+
}
145+
136146
}

tests/PHPStan/Rules/DeadCode/UnusedPrivatePropertyRuleTest.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,4 +336,19 @@ public function testBug7251(): void
336336
$this->analyse([__DIR__ . '/data/bug-7251.php'], []);
337337
}
338338

339+
public function testBug11802(): void
340+
{
341+
$tip = 'See: https://phpstan.org/developing-extensions/always-read-written-properties';
342+
343+
$this->alwaysWrittenTags = [];
344+
$this->alwaysReadTags = [];
345+
$this->analyse([__DIR__ . '/data/bug-11802.php'], [
346+
[
347+
'Property Bug11802\HelloWorld::$isFinal is never read, only written.',
348+
8,
349+
$tip,
350+
],
351+
]);
352+
}
353+
339354
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php // lint >= 8.0
2+
3+
namespace Bug11802;
4+
5+
class HelloWorld
6+
{
7+
public function __construct(
8+
private bool $isFinal,
9+
private bool $used
10+
)
11+
{
12+
}
13+
14+
public function doFoo(HelloWorld $x, $y): void
15+
{
16+
if ($y !== 'isFinal') {
17+
$s = $x->{$y};
18+
}
19+
}
20+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php // lint >= 8.0
2+
3+
namespace Bug11802b;
4+
5+
class HelloWorld
6+
{
7+
public function __construct(
8+
) {}
9+
10+
private function doBar():void {}
11+
12+
private function doFooBar():void {}
13+
14+
public function doFoo(HelloWorld $x, $y): void {
15+
if ($y !== 'doBar') {
16+
$s = $x->$y();
17+
}
18+
}
19+
}

0 commit comments

Comments
 (0)