77use PHPStan \Reflection \FunctionReflection ;
88use PHPStan \ShouldNotHappenException ;
99use PHPStan \Type \Accessory \AccessoryLowercaseStringType ;
10- use PHPStan \Type \Accessory \AccessoryUppercaseStringType ;
1110use PHPStan \Type \Constant \ConstantArrayTypeBuilder ;
1211use PHPStan \Type \Constant \ConstantBooleanType ;
1312use PHPStan \Type \Constant \ConstantIntegerType ;
@@ -40,23 +39,15 @@ final class ParseUrlFunctionDynamicReturnTypeExtension implements DynamicFunctio
4039 /** @var array<string,Type>|null */
4140 private ?array $ componentTypesPairedStrings = null ;
4241
43- private ?Type $ allComponentsTogetherType = null ;
44-
4542 /** @var array<int,Type>|null */
4643 private ?array $ componentTypesPairedConstantsForLowercaseString = null ;
4744
4845 /** @var array<string,Type>|null */
4946 private ?array $ componentTypesPairedStringsForLowercaseString = null ;
5047
51- private ?Type $ allComponentsTogetherTypeForLowercaseString = null ;
52-
53- /** @var array<int,Type>|null */
54- private ?array $ componentTypesPairedConstantsForUppercaseString = null ;
55-
56- /** @var array<string,Type>|null */
57- private ?array $ componentTypesPairedStringsForUppercaseString = null ;
48+ private ?Type $ allComponentsTogetherType = null ;
5849
59- private ?Type $ allComponentsTogetherTypeForUppercaseString = null ;
50+ private ?Type $ allComponentsTogetherTypeForLowercaseString = null ;
6051
6152 public function isFunctionSupported (FunctionReflection $ functionReflection ): bool
6253 {
@@ -76,18 +67,12 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
7667 $ componentType = $ scope ->getType ($ functionCall ->getArgs ()[1 ]->value );
7768
7869 if (!$ componentType ->isConstantValue ()->yes ()) {
79- return $ this ->createAllComponentsReturnType (
80- $ urlType ->isLowercaseString ()->yes (),
81- $ urlType ->isUppercaseString ()->yes (),
82- );
70+ return $ this ->createAllComponentsReturnType ($ urlType ->isLowercaseString ()->yes ());
8371 }
8472
8573 $ componentType = $ componentType ->toInteger ();
8674 if (!$ componentType instanceof ConstantIntegerType) {
87- return $ this ->createAllComponentsReturnType (
88- $ urlType ->isLowercaseString ()->yes (),
89- $ urlType ->isUppercaseString ()->yes (),
90- );
75+ return $ this ->createAllComponentsReturnType ($ urlType ->isLowercaseString ()->yes ());
9176 }
9277 } else {
9378 $ componentType = new ConstantIntegerType (-1 );
@@ -111,10 +96,7 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
11196
11297 if ($ componentType ->getValue () === -1 ) {
11398 return TypeCombinator::union (
114- $ this ->createComponentsArray (
115- $ urlType ->isLowercaseString ()->yes (),
116- $ urlType ->isUppercaseString ()->yes (),
117- ),
99+ $ this ->createComponentsArray ($ urlType ->isLowercaseString ()->yes ()),
118100 new ConstantBooleanType (false ),
119101 );
120102 }
@@ -123,43 +105,19 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
123105 return $ this ->componentTypesPairedConstantsForLowercaseString [$ componentType ->getValue ()] ?? new ConstantBooleanType (false );
124106 }
125107
126- if ($ urlType ->isUppercaseString ()->yes ()) {
127- return $ this ->componentTypesPairedConstantsForUppercaseString [$ componentType ->getValue ()] ?? new ConstantBooleanType (false );
128- }
129-
130108 return $ this ->componentTypesPairedConstants [$ componentType ->getValue ()] ?? new ConstantBooleanType (false );
131109 }
132110
133- private function createAllComponentsReturnType (bool $ urlIsLowercase, bool $ urlIsUppercase ): Type
111+ private function createAllComponentsReturnType (bool $ urlIsLowercase ): Type
134112 {
135- if ($ urlIsLowercase && $ urlIsUppercase ) {
136- if (
137- $ this ->allComponentsTogetherTypeForLowercaseString === null
138- && $ this ->allComponentsTogetherTypeForUppercaseString === null
139- ) {
140- $ returnTypes = [
141- new ConstantBooleanType (false ),
142- new NullType (),
143- IntegerRangeType::fromInterval (0 , 65535 ),
144- new IntersectionType ([new StringType (), new AccessoryLowercaseStringType (), new AccessoryUppercaseStringType ()]),
145- $ this ->createComponentsArray (true , true ),
146- ];
147-
148- $ union = TypeCombinator::union (...$ returnTypes );
149- $ this ->allComponentsTogetherTypeForLowercaseString = $ union ;
150- $ this ->allComponentsTogetherTypeForUppercaseString = $ union ;
151- return $ union ;
152- }
153- }
154-
155113 if ($ urlIsLowercase ) {
156114 if ($ this ->allComponentsTogetherTypeForLowercaseString === null ) {
157115 $ returnTypes = [
158116 new ConstantBooleanType (false ),
159117 new NullType (),
160118 IntegerRangeType::fromInterval (0 , 65535 ),
161119 new IntersectionType ([new StringType (), new AccessoryLowercaseStringType ()]),
162- $ this ->createComponentsArray (true , false ),
120+ $ this ->createComponentsArray (true ),
163121 ];
164122
165123 $ this ->allComponentsTogetherTypeForLowercaseString = TypeCombinator::union (...$ returnTypes );
@@ -168,29 +126,13 @@ private function createAllComponentsReturnType(bool $urlIsLowercase, bool $urlIs
168126 return $ this ->allComponentsTogetherTypeForLowercaseString ;
169127 }
170128
171- if ($ urlIsUppercase ) {
172- if ($ this ->allComponentsTogetherTypeForUppercaseString === null ) {
173- $ returnTypes = [
174- new ConstantBooleanType (false ),
175- new NullType (),
176- IntegerRangeType::fromInterval (0 , 65535 ),
177- new IntersectionType ([new StringType (), new AccessoryUppercaseStringType ()]),
178- $ this ->createComponentsArray (false , true ),
179- ];
180-
181- $ this ->allComponentsTogetherTypeForUppercaseString = TypeCombinator::union (...$ returnTypes );
182- }
183-
184- return $ this ->allComponentsTogetherTypeForUppercaseString ;
185- }
186-
187129 if ($ this ->allComponentsTogetherType === null ) {
188130 $ returnTypes = [
189131 new ConstantBooleanType (false ),
190132 new NullType (),
191133 IntegerRangeType::fromInterval (0 , 65535 ),
192134 new StringType (),
193- $ this ->createComponentsArray (false , false ),
135+ $ this ->createComponentsArray (false ),
194136 ];
195137
196138 $ this ->allComponentsTogetherType = TypeCombinator::union (...$ returnTypes );
@@ -199,7 +141,7 @@ private function createAllComponentsReturnType(bool $urlIsLowercase, bool $urlIs
199141 return $ this ->allComponentsTogetherType ;
200142 }
201143
202- private function createComponentsArray (bool $ urlIsLowercase, bool $ urlIsUppercase ): Type
144+ private function createComponentsArray (bool $ urlIsLowercase ): Type
203145 {
204146 $ builder = ConstantArrayTypeBuilder::createEmpty ();
205147
@@ -211,19 +153,7 @@ private function createComponentsArray(bool $urlIsLowercase, bool $urlIsUppercas
211153 foreach ($ this ->componentTypesPairedStringsForLowercaseString as $ componentName => $ componentValueType ) {
212154 $ builder ->setOffsetValueType (new ConstantStringType ($ componentName ), $ componentValueType , true );
213155 }
214- }
215-
216- if ($ urlIsUppercase ) {
217- if ($ this ->componentTypesPairedStringsForUppercaseString === null ) {
218- throw new ShouldNotHappenException ();
219- }
220-
221- foreach ($ this ->componentTypesPairedStringsForUppercaseString as $ componentName => $ componentValueType ) {
222- $ builder ->setOffsetValueType (new ConstantStringType ($ componentName ), $ componentValueType , true );
223- }
224- }
225-
226- if (! $ urlIsLowercase && ! $ urlIsUppercase ) {
156+ } else {
227157 if ($ this ->componentTypesPairedStrings === null ) {
228158 throw new ShouldNotHappenException ();
229159 }
@@ -243,10 +173,13 @@ private function cacheReturnTypes(): void
243173 }
244174
245175 $ string = new StringType ();
176+ $ lowercaseString = new IntersectionType ([new StringType (), new AccessoryLowercaseStringType ()]);
246177 $ port = IntegerRangeType::fromInterval (0 , 65535 );
247178 $ false = new ConstantBooleanType (false );
248179 $ null = new NullType ();
180+
249181 $ stringOrFalseOrNull = TypeCombinator::union ($ string , $ false , $ null );
182+ $ lowercaseStringOrFalseOrNull = TypeCombinator::union ($ lowercaseString , $ false , $ null );
250183 $ portOrFalseOrNull = TypeCombinator::union ($ port , $ false , $ null );
251184
252185 $ this ->componentTypesPairedConstants = [
@@ -259,6 +192,16 @@ private function cacheReturnTypes(): void
259192 PHP_URL_QUERY => $ stringOrFalseOrNull ,
260193 PHP_URL_FRAGMENT => $ stringOrFalseOrNull ,
261194 ];
195+ $ this ->componentTypesPairedConstantsForLowercaseString = [
196+ PHP_URL_SCHEME => $ lowercaseStringOrFalseOrNull ,
197+ PHP_URL_HOST => $ lowercaseStringOrFalseOrNull ,
198+ PHP_URL_PORT => $ portOrFalseOrNull ,
199+ PHP_URL_USER => $ lowercaseStringOrFalseOrNull ,
200+ PHP_URL_PASS => $ lowercaseStringOrFalseOrNull ,
201+ PHP_URL_PATH => $ lowercaseStringOrFalseOrNull ,
202+ PHP_URL_QUERY => $ lowercaseStringOrFalseOrNull ,
203+ PHP_URL_FRAGMENT => $ lowercaseStringOrFalseOrNull ,
204+ ];
262205
263206 $ this ->componentTypesPairedStrings = [
264207 'scheme ' => $ string ,
@@ -270,20 +213,6 @@ private function cacheReturnTypes(): void
270213 'query ' => $ string ,
271214 'fragment ' => $ string ,
272215 ];
273-
274- $ lowercaseString = new IntersectionType ([new StringType (), new AccessoryLowercaseStringType ()]);
275- $ lowercaseStringOrFalseOrNull = TypeCombinator::union ($ lowercaseString , $ false , $ null );
276-
277- $ this ->componentTypesPairedConstantsForLowercaseString = [
278- PHP_URL_SCHEME => $ lowercaseStringOrFalseOrNull ,
279- PHP_URL_HOST => $ lowercaseStringOrFalseOrNull ,
280- PHP_URL_PORT => $ portOrFalseOrNull ,
281- PHP_URL_USER => $ lowercaseStringOrFalseOrNull ,
282- PHP_URL_PASS => $ lowercaseStringOrFalseOrNull ,
283- PHP_URL_PATH => $ lowercaseStringOrFalseOrNull ,
284- PHP_URL_QUERY => $ lowercaseStringOrFalseOrNull ,
285- PHP_URL_FRAGMENT => $ lowercaseStringOrFalseOrNull ,
286- ];
287216 $ this ->componentTypesPairedStringsForLowercaseString = [
288217 'scheme ' => $ lowercaseString ,
289218 'host ' => $ lowercaseString ,
@@ -294,30 +223,6 @@ private function cacheReturnTypes(): void
294223 'query ' => $ lowercaseString ,
295224 'fragment ' => $ lowercaseString ,
296225 ];
297-
298- $ uppercaseString = new IntersectionType ([new StringType (), new AccessoryUppercaseStringType ()]);
299- $ uppercaseStringOrFalseOrNull = TypeCombinator::union ($ uppercaseString , $ false , $ null );
300-
301- $ this ->componentTypesPairedConstantsForUppercaseString = [
302- PHP_URL_SCHEME => $ uppercaseStringOrFalseOrNull ,
303- PHP_URL_HOST => $ uppercaseStringOrFalseOrNull ,
304- PHP_URL_PORT => $ portOrFalseOrNull ,
305- PHP_URL_USER => $ uppercaseStringOrFalseOrNull ,
306- PHP_URL_PASS => $ uppercaseStringOrFalseOrNull ,
307- PHP_URL_PATH => $ uppercaseStringOrFalseOrNull ,
308- PHP_URL_QUERY => $ uppercaseStringOrFalseOrNull ,
309- PHP_URL_FRAGMENT => $ uppercaseStringOrFalseOrNull ,
310- ];
311- $ this ->componentTypesPairedStringsForUppercaseString = [
312- 'scheme ' => $ uppercaseString ,
313- 'host ' => $ uppercaseString ,
314- 'port ' => $ port ,
315- 'user ' => $ uppercaseString ,
316- 'pass ' => $ uppercaseString ,
317- 'path ' => $ uppercaseString ,
318- 'query ' => $ uppercaseString ,
319- 'fragment ' => $ uppercaseString ,
320- ];
321226 }
322227
323228}
0 commit comments