Skip to content

Commit d605da6

Browse files
Improve EnumSanityRule
1 parent 214927b commit d605da6

File tree

3 files changed

+56
-32
lines changed

3 files changed

+56
-32
lines changed

src/Rules/Classes/EnumSanityRule.php

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -145,27 +145,16 @@ public function processNode(Node $node, Scope $scope): array
145145
}
146146
$caseName = $stmt->name->name;
147147

148-
if ($stmt->expr instanceof Node\Scalar\Int_ || $stmt->expr instanceof Node\Scalar\String_) {
149-
if ($enumNode->scalarType === null) {
150-
$errors[] = RuleErrorBuilder::message(sprintf(
151-
'Enum %s is not backed, but case %s has value %s.',
152-
$classReflection->getDisplayName(),
153-
$caseName,
154-
$stmt->expr->value,
155-
))
156-
->identifier('enum.caseWithValue')
157-
->line($stmt->getStartLine())
158-
->nonIgnorable()
159-
->build();
160-
} else {
161-
$caseValue = $stmt->expr->value;
162-
163-
if (!isset($enumCases[$caseValue])) {
164-
$enumCases[$caseValue] = [];
165-
}
166-
167-
$enumCases[$caseValue][] = $caseName;
168-
}
148+
if ($enumNode->scalarType === null && $stmt->expr !== null) {
149+
$errors[] = RuleErrorBuilder::message(sprintf(
150+
'Enum %s is not backed, but case %s has value.',
151+
$classReflection->getDisplayName(),
152+
$caseName,
153+
))
154+
->identifier('enum.caseWithValue')
155+
->line($stmt->getStartLine())
156+
->nonIgnorable()
157+
->build();
169158
}
170159

171160
if ($enumNode->scalarType === null) {
@@ -187,6 +176,16 @@ public function processNode(Node $node, Scope $scope): array
187176
}
188177

189178
$exprType = $scope->getType($stmt->expr);
179+
$constantValues = $exprType->getConstantScalarValues();
180+
if (count($constantValues) === 1) {
181+
$caseValue = $constantValues[0];
182+
if (!isset($enumCases[$caseValue])) {
183+
$enumCases[$caseValue] = [];
184+
}
185+
186+
$enumCases[$caseValue][] = $caseName;
187+
}
188+
190189
$scalarType = $enumNode->scalarType->toLowerString() === 'int' ? new IntegerType() : new StringType();
191190
if ($scalarType->isSuperTypeOf($exprType)->yes()) {
192191
continue;

tests/PHPStan/Rules/Classes/EnumSanityRuleTest.php

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ public function testRule(): void
9595
110,
9696
],
9797
[
98-
'Enum EnumSanity\EnumWithValueButNotBacked is not backed, but case FOO has value 1.',
98+
'Enum EnumSanity\EnumWithValueButNotBacked is not backed, but case FOO has value.',
9999
114,
100100
],
101101
[
@@ -119,24 +119,28 @@ public function testBug9402(): void
119119
}
120120

121121
#[RequiresPhp('>= 8.1')]
122-
public function testBug11592(): void
122+
public function testBug13768(): void
123123
{
124-
$this->analyse([__DIR__ . '/data/bug-11592.php'], [
124+
$this->analyse([__DIR__ . '/data/bug-13768.php'], [
125125
[
126-
'Enum Bug11592\Test2 cannot redeclare native method cases().',
127-
22,
126+
'Enum Bug13768\Order is not backed, but case A has value.',
127+
7,
128128
],
129129
[
130-
'Enum Bug11592\BackedTest2 cannot redeclare native method cases().',
131-
37,
130+
'Enum Bug13768\Order is not backed, but case B has value.',
131+
8,
132132
],
133133
[
134-
'Enum Bug11592\BackedTest2 cannot redeclare native method from().',
135-
39,
134+
'Enum Bug13768\Order is not backed, but case C has value.',
135+
9,
136+
],
137+
[
138+
'Enum Bug13768\Order is not backed, but case D has value.',
139+
10,
136140
],
137141
[
138-
'Enum Bug11592\BackedTest2 cannot redeclare native method tryFrom().',
139-
41,
142+
'Enum Bug13768\Backed has duplicate value 1 for cases One, Two.',
143+
18,
140144
],
141145
]);
142146
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace Bug13768;
4+
5+
enum Order {
6+
case U;
7+
case A = 1.5;
8+
case B = 2.5;
9+
case C = 3;
10+
case D = '3';
11+
}
12+
13+
class Foo
14+
{
15+
public const A = 1;
16+
}
17+
18+
enum Backed: int {
19+
case One = Foo::A;
20+
case Two = Foo::A;
21+
}

0 commit comments

Comments
 (0)