Skip to content

Commit b17d529

Browse files
committed
Optimize enums with many cases
1 parent a9fe295 commit b17d529

File tree

1 file changed

+38
-0
lines changed

1 file changed

+38
-0
lines changed

src/Type/TypeCombinator.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use PHPStan\Type\Constant\ConstantFloatType;
1717
use PHPStan\Type\Constant\ConstantIntegerType;
1818
use PHPStan\Type\Constant\ConstantStringType;
19+
use PHPStan\Type\Enum\EnumCaseObjectType;
1920
use PHPStan\Type\Generic\GenericClassStringType;
2021
use PHPStan\Type\Generic\TemplateBenevolentUnionType;
2122
use PHPStan\Type\Generic\TemplateType;
@@ -179,6 +180,7 @@ public static function union(Type ...$types): Type
179180
$arrayTypes = [];
180181
$scalarTypes = [];
181182
$hasGenericScalarTypes = [];
183+
$enumCaseTypes = [];
182184
for ($i = 0; $i < $typesCount; $i++) {
183185
if ($types[$i] instanceof ConstantScalarType) {
184186
$type = $types[$i];
@@ -198,6 +200,12 @@ public static function union(Type ...$types): Type
198200
if ($types[$i] instanceof StringType && !$types[$i] instanceof ClassStringType) {
199201
$hasGenericScalarTypes[ConstantStringType::class] = true;
200202
}
203+
if ($types[$i] instanceof EnumCaseObjectType) {
204+
$enumCaseTypes[$types[$i]->describe(VerbosityLevel::cache())] = $types[$i];
205+
unset($types[$i]);
206+
continue;
207+
}
208+
201209
if (!$types[$i]->isArray()->yes()) {
202210
continue;
203211
}
@@ -210,6 +218,7 @@ public static function union(Type ...$types): Type
210218
$scalarTypes[$classType] = array_values($scalarTypeItems);
211219
}
212220

221+
$enumCaseTypes = array_values($enumCaseTypes);
213222
$types = array_values($types);
214223
$typesCount = count($types);
215224

@@ -291,6 +300,35 @@ public static function union(Type ...$types): Type
291300
}
292301
}
293302

303+
$enumCasesCount = count($enumCaseTypes);
304+
for ($i = 0; $i < $typesCount; $i++) {
305+
for ($j = 0; $j < $enumCasesCount; $j++) {
306+
$compareResult = self::compareTypesInUnion($types[$i], $enumCaseTypes[$j]);
307+
if ($compareResult === null) {
308+
continue;
309+
}
310+
311+
[$a, $b] = $compareResult;
312+
if ($a !== null) {
313+
$types[$i] = $a;
314+
array_splice($enumCaseTypes, $j--, 1);
315+
$enumCasesCount--;
316+
continue 1;
317+
}
318+
if ($b !== null) {
319+
$enumCaseTypes[$j] = $b;
320+
array_splice($types, $i--, 1);
321+
$typesCount--;
322+
continue 2;
323+
}
324+
}
325+
}
326+
327+
foreach ($enumCaseTypes as $enumCaseType) {
328+
$types[] = $enumCaseType;
329+
$typesCount++;
330+
}
331+
294332
foreach ($scalarTypes as $scalarTypeItems) {
295333
foreach ($scalarTypeItems as $scalarType) {
296334
$types[] = $scalarType;

0 commit comments

Comments
 (0)