|
9 | 9 | use PHPStan\ShouldNotHappenException; |
10 | 10 | use PHPStan\TrinaryLogic; |
11 | 11 | use PHPStan\Type\Accessory\AccessoryArrayListType; |
| 12 | +use PHPStan\Type\Accessory\AccessoryLowercaseStringType; |
| 13 | +use PHPStan\Type\Accessory\AccessoryNonEmptyStringType; |
| 14 | +use PHPStan\Type\Accessory\AccessoryUppercaseStringType; |
12 | 15 | use PHPStan\Type\Accessory\NonEmptyArrayType; |
13 | 16 | use PHPStan\Type\ArrayType; |
14 | 17 | use PHPStan\Type\Constant\ConstantArrayType; |
@@ -80,32 +83,43 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection, |
80 | 83 | } |
81 | 84 | } |
82 | 85 |
|
83 | | - if (!isset($splitLength)) { |
84 | | - return null; |
85 | | - } |
86 | | - |
87 | 86 | $stringType = $scope->getType($functionCall->getArgs()[0]->value); |
88 | | - |
89 | | - $constantStrings = $stringType->getConstantStrings(); |
90 | | - if (count($constantStrings) > 0) { |
91 | | - $results = []; |
92 | | - foreach ($constantStrings as $constantString) { |
93 | | - $items = $encoding === null |
94 | | - ? str_split($constantString->getValue(), $splitLength) |
95 | | - : @mb_str_split($constantString->getValue(), $splitLength, $encoding); |
96 | | - if ($items === false) { |
97 | | - throw new ShouldNotHappenException(); |
| 87 | + if (isset($splitLength)) { |
| 88 | + $constantStrings = $stringType->getConstantStrings(); |
| 89 | + if (count($constantStrings) > 0) { |
| 90 | + $results = []; |
| 91 | + foreach ($constantStrings as $constantString) { |
| 92 | + $items = $encoding === null |
| 93 | + ? str_split($constantString->getValue(), $splitLength) |
| 94 | + : @mb_str_split($constantString->getValue(), $splitLength, $encoding); |
| 95 | + if ($items === false) { |
| 96 | + throw new ShouldNotHappenException(); |
| 97 | + } |
| 98 | + |
| 99 | + $results[] = self::createConstantArrayFrom($items, $scope); |
98 | 100 | } |
99 | 101 |
|
100 | | - $results[] = self::createConstantArrayFrom($items, $scope); |
| 102 | + return TypeCombinator::union(...$results); |
101 | 103 | } |
| 104 | + } |
| 105 | + |
| 106 | + $isInputNonEmptyString = $stringType->isNonEmptyString()->yes(); |
102 | 107 |
|
103 | | - return TypeCombinator::union(...$results); |
| 108 | + $valueTypes = [new StringType()]; |
| 109 | + if ($isInputNonEmptyString || $this->phpVersion->strSplitReturnsEmptyArray()) { |
| 110 | + $valueTypes[] = new AccessoryNonEmptyStringType(); |
| 111 | + } |
| 112 | + if ($stringType->isLowercaseString()->yes()) { |
| 113 | + $valueTypes[] = new AccessoryLowercaseStringType(); |
| 114 | + } |
| 115 | + if ($stringType->isUppercaseString()->yes()) { |
| 116 | + $valueTypes[] = new AccessoryUppercaseStringType(); |
104 | 117 | } |
| 118 | + $returnValueType = TypeCombinator::intersect(new StringType(), ...$valueTypes); |
105 | 119 |
|
106 | | - $returnType = AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), new StringType())); |
| 120 | + $returnType = AccessoryArrayListType::intersectWith(TypeCombinator::intersect(new ArrayType(new IntegerType(), $returnValueType))); |
107 | 121 |
|
108 | | - return $encoding === null && !$this->phpVersion->strSplitReturnsEmptyArray() |
| 122 | + return $isInputNonEmptyString || ($encoding === null && !$this->phpVersion->strSplitReturnsEmptyArray()) |
109 | 123 | ? TypeCombinator::intersect($returnType, new NonEmptyArrayType()) |
110 | 124 | : $returnType; |
111 | 125 | } |
|
0 commit comments