Skip to content

Commit 606582e

Browse files
authored
Fix crash upon provided usages inside property hooks (#302)
1 parent be0ea81 commit 606582e

File tree

3 files changed

+30
-3
lines changed

3 files changed

+30
-3
lines changed

src/Collector/ProvidedUsagesCollector.php

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use PHPStan\Analyser\Scope;
88
use PHPStan\Collectors\Collector;
99
use PHPStan\Reflection\ReflectionProvider;
10+
use ShipMonk\PHPStan\DeadCode\Enum\MemberType;
1011
use ShipMonk\PHPStan\DeadCode\Excluder\MemberUsageExcluder;
1112
use ShipMonk\PHPStan\DeadCode\Graph\ClassMemberUsage;
1213
use ShipMonk\PHPStan\DeadCode\Graph\CollectedUsage;
@@ -85,7 +86,7 @@ private function validateUsage(
8586
{
8687
$origin = $usage->getOrigin();
8788
$originClass = $origin->getClassName();
88-
$originMethod = $origin->getMemberName();
89+
$originMember = $origin->getMemberName();
8990

9091
$context = sprintf(
9192
"It emitted usage of %s by %s for node '%s' in '%s' on line %s",
@@ -101,8 +102,14 @@ private function validateUsage(
101102
throw new LogicException("Class '{$originClass}' does not exist. $context");
102103
}
103104

104-
if ($originMethod !== null && !$this->reflectionProvider->getClass($originClass)->hasMethod($originMethod)) {
105-
throw new LogicException("Method '{$originMethod}' does not exist in class '$originClass'. $context");
105+
if ($originMember !== null) {
106+
if ($origin->getMemberType() === MemberType::METHOD && !$this->reflectionProvider->getClass($originClass)->hasMethod($originMember)) {
107+
throw new LogicException("Method '{$originMember}' does not exist in class '$originClass'. $context");
108+
}
109+
110+
if ($origin->getMemberType() === MemberType::PROPERTY && !$this->reflectionProvider->getClass($originClass)->hasNativeProperty($originMember)) {
111+
throw new LogicException("Property '{$originMember}' does not exist in class '$originClass'. $context");
112+
}
106113
}
107114
}
108115
}

tests/Rule/DeadCodeRuleTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1026,6 +1026,7 @@ public static function provideFiles(): Traversable
10261026
yield 'provider-nette-tester' => [__DIR__ . '/data/providers/nette-tester.php'];
10271027
yield 'provider-apiphpdoc' => [__DIR__ . '/data/providers/api-phpdoc.php', self::requiresPhp(8_01_00)];
10281028
yield 'provider-enum' => [__DIR__ . '/data/providers/enum.php', self::requiresPhp(8_01_00)];
1029+
yield 'provider-enum-hooks' => [__DIR__ . '/data/providers/enum-hooks.php', self::requiresPhp(8_01_00)];
10291030
yield 'provider-builtin' => [__DIR__ . '/data/providers/builtin.php'];
10301031
yield 'provider-stream-wrapper' => [__DIR__ . '/data/providers/stream-wrapper.php'];
10311032

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace EnumProviderHooks;
4+
5+
enum Status: string {
6+
case Active = 'active';
7+
case Inactive = 'inactive'; // error: Unused EnumProviderHooks\Status::Inactive
8+
}
9+
10+
class Project
11+
{
12+
public Status $status {
13+
get => Status::from('active');
14+
}
15+
}
16+
17+
function test(): void {
18+
echo (new Project())->status;
19+
}

0 commit comments

Comments
 (0)