33namespace PHPStan \Analyser ;
44
55use PhpParser \Node \Name ;
6+ use PHPStan \Php \ComposerPhpVersionFactory ;
67use PHPStan \Php \PhpVersion ;
78use PHPStan \Reflection \NamespaceAnswerer ;
89use PHPStan \Reflection \ReflectionProvider ;
910use PHPStan \Reflection \ReflectionProvider \ReflectionProviderProvider ;
11+ use PHPStan \ShouldNotHappenException ;
1012use PHPStan \Type \Accessory \AccessoryNonFalsyStringType ;
1113use PHPStan \Type \Constant \ConstantFloatType ;
1214use PHPStan \Type \Constant \ConstantIntegerType ;
2123use PHPStan \Type \UnionType ;
2224use function array_key_exists ;
2325use function in_array ;
26+ use function is_array ;
27+ use function is_int ;
2428use function max ;
2529use function sprintf ;
2630use const INF ;
@@ -35,12 +39,13 @@ final class ConstantResolver
3539
3640 /**
3741 * @param string[] $dynamicConstantNames
42+ * @param int|array{min: int, max: int}|null $phpVersion
3843 */
3944 public function __construct (
4045 private ReflectionProviderProvider $ reflectionProviderProvider ,
4146 private array $ dynamicConstantNames ,
42- private ? PhpVersion $ composerMinPhpVersion ,
43- private ?PhpVersion $ composerMaxPhpVersion ,
47+ private int | array | null $ phpVersion ,
48+ private ?ComposerPhpVersionFactory $ composerPhpVersionFactory ,
4449 )
4550 {
4651 }
@@ -87,11 +92,11 @@ public function resolvePredefinedConstant(string $resolvedConstantName): ?Type
8792 $ minMajor = 5 ;
8893 $ maxMajor = null ;
8994
90- if ($ this ->composerMinPhpVersion !== null ) {
91- $ minMajor = max ($ minMajor , $ this ->composerMinPhpVersion ->getMajorVersionId ());
95+ if ($ this ->getMinPhpVersion () !== null ) {
96+ $ minMajor = max ($ minMajor , $ this ->getMinPhpVersion () ->getMajorVersionId ());
9297 }
93- if ($ this ->composerMaxPhpVersion !== null ) {
94- $ maxMajor = $ this ->composerMaxPhpVersion ->getMajorVersionId ();
98+ if ($ this ->getMaxPhpVersion () !== null ) {
99+ $ maxMajor = $ this ->getMaxPhpVersion () ->getMajorVersionId ();
95100 }
96101
97102 return $ this ->createInteger ($ minMajor , $ maxMajor );
@@ -101,12 +106,12 @@ public function resolvePredefinedConstant(string $resolvedConstantName): ?Type
101106 $ maxMinor = null ;
102107
103108 if (
104- $ this ->composerMinPhpVersion !== null
105- && $ this ->composerMaxPhpVersion !== null
106- && $ this ->composerMaxPhpVersion ->getMajorVersionId () === $ this ->composerMinPhpVersion ->getMajorVersionId ()
109+ $ this ->getMinPhpVersion () !== null
110+ && $ this ->getMaxPhpVersion () !== null
111+ && $ this ->getMaxPhpVersion () ->getMajorVersionId () === $ this ->getMinPhpVersion () ->getMajorVersionId ()
107112 ) {
108- $ minMinor = $ this ->composerMinPhpVersion ->getMinorVersionId ();
109- $ maxMinor = $ this ->composerMaxPhpVersion ->getMinorVersionId ();
113+ $ minMinor = $ this ->getMinPhpVersion () ->getMinorVersionId ();
114+ $ maxMinor = $ this ->getMaxPhpVersion () ->getMinorVersionId ();
110115 }
111116
112117 return $ this ->createInteger ($ minMinor , $ maxMinor );
@@ -116,25 +121,25 @@ public function resolvePredefinedConstant(string $resolvedConstantName): ?Type
116121 $ maxRelease = null ;
117122
118123 if (
119- $ this ->composerMinPhpVersion !== null
120- && $ this ->composerMaxPhpVersion !== null
121- && $ this ->composerMaxPhpVersion ->getMajorVersionId () === $ this ->composerMinPhpVersion ->getMajorVersionId ()
122- && $ this ->composerMaxPhpVersion ->getMinorVersionId () === $ this ->composerMinPhpVersion ->getMinorVersionId ()
124+ $ this ->getMinPhpVersion () !== null
125+ && $ this ->getMaxPhpVersion () !== null
126+ && $ this ->getMaxPhpVersion () ->getMajorVersionId () === $ this ->getMinPhpVersion () ->getMajorVersionId ()
127+ && $ this ->getMaxPhpVersion () ->getMinorVersionId () === $ this ->getMinPhpVersion () ->getMinorVersionId ()
123128 ) {
124- $ minRelease = $ this ->composerMinPhpVersion ->getPatchVersionId ();
125- $ maxRelease = $ this ->composerMaxPhpVersion ->getPatchVersionId ();
129+ $ minRelease = $ this ->getMinPhpVersion () ->getPatchVersionId ();
130+ $ maxRelease = $ this ->getMaxPhpVersion () ->getPatchVersionId ();
126131 }
127132
128133 return $ this ->createInteger ($ minRelease , $ maxRelease );
129134 }
130135 if ($ resolvedConstantName === 'PHP_VERSION_ID ' ) {
131136 $ minVersion = 50207 ;
132137 $ maxVersion = null ;
133- if ($ this ->composerMinPhpVersion !== null ) {
134- $ minVersion = max ($ minVersion , $ this ->composerMinPhpVersion ->getVersionId ());
138+ if ($ this ->getMinPhpVersion () !== null ) {
139+ $ minVersion = max ($ minVersion , $ this ->getMinPhpVersion () ->getVersionId ());
135140 }
136- if ($ this ->composerMaxPhpVersion !== null ) {
137- $ maxVersion = $ this ->composerMaxPhpVersion ->getVersionId ();
141+ if ($ this ->getMaxPhpVersion () !== null ) {
142+ $ maxVersion = $ this ->getMaxPhpVersion () ->getVersionId ();
138143 }
139144
140145 return $ this ->createInteger ($ minVersion , $ maxVersion );
@@ -351,6 +356,48 @@ public function resolvePredefinedConstant(string $resolvedConstantName): ?Type
351356 return null ;
352357 }
353358
359+ private function getMinPhpVersion (): ?PhpVersion
360+ {
361+ if (is_int ($ this ->phpVersion )) {
362+ return null ;
363+ }
364+
365+ if (is_array ($ this ->phpVersion )) {
366+ if ($ this ->phpVersion ['max ' ] < $ this ->phpVersion ['min ' ]) {
367+ throw new ShouldNotHappenException ('Invalid PHP version range: phpVersion.max should be greater or equal to phpVersion.min. ' );
368+ }
369+
370+ return new PhpVersion ($ this ->phpVersion ['min ' ]);
371+ }
372+
373+ if ($ this ->composerPhpVersionFactory === null ) {
374+ return null ;
375+ }
376+
377+ return $ this ->composerPhpVersionFactory ->getMinVersion ();
378+ }
379+
380+ private function getMaxPhpVersion (): ?PhpVersion
381+ {
382+ if (is_int ($ this ->phpVersion )) {
383+ return null ;
384+ }
385+
386+ if (is_array ($ this ->phpVersion )) {
387+ if ($ this ->phpVersion ['max ' ] < $ this ->phpVersion ['min ' ]) {
388+ throw new ShouldNotHappenException ('Invalid PHP version range: phpVersion.max should be greater or equal to phpVersion.min. ' );
389+ }
390+
391+ return new PhpVersion ($ this ->phpVersion ['max ' ]);
392+ }
393+
394+ if ($ this ->composerPhpVersionFactory === null ) {
395+ return null ;
396+ }
397+
398+ return $ this ->composerPhpVersionFactory ->getMaxVersion ();
399+ }
400+
354401 public function resolveConstantType (string $ constantName , Type $ constantType ): Type
355402 {
356403 if ($ constantType ->isConstantValue ()->yes () && in_array ($ constantName , $ this ->dynamicConstantNames , true )) {
0 commit comments