3
3
namespace PHPStan \Analyser ;
4
4
5
5
use PhpParser \Node \Name ;
6
+ use PHPStan \Php \ComposerPhpVersionFactory ;
6
7
use PHPStan \Php \PhpVersion ;
7
8
use PHPStan \Reflection \NamespaceAnswerer ;
8
9
use PHPStan \Reflection \ReflectionProvider ;
9
10
use PHPStan \Reflection \ReflectionProvider \ReflectionProviderProvider ;
11
+ use PHPStan \ShouldNotHappenException ;
10
12
use PHPStan \Type \Accessory \AccessoryNonFalsyStringType ;
11
13
use PHPStan \Type \Constant \ConstantFloatType ;
12
14
use PHPStan \Type \Constant \ConstantIntegerType ;
21
23
use PHPStan \Type \UnionType ;
22
24
use function array_key_exists ;
23
25
use function in_array ;
26
+ use function is_array ;
27
+ use function is_int ;
24
28
use function max ;
25
29
use function sprintf ;
26
30
use const INF ;
@@ -35,12 +39,13 @@ final class ConstantResolver
35
39
36
40
/**
37
41
* @param string[] $dynamicConstantNames
42
+ * @param int|array{min: int, max: int}|null $phpVersion
38
43
*/
39
44
public function __construct (
40
45
private ReflectionProviderProvider $ reflectionProviderProvider ,
41
46
private array $ dynamicConstantNames ,
42
- private ? PhpVersion $ composerMinPhpVersion ,
43
- private ? PhpVersion $ composerMaxPhpVersion ,
47
+ private int | array | null $ phpVersion ,
48
+ private ComposerPhpVersionFactory $ composerPhpVersionFactory ,
44
49
)
45
50
{
46
51
}
@@ -83,15 +88,23 @@ public function resolvePredefinedConstant(string $resolvedConstantName): ?Type
83
88
new AccessoryNonFalsyStringType (),
84
89
]);
85
90
}
91
+
92
+ $ minPhpVersion = null ;
93
+ $ maxPhpVersion = null ;
94
+ if (in_array ($ resolvedConstantName , ['PHP_VERSION_ID ' , 'PHP_MAJOR_VERSION ' , 'PHP_MINOR_VERSION ' , 'PHP_RELEASE_VERSION ' ], true )) {
95
+ $ minPhpVersion = $ this ->getMinPhpVersion ();
96
+ $ maxPhpVersion = $ this ->getMaxPhpVersion ();
97
+ }
98
+
86
99
if ($ resolvedConstantName === 'PHP_MAJOR_VERSION ' ) {
87
100
$ minMajor = 5 ;
88
101
$ maxMajor = null ;
89
102
90
- if ($ this -> composerMinPhpVersion !== null ) {
91
- $ minMajor = max ($ minMajor , $ this -> composerMinPhpVersion ->getMajorVersionId ());
103
+ if ($ minPhpVersion !== null ) {
104
+ $ minMajor = max ($ minMajor , $ minPhpVersion ->getMajorVersionId ());
92
105
}
93
- if ($ this -> composerMaxPhpVersion !== null ) {
94
- $ maxMajor = $ this -> composerMaxPhpVersion ->getMajorVersionId ();
106
+ if ($ maxPhpVersion !== null ) {
107
+ $ maxMajor = $ maxPhpVersion ->getMajorVersionId ();
95
108
}
96
109
97
110
return $ this ->createInteger ($ minMajor , $ maxMajor );
@@ -101,12 +114,12 @@ public function resolvePredefinedConstant(string $resolvedConstantName): ?Type
101
114
$ maxMinor = null ;
102
115
103
116
if (
104
- $ this -> composerMinPhpVersion !== null
105
- && $ this -> composerMaxPhpVersion !== null
106
- && $ this -> composerMaxPhpVersion -> getMajorVersionId () === $ this -> composerMinPhpVersion ->getMajorVersionId ()
117
+ $ minPhpVersion !== null
118
+ && $ maxPhpVersion !== null
119
+ && $ maxPhpVersion -> getMajorVersionId () === $ minPhpVersion ->getMajorVersionId ()
107
120
) {
108
- $ minMinor = $ this -> composerMinPhpVersion ->getMinorVersionId ();
109
- $ maxMinor = $ this -> composerMaxPhpVersion ->getMinorVersionId ();
121
+ $ minMinor = $ minPhpVersion ->getMinorVersionId ();
122
+ $ maxMinor = $ maxPhpVersion ->getMinorVersionId ();
110
123
}
111
124
112
125
return $ this ->createInteger ($ minMinor , $ maxMinor );
@@ -116,25 +129,25 @@ public function resolvePredefinedConstant(string $resolvedConstantName): ?Type
116
129
$ maxRelease = null ;
117
130
118
131
if (
119
- $ this -> composerMinPhpVersion !== null
120
- && $ this -> composerMaxPhpVersion !== null
121
- && $ this -> composerMaxPhpVersion -> getMajorVersionId () === $ this -> composerMinPhpVersion ->getMajorVersionId ()
122
- && $ this -> composerMaxPhpVersion -> getMinorVersionId () === $ this -> composerMinPhpVersion ->getMinorVersionId ()
132
+ $ minPhpVersion !== null
133
+ && $ maxPhpVersion !== null
134
+ && $ maxPhpVersion -> getMajorVersionId () === $ minPhpVersion ->getMajorVersionId ()
135
+ && $ maxPhpVersion -> getMinorVersionId () === $ minPhpVersion ->getMinorVersionId ()
123
136
) {
124
- $ minRelease = $ this -> composerMinPhpVersion ->getPatchVersionId ();
125
- $ maxRelease = $ this -> composerMaxPhpVersion ->getPatchVersionId ();
137
+ $ minRelease = $ minPhpVersion ->getPatchVersionId ();
138
+ $ maxRelease = $ maxPhpVersion ->getPatchVersionId ();
126
139
}
127
140
128
141
return $ this ->createInteger ($ minRelease , $ maxRelease );
129
142
}
130
143
if ($ resolvedConstantName === 'PHP_VERSION_ID ' ) {
131
144
$ minVersion = 50207 ;
132
145
$ maxVersion = null ;
133
- if ($ this -> composerMinPhpVersion !== null ) {
134
- $ minVersion = max ($ minVersion , $ this -> composerMinPhpVersion ->getVersionId ());
146
+ if ($ minPhpVersion !== null ) {
147
+ $ minVersion = max ($ minVersion , $ minPhpVersion ->getVersionId ());
135
148
}
136
- if ($ this -> composerMaxPhpVersion !== null ) {
137
- $ maxVersion = $ this -> composerMaxPhpVersion ->getVersionId ();
149
+ if ($ maxPhpVersion !== null ) {
150
+ $ maxVersion = $ maxPhpVersion ->getVersionId ();
138
151
}
139
152
140
153
return $ this ->createInteger ($ minVersion , $ maxVersion );
@@ -351,6 +364,40 @@ public function resolvePredefinedConstant(string $resolvedConstantName): ?Type
351
364
return null ;
352
365
}
353
366
367
+ private function getMinPhpVersion (): ?PhpVersion
368
+ {
369
+ if (is_int ($ this ->phpVersion )) {
370
+ return null ;
371
+ }
372
+
373
+ if (is_array ($ this ->phpVersion )) {
374
+ if ($ this ->phpVersion ['max ' ] < $ this ->phpVersion ['min ' ]) {
375
+ throw new ShouldNotHappenException ('Invalid PHP version range: phpVersion.max should be greater or equal to phpVersion.min. ' );
376
+ }
377
+
378
+ return new PhpVersion ($ this ->phpVersion ['min ' ]);
379
+ }
380
+
381
+ return $ this ->composerPhpVersionFactory ->getMinVersion ();
382
+ }
383
+
384
+ private function getMaxPhpVersion (): ?PhpVersion
385
+ {
386
+ if (is_int ($ this ->phpVersion )) {
387
+ return null ;
388
+ }
389
+
390
+ if (is_array ($ this ->phpVersion )) {
391
+ if ($ this ->phpVersion ['max ' ] < $ this ->phpVersion ['min ' ]) {
392
+ throw new ShouldNotHappenException ('Invalid PHP version range: phpVersion.max should be greater or equal to phpVersion.min. ' );
393
+ }
394
+
395
+ return new PhpVersion ($ this ->phpVersion ['max ' ]);
396
+ }
397
+
398
+ return $ this ->composerPhpVersionFactory ->getMaxVersion ();
399
+ }
400
+
354
401
public function resolveConstantType (string $ constantName , Type $ constantType ): Type
355
402
{
356
403
if ($ constantType ->isConstantValue ()->yes () && in_array ($ constantName , $ this ->dynamicConstantNames , true )) {
0 commit comments