Skip to content

Commit 43d6b0b

Browse files
herndlmondrejmirtes
authored andcommitted
Add Type::getIterableCount()
1 parent a272969 commit 43d6b0b

17 files changed

+101
-33
lines changed

src/Rules/FunctionCallParametersCheck.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ public function check(
104104
if (count($arrays) > 0) {
105105
$minKeys = null;
106106
foreach ($arrays as $array) {
107-
$countType = $array->count();
107+
$countType = $array->getIterableCount();
108108
if ($countType instanceof ConstantIntegerType) {
109109
$keysCount = $countType->getValue();
110110
} elseif ($countType instanceof IntegerRangeType) {

src/Type/Accessory/AccessoryArrayListType.php

+5
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,11 @@ public function isIterableAtLeastOnce(): TrinaryLogic
147147
return TrinaryLogic::createMaybe();
148148
}
149149

150+
public function getIterableCount(): Type
151+
{
152+
return IntegerRangeType::fromInterval(0, null);
153+
}
154+
150155
public function getIterableKeyType(): Type
151156
{
152157
return IntegerRangeType::fromInterval(0, null);

src/Type/Accessory/NonEmptyArrayType.php

+6
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use PHPStan\Type\Constant\ConstantFloatType;
88
use PHPStan\Type\Constant\ConstantIntegerType;
99
use PHPStan\Type\ErrorType;
10+
use PHPStan\Type\IntegerRangeType;
1011
use PHPStan\Type\IntersectionType;
1112
use PHPStan\Type\MixedType;
1213
use PHPStan\Type\Traits\MaybeCallableTypeTrait;
@@ -136,6 +137,11 @@ public function isIterableAtLeastOnce(): TrinaryLogic
136137
return TrinaryLogic::createYes();
137138
}
138139

140+
public function getIterableCount(): Type
141+
{
142+
return IntegerRangeType::fromInterval(1, null);
143+
}
144+
139145
public function getIterableKeyType(): Type
140146
{
141147
return new MixedType();

src/Type/Accessory/OversizedArrayType.php

+6
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use PHPStan\Type\Constant\ConstantFloatType;
88
use PHPStan\Type\Constant\ConstantIntegerType;
99
use PHPStan\Type\ErrorType;
10+
use PHPStan\Type\IntegerRangeType;
1011
use PHPStan\Type\IntersectionType;
1112
use PHPStan\Type\MixedType;
1213
use PHPStan\Type\Traits\MaybeCallableTypeTrait;
@@ -135,6 +136,11 @@ public function isIterableAtLeastOnce(): TrinaryLogic
135136
return TrinaryLogic::createYes();
136137
}
137138

139+
public function getIterableCount(): Type
140+
{
141+
return IntegerRangeType::fromInterval(0, null);
142+
}
143+
138144
public function getIterableKeyType(): Type
139145
{
140146
return new MixedType();

src/Type/ArrayType.php

+7-1
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,11 @@ public function isIterableAtLeastOnce(): TrinaryLogic
195195
return TrinaryLogic::createMaybe();
196196
}
197197

198+
public function getIterableCount(): Type
199+
{
200+
return IntegerRangeType::fromInterval(0, null);
201+
}
202+
198203
public function getIterableKeyType(): Type
199204
{
200205
$keyType = $this->keyType;
@@ -407,9 +412,10 @@ public function toArray(): Type
407412
return $this;
408413
}
409414

415+
/** @deprecated Use getIterableCount() instead */
410416
public function count(): Type
411417
{
412-
return IntegerRangeType::fromInterval(0, null);
418+
return $this->getIterableCount();
413419
}
414420

415421
public static function castToArrayKeyType(Type $offsetType): Type

src/Type/Constant/ConstantArrayType.php

+14-8
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,17 @@ public function isIterableAtLeastOnce(): TrinaryLogic
685685
return TrinaryLogic::createMaybe();
686686
}
687687

688+
public function getIterableCount(): Type
689+
{
690+
$optionalKeysCount = count($this->optionalKeys);
691+
$totalKeysCount = count($this->getKeyTypes());
692+
if ($optionalKeysCount === 0) {
693+
return new ConstantIntegerType($totalKeysCount);
694+
}
695+
696+
return IntegerRangeType::fromInterval($totalKeysCount - $optionalKeysCount, $totalKeysCount);
697+
}
698+
688699
public function getFirstIterableKeyType(): Type
689700
{
690701
$keyTypes = [];
@@ -979,7 +990,7 @@ private function reindex(): self
979990

980991
public function toBoolean(): BooleanType
981992
{
982-
return $this->count()->toBoolean();
993+
return $this->getIterableCount()->toBoolean();
983994
}
984995

985996
public function toInteger(): Type
@@ -1116,15 +1127,10 @@ public function getValuesArray(): Type
11161127
return new self($keyTypes, $valueTypes, $autoIndex, $optionalKeys, true);
11171128
}
11181129

1130+
/** @deprecated Use getIterableCount() instead */
11191131
public function count(): Type
11201132
{
1121-
$optionalKeysCount = count($this->optionalKeys);
1122-
$totalKeysCount = count($this->getKeyTypes());
1123-
if ($optionalKeysCount === 0) {
1124-
return new ConstantIntegerType($totalKeysCount);
1125-
}
1126-
1127-
return IntegerRangeType::fromInterval($totalKeysCount - $optionalKeysCount, $totalKeysCount);
1133+
return $this->getIterableCount();
11281134
}
11291135

11301136
public function describe(VerbosityLevel $level): string

src/Type/IntersectionType.php

+5
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,11 @@ public function isIterableAtLeastOnce(): TrinaryLogic
406406
return $this->intersectResults(static fn (Type $type): TrinaryLogic => $type->isIterableAtLeastOnce());
407407
}
408408

409+
public function getIterableCount(): Type
410+
{
411+
return $this->intersectTypes(static fn (Type $type): Type => $type->getIterableCount());
412+
}
413+
409414
public function getIterableKeyType(): Type
410415
{
411416
return $this->intersectTypes(static fn (Type $type): Type => $type->getIterableKeyType());

src/Type/IterableType.php

+5
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,11 @@ public function isIterableAtLeastOnce(): TrinaryLogic
220220
return TrinaryLogic::createMaybe();
221221
}
222222

223+
public function getIterableCount(): Type
224+
{
225+
return IntegerRangeType::fromInterval(0, null);
226+
}
227+
223228
public function getIterableKeyType(): Type
224229
{
225230
return $this->keyType;

src/Type/MixedType.php

+9
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,15 @@ public function isIterableAtLeastOnce(): TrinaryLogic
366366
return $this->isIterable();
367367
}
368368

369+
public function getIterableCount(): Type
370+
{
371+
if ($this->isIterable()->no()) {
372+
return new ErrorType();
373+
}
374+
375+
return IntegerRangeType::fromInterval(0, null);
376+
}
377+
369378
public function getIterableKeyType(): Type
370379
{
371380
return new self($this->isExplicitMixed);

src/Type/Php/CountFunctionReturnTypeExtension.php

+4-21
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,9 @@
55
use PhpParser\Node\Expr\FuncCall;
66
use PHPStan\Analyser\Scope;
77
use PHPStan\Reflection\FunctionReflection;
8-
use PHPStan\Reflection\ParametersAcceptorSelector;
98
use PHPStan\Type\Constant\ConstantIntegerType;
109
use PHPStan\Type\DynamicFunctionReturnTypeExtension;
11-
use PHPStan\Type\IntegerRangeType;
1210
use PHPStan\Type\Type;
13-
use PHPStan\Type\TypeCombinator;
1411
use function count;
1512
use function in_array;
1613
use const COUNT_RECURSIVE;
@@ -27,34 +24,20 @@ public function getTypeFromFunctionCall(
2724
FunctionReflection $functionReflection,
2825
FuncCall $functionCall,
2926
Scope $scope,
30-
): Type
27+
): ?Type
3128
{
3229
if (count($functionCall->getArgs()) < 1) {
33-
return ParametersAcceptorSelector::selectSingle($functionReflection->getVariants())->getReturnType();
30+
return null;
3431
}
3532

3633
if (count($functionCall->getArgs()) > 1) {
3734
$mode = $scope->getType($functionCall->getArgs()[1]->value);
3835
if ($mode->isSuperTypeOf(new ConstantIntegerType(COUNT_RECURSIVE))->yes()) {
39-
return ParametersAcceptorSelector::selectSingle($functionReflection->getVariants())->getReturnType();
36+
return null;
4037
}
4138
}
4239

43-
$argType = $scope->getType($functionCall->getArgs()[0]->value);
44-
$constantArrays = $scope->getType($functionCall->getArgs()[0]->value)->getConstantArrays();
45-
if (count($constantArrays) === 0) {
46-
if ($argType->isIterableAtLeastOnce()->yes()) {
47-
return IntegerRangeType::fromInterval(1, null);
48-
}
49-
50-
return ParametersAcceptorSelector::selectSingle($functionReflection->getVariants())->getReturnType();
51-
}
52-
$countTypes = [];
53-
foreach ($constantArrays as $array) {
54-
$countTypes[] = $array->count();
55-
}
56-
57-
return TypeCombinator::union(...$countTypes);
40+
return $scope->getType($functionCall->getArgs()[0]->value)->getIterableCount();
5841
}
5942

6043
}

src/Type/Php/MinMaxFunctionReturnTypeExtension.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -178,9 +178,9 @@ private function compareTypes(
178178
$firstType instanceof ConstantArrayType
179179
&& $secondType instanceof ConstantArrayType
180180
) {
181-
if ($secondType->count() < $firstType->count()) {
181+
if ($secondType->getIterableCount() < $firstType->getIterableCount()) {
182182
return $secondType;
183-
} elseif ($firstType->count() < $secondType->count()) {
183+
} elseif ($firstType->getIterableCount() < $secondType->getIterableCount()) {
184184
return $firstType;
185185
}
186186

src/Type/StaticType.php

+5
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,11 @@ public function isIterableAtLeastOnce(): TrinaryLogic
297297
return $this->getStaticObjectType()->isIterableAtLeastOnce();
298298
}
299299

300+
public function getIterableCount(): Type
301+
{
302+
return $this->getStaticObjectType()->getIterableCount();
303+
}
304+
300305
public function getIterableKeyType(): Type
301306
{
302307
return $this->getStaticObjectType()->getIterableKeyType();

src/Type/Traits/LateResolvableTypeTrait.php

+5
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,11 @@ public function isIterableAtLeastOnce(): TrinaryLogic
125125
return $this->resolve()->isIterableAtLeastOnce();
126126
}
127127

128+
public function getIterableCount(): Type
129+
{
130+
return $this->resolve()->getIterableCount();
131+
}
132+
128133
public function getIterableKeyType(): Type
129134
{
130135
return $this->resolve()->getIterableKeyType();

src/Type/Traits/MaybeIterableTypeTrait.php

+15
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
namespace PHPStan\Type\Traits;
44

55
use PHPStan\TrinaryLogic;
6+
use PHPStan\Type\ErrorType;
7+
use PHPStan\Type\IntegerRangeType;
68
use PHPStan\Type\MixedType;
79
use PHPStan\Type\Type;
810

@@ -19,6 +21,19 @@ public function isIterableAtLeastOnce(): TrinaryLogic
1921
return TrinaryLogic::createMaybe();
2022
}
2123

24+
public function getIterableCount(): Type
25+
{
26+
if ($this->isIterable()->no()) {
27+
return new ErrorType();
28+
}
29+
30+
if ($this->isIterableAtLeastOnce()->yes()) {
31+
return IntegerRangeType::fromInterval(1, null);
32+
}
33+
34+
return IntegerRangeType::fromInterval(0, null);
35+
}
36+
2237
public function getIterableKeyType(): Type
2338
{
2439
return new MixedType();

src/Type/Traits/NonIterableTypeTrait.php

+5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ public function isIterableAtLeastOnce(): TrinaryLogic
1919
return TrinaryLogic::createNo();
2020
}
2121

22+
public function getIterableCount(): Type
23+
{
24+
return new ErrorType();
25+
}
26+
2227
public function getIterableKeyType(): Type
2328
{
2429
return new ErrorType();

src/Type/Type.php

+2
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ public function isIterable(): TrinaryLogic;
6464

6565
public function isIterableAtLeastOnce(): TrinaryLogic;
6666

67+
public function getIterableCount(): Type;
68+
6769
public function getIterableKeyType(): Type;
6870

6971
public function getFirstIterableKeyType(): Type;

src/Type/UnionType.php

+5
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,11 @@ public function isIterableAtLeastOnce(): TrinaryLogic
420420
return $this->unionResults(static fn (Type $type): TrinaryLogic => $type->isIterableAtLeastOnce());
421421
}
422422

423+
public function getIterableCount(): Type
424+
{
425+
return $this->unionTypes(static fn (Type $type): Type => $type->getIterableCount());
426+
}
427+
423428
public function getIterableKeyType(): Type
424429
{
425430
return $this->unionTypes(static fn (Type $type): Type => $type->getIterableKeyType());

0 commit comments

Comments
 (0)