19
19
use PHPStan \Type \Constant \ConstantBooleanType ;
20
20
use PHPStan \Type \Constant \ConstantIntegerType ;
21
21
use PHPStan \Type \Constant \ConstantStringType ;
22
- use PHPStan \Type \IntegerType ;
22
+ use PHPStan \Type \IntegerRangeType ;
23
23
use PHPStan \Type \NullType ;
24
24
use PHPStan \Type \StringType ;
25
25
use PHPStan \Type \Type ;
@@ -67,31 +67,41 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
67
67
$ this ->cacheReturnTypes ();
68
68
69
69
$ componentType = new ConstantIntegerType (-1 );
70
+
70
71
if (count ($ functionCall ->getArgs ()) > 1 ) {
71
72
$ componentType = $ scope ->getType ($ functionCall ->getArgs ()[1 ]->value );
72
73
74
+ if (! $ componentType ->isConstantValue ()->yes ()) {
75
+ return $ this ->createAllComponentsReturnType ();
76
+ }
77
+
78
+ $ componentType = $ componentType ->toInteger ();
79
+
73
80
if (! $ componentType instanceof ConstantIntegerType) {
74
81
return $ this ->createAllComponentsReturnType ();
75
82
}
76
83
}
77
84
78
85
$ urlType = $ scope ->getType ($ functionCall ->getArgs ()[0 ]->value );
79
- if (count ($ urlType ->getConstantStrings ()) !== 0 ) {
80
- $ returnTypes = [];
86
+ if (count ($ urlType ->getConstantStrings ()) > 0 ) {
87
+ $ types = [];
81
88
foreach ($ urlType ->getConstantStrings () as $ constantString ) {
82
89
try {
83
90
// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
84
91
$ result = @parse_url ($ constantString ->getValue (), $ componentType ->getValue ());
85
- $ returnTypes [] = $ scope ->getTypeFromValue ($ result );
86
92
} catch (\ValueError $ e ) {
87
- $ returnTypes [] = new ConstantBooleanType (false );
93
+ $ types [] = new ConstantBooleanType (false );
94
+ continue ;
88
95
}
96
+
97
+ $ types [] = $ scope ->getTypeFromValue ($ result );
89
98
}
90
- return TypeCombinator::union (...$ returnTypes );
99
+
100
+ return TypeCombinator::union (...$ types );
91
101
}
92
102
93
103
if ($ componentType ->getValue () === -1 ) {
94
- return $ this ->createAllComponentsReturnType ( );
104
+ return TypeCombinator:: union ( $ this ->createComponentsArray (), new ConstantBooleanType ( false ) );
95
105
}
96
106
97
107
return $ this ->componentTypesPairedConstants [$ componentType ->getValue ()] ?? new ConstantBooleanType (false );
@@ -102,24 +112,31 @@ private function createAllComponentsReturnType(): Type
102
112
if ($ this ->allComponentsTogetherType === null ) {
103
113
$ returnTypes = [
104
114
new ConstantBooleanType (false ),
115
+ new NullType (),
116
+ IntegerRangeType::fromInterval (0 , 65535 ),
117
+ new StringType (),
118
+ $ this ->createComponentsArray (),
105
119
];
106
120
107
- $ builder = ConstantArrayTypeBuilder::createEmpty ();
121
+ $ this ->allComponentsTogetherType = TypeCombinator::union (...$ returnTypes );
122
+ }
108
123
109
- if ($ this ->componentTypesPairedStrings === null ) {
110
- throw new \PHPStan \ShouldNotHappenException ();
111
- }
124
+ return $ this ->allComponentsTogetherType ;
125
+ }
112
126
113
- foreach ( $ this -> componentTypesPairedStrings as $ componentName => $ componentValueType ) {
114
- $ builder -> setOffsetValueType ( new ConstantStringType ( $ componentName ), $ componentValueType , true );
115
- }
127
+ private function createComponentsArray (): Type
128
+ {
129
+ $ builder = ConstantArrayTypeBuilder:: createEmpty ();
116
130
117
- $ returnTypes [] = $ builder ->getArray ();
131
+ if ($ this ->componentTypesPairedStrings === null ) {
132
+ throw new \PHPStan \ShouldNotHappenException ();
133
+ }
118
134
119
- $ this ->allComponentsTogetherType = TypeCombinator::union (...$ returnTypes );
135
+ foreach ($ this ->componentTypesPairedStrings as $ componentName => $ componentValueType ) {
136
+ $ builder ->setOffsetValueType (new ConstantStringType ($ componentName ), $ componentValueType , true );
120
137
}
121
138
122
- return $ this -> allComponentsTogetherType ;
139
+ return $ builder -> getArray () ;
123
140
}
124
141
125
142
private function cacheReturnTypes (): void
@@ -129,17 +146,17 @@ private function cacheReturnTypes(): void
129
146
}
130
147
131
148
$ stringType = new StringType ();
132
- $ integerType = new IntegerType ( );
149
+ $ port = IntegerRangeType:: fromInterval ( 0 , 65535 );
133
150
$ falseType = new ConstantBooleanType (false );
134
151
$ nullType = new NullType ();
135
152
136
153
$ stringOrFalseOrNull = TypeCombinator::union ($ stringType , $ falseType , $ nullType );
137
- $ integerOrFalseOrNull = TypeCombinator::union ($ integerType , $ falseType , $ nullType );
154
+ $ portOrFalseOrNull = TypeCombinator::union ($ port , $ falseType , $ nullType );
138
155
139
156
$ this ->componentTypesPairedConstants = [
140
157
PHP_URL_SCHEME => $ stringOrFalseOrNull ,
141
158
PHP_URL_HOST => $ stringOrFalseOrNull ,
142
- PHP_URL_PORT => $ integerOrFalseOrNull ,
159
+ PHP_URL_PORT => $ portOrFalseOrNull ,
143
160
PHP_URL_USER => $ stringOrFalseOrNull ,
144
161
PHP_URL_PASS => $ stringOrFalseOrNull ,
145
162
PHP_URL_PATH => $ stringOrFalseOrNull ,
@@ -150,7 +167,7 @@ private function cacheReturnTypes(): void
150
167
$ this ->componentTypesPairedStrings = [
151
168
'scheme ' => $ stringType ,
152
169
'host ' => $ stringType ,
153
- 'port ' => $ integerType ,
170
+ 'port ' => $ port ,
154
171
'user ' => $ stringType ,
155
172
'pass ' => $ stringType ,
156
173
'path ' => $ stringType ,
0 commit comments