Skip to content

Commit 7912caf

Browse files
committed
Type::getFiniteTypes()
1 parent 175307e commit 7912caf

38 files changed

+423
-1
lines changed

src/Type/Accessory/AccessoryArrayListType.php

+5
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,11 @@ public function exponentiate(Type $exponent): Type
474474
return new ErrorType();
475475
}
476476

477+
public function getFiniteTypes(): array
478+
{
479+
return [];
480+
}
481+
477482
public function toPhpDocNode(): TypeNode
478483
{
479484
return new IdentifierTypeNode('list');

src/Type/Accessory/AccessoryLiteralStringType.php

+5
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,11 @@ public function exponentiate(Type $exponent): Type
335335
]);
336336
}
337337

338+
public function getFiniteTypes(): array
339+
{
340+
return [];
341+
}
342+
338343
public function toPhpDocNode(): TypeNode
339344
{
340345
return new IdentifierTypeNode('literal-string');

src/Type/Accessory/AccessoryNonEmptyStringType.php

+5
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,11 @@ public function exponentiate(Type $exponent): Type
340340
]);
341341
}
342342

343+
public function getFiniteTypes(): array
344+
{
345+
return [];
346+
}
347+
343348
public function toPhpDocNode(): TypeNode
344349
{
345350
return new IdentifierTypeNode('non-empty-string');

src/Type/Accessory/AccessoryNonFalsyStringType.php

+5
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,11 @@ public function exponentiate(Type $exponent): Type
331331
]);
332332
}
333333

334+
public function getFiniteTypes(): array
335+
{
336+
return [];
337+
}
338+
334339
public function toPhpDocNode(): TypeNode
335340
{
336341
return new IdentifierTypeNode('non-falsy-string');

src/Type/Accessory/AccessoryNumericStringType.php

+5
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,11 @@ public function exponentiate(Type $exponent): Type
342342
]);
343343
}
344344

345+
public function getFiniteTypes(): array
346+
{
347+
return [];
348+
}
349+
345350
public function toPhpDocNode(): TypeNode
346351
{
347352
return new IdentifierTypeNode('numeric-string');

src/Type/Accessory/HasMethodType.php

+5
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,11 @@ public function exponentiate(Type $exponent): Type
190190
return new ErrorType();
191191
}
192192

193+
public function getFiniteTypes(): array
194+
{
195+
return [];
196+
}
197+
193198
public static function __set_state(array $properties): Type
194199
{
195200
return new self($properties['methodName']);

src/Type/Accessory/HasOffsetType.php

+5
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,11 @@ public function exponentiate(Type $exponent): Type
363363
return new ErrorType();
364364
}
365365

366+
public function getFiniteTypes(): array
367+
{
368+
return [];
369+
}
370+
366371
public static function __set_state(array $properties): Type
367372
{
368373
return new self($properties['offsetType']);

src/Type/Accessory/HasOffsetValueType.php

+5
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,11 @@ public function exponentiate(Type $exponent): Type
419419
return new ErrorType();
420420
}
421421

422+
public function getFiniteTypes(): array
423+
{
424+
return [];
425+
}
426+
422427
public static function __set_state(array $properties): Type
423428
{
424429
return new self($properties['offsetType'], $properties['valueType']);

src/Type/Accessory/HasPropertyType.php

+5
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,11 @@ public function exponentiate(Type $exponent): Type
152152
return new ErrorType();
153153
}
154154

155+
public function getFiniteTypes(): array
156+
{
157+
return [];
158+
}
159+
155160
public static function __set_state(array $properties): Type
156161
{
157162
return new self($properties['propertyName']);

src/Type/Accessory/NonEmptyArrayType.php

+5
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,11 @@ public function exponentiate(Type $exponent): Type
429429
return new ErrorType();
430430
}
431431

432+
public function getFiniteTypes(): array
433+
{
434+
return [];
435+
}
436+
432437
public static function __set_state(array $properties): Type
433438
{
434439
return new self();

src/Type/Accessory/OversizedArrayType.php

+5
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,11 @@ public function exponentiate(Type $exponent): Type
415415
return new ErrorType();
416416
}
417417

418+
public function getFiniteTypes(): array
419+
{
420+
return [];
421+
}
422+
418423
public static function __set_state(array $properties): Type
419424
{
420425
return new self();

src/Type/ArrayType.php

+5
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,11 @@ public function exponentiate(Type $exponent): Type
728728
return new ErrorType();
729729
}
730730

731+
public function getFiniteTypes(): array
732+
{
733+
return [];
734+
}
735+
731736
/**
732737
* @param mixed[] $properties
733738
*/

src/Type/BooleanType.php

+8
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,14 @@ public function tryRemove(Type $typeToRemove): ?Type
135135
return null;
136136
}
137137

138+
public function getFiniteTypes(): array
139+
{
140+
return [
141+
new ConstantBooleanType(true),
142+
new ConstantBooleanType(false),
143+
];
144+
}
145+
138146
public function exponentiate(Type $exponent): Type
139147
{
140148
return ExponentiateHelper::exponentiate($this, $exponent);

src/Type/CallableType.php

+5
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,11 @@ public function exponentiate(Type $exponent): Type
524524
return new ErrorType();
525525
}
526526

527+
public function getFiniteTypes(): array
528+
{
529+
return [];
530+
}
531+
527532
public function toPhpDocNode(): TypeNode
528533
{
529534
if ($this->isCommonCallable) {

src/Type/ClosureType.php

+5
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,11 @@ public function exponentiate(Type $exponent): Type
588588
return new ErrorType();
589589
}
590590

591+
public function getFiniteTypes(): array
592+
{
593+
return [];
594+
}
595+
591596
public function toPhpDocNode(): TypeNode
592597
{
593598
$parameters = [];

src/Type/Constant/ConstantArrayType.php

+40
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace PHPStan\Type\Constant;
44

55
use Nette\Utils\Strings;
6+
use PHPStan\Internal\CombinationsHelper;
67
use PHPStan\Php\PhpVersion;
78
use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprIntegerNode;
89
use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprStringNode;
@@ -13,6 +14,7 @@
1314
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
1415
use PHPStan\Reflection\ClassMemberAccessAnswerer;
1516
use PHPStan\Reflection\InaccessibleMethod;
17+
use PHPStan\Reflection\InitializerExprTypeResolver;
1618
use PHPStan\Reflection\ParametersAcceptor;
1719
use PHPStan\Reflection\TrivialParametersAcceptor;
1820
use PHPStan\ShouldNotHappenException;
@@ -1606,6 +1608,44 @@ public static function isValidIdentifier(string $value): bool
16061608
return $result !== null;
16071609
}
16081610

1611+
public function getFiniteTypes(): array
1612+
{
1613+
$arraysArraysForCombinations = [];
1614+
$count = 0;
1615+
foreach ($this->getAllArrays() as $array) {
1616+
$values = $array->getValueTypes();
1617+
$arraysForCombinations = [];
1618+
$combinationCount = 1;
1619+
foreach ($values as $valueType) {
1620+
if ($valueType->getFiniteTypes() === []) {
1621+
return [];
1622+
}
1623+
$arraysForCombinations[] = $valueType->getFiniteTypes();
1624+
$combinationCount *= count($valueType->getFiniteTypes());
1625+
}
1626+
$arraysArraysForCombinations[] = $arraysForCombinations;
1627+
$count += $combinationCount;
1628+
}
1629+
1630+
if ($count > InitializerExprTypeResolver::CALCULATE_SCALARS_LIMIT) {
1631+
return [];
1632+
}
1633+
1634+
$finiteTypes = [];
1635+
foreach ($arraysArraysForCombinations as $arraysForCombinations) {
1636+
$combinations = CombinationsHelper::combinations($arraysForCombinations);
1637+
foreach ($combinations as $combination) {
1638+
$builder = ConstantArrayTypeBuilder::createEmpty();
1639+
foreach ($combination as $i => $v) {
1640+
$builder->setOffsetValueType($this->keyTypes[$i], $v);
1641+
}
1642+
$finiteTypes[] = $builder->getArray();
1643+
}
1644+
}
1645+
1646+
return $finiteTypes;
1647+
}
1648+
16091649
/**
16101650
* @param mixed[] $properties
16111651
*/

src/Type/FloatType.php

+5
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,11 @@ public function toPhpDocNode(): TypeNode
269269
return new IdentifierTypeNode('float');
270270
}
271271

272+
public function getFiniteTypes(): array
273+
{
274+
return [];
275+
}
276+
272277
/**
273278
* @param mixed[] $properties
274279
*/

src/Type/IntegerRangeType.php

+20
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use PHPStan\PhpDocParser\Ast\Type\GenericTypeNode;
88
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
99
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
10+
use PHPStan\Reflection\InitializerExprTypeResolver;
1011
use PHPStan\TrinaryLogic;
1112
use PHPStan\Type\Constant\ConstantBooleanType;
1213
use PHPStan\Type\Constant\ConstantIntegerType;
@@ -615,6 +616,25 @@ public function exponentiate(Type $exponent): Type
615616
return parent::exponentiate($exponent);
616617
}
617618

619+
public function getFiniteTypes(): array
620+
{
621+
if ($this->min === null || $this->max === null) {
622+
return [];
623+
}
624+
625+
$size = $this->max - $this->min;
626+
if ($size > InitializerExprTypeResolver::CALCULATE_SCALARS_LIMIT) {
627+
return [];
628+
}
629+
630+
$types = [];
631+
for ($i = $this->min; $i <= $this->max; $i++) {
632+
$types[] = new ConstantIntegerType($i);
633+
}
634+
635+
return $types;
636+
}
637+
618638
public function toPhpDocNode(): TypeNode
619639
{
620640
if ($this->min === null) {

src/Type/IntegerType.php

+5
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,11 @@ public function tryRemove(Type $typeToRemove): ?Type
157157
return null;
158158
}
159159

160+
public function getFiniteTypes(): array
161+
{
162+
return [];
163+
}
164+
160165
public function exponentiate(Type $exponent): Type
161166
{
162167
return ExponentiateHelper::exponentiate($this, $exponent);

src/Type/IntersectionType.php

+23-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use PHPStan\Reflection\ClassMemberAccessAnswerer;
1111
use PHPStan\Reflection\ConstantReflection;
1212
use PHPStan\Reflection\ExtendedMethodReflection;
13+
use PHPStan\Reflection\InitializerExprTypeResolver;
1314
use PHPStan\Reflection\ParametersAcceptor;
1415
use PHPStan\Reflection\PropertyReflection;
1516
use PHPStan\Reflection\TrivialParametersAcceptor;
@@ -40,6 +41,7 @@
4041
use function implode;
4142
use function in_array;
4243
use function ksort;
44+
use function md5;
4345
use function sprintf;
4446
use function strlen;
4547
use function substr;
@@ -719,7 +721,7 @@ public function getEnumCases(): array
719721
foreach ($this->types as $type) {
720722
$oneType = [];
721723
foreach ($type->getEnumCases() as $enumCase) {
722-
$oneType[$enumCase->describe(VerbosityLevel::typeOnly())] = $enumCase;
724+
$oneType[md5($enumCase->describe(VerbosityLevel::typeOnly()))] = $enumCase;
723725
}
724726
$compare[] = $oneType;
725727
}
@@ -995,6 +997,26 @@ public function exponentiate(Type $exponent): Type
995997
return $this->intersectTypes(static fn (Type $type): Type => $type->exponentiate($exponent));
996998
}
997999

1000+
public function getFiniteTypes(): array
1001+
{
1002+
$compare = [];
1003+
foreach ($this->types as $type) {
1004+
$oneType = [];
1005+
foreach ($type->getFiniteTypes() as $finiteType) {
1006+
$oneType[md5($finiteType->describe(VerbosityLevel::typeOnly()))] = $finiteType;
1007+
}
1008+
$compare[] = $oneType;
1009+
}
1010+
1011+
$result = array_values(array_intersect_key(...$compare));
1012+
1013+
if (count($result) > InitializerExprTypeResolver::CALCULATE_SCALARS_LIMIT) {
1014+
return [];
1015+
}
1016+
1017+
return $result;
1018+
}
1019+
9981020
/**
9991021
* @param mixed[] $properties
10001022
*/

src/Type/IterableType.php

+5
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,11 @@ public function exponentiate(Type $exponent): Type
470470
return new ErrorType();
471471
}
472472

473+
public function getFiniteTypes(): array
474+
{
475+
return [];
476+
}
477+
473478
public function toPhpDocNode(): TypeNode
474479
{
475480
$isMixedKeyType = $this->keyType instanceof MixedType && $this->keyType->describe(VerbosityLevel::precise()) === 'mixed';

src/Type/MixedType.php

+5
Original file line numberDiff line numberDiff line change
@@ -909,6 +909,11 @@ public function exponentiate(Type $exponent): Type
909909
]);
910910
}
911911

912+
public function getFiniteTypes(): array
913+
{
914+
return [];
915+
}
916+
912917
public function toPhpDocNode(): TypeNode
913918
{
914919
return new IdentifierTypeNode('mixed');

src/Type/NeverType.php

+5
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,11 @@ public function exponentiate(Type $exponent): Type
496496
return $this;
497497
}
498498

499+
public function getFiniteTypes(): array
500+
{
501+
return [];
502+
}
503+
499504
public function toPhpDocNode(): TypeNode
500505
{
501506
return new IdentifierTypeNode('never');

0 commit comments

Comments
 (0)