@@ -21,6 +21,8 @@ class ClassConstantRuleTest extends RuleTestCase
2121
2222 private int $ phpVersion ;
2323
24+ private bool $ checkNonStringableDynamicAccess ;
25+
2426 protected function getRule (): Rule
2527 {
2628 $ reflectionProvider = self ::createReflectionProvider ();
@@ -34,12 +36,14 @@ protected function getRule(): Rule
3436 self ::getContainer (),
3537 ),
3638 new PhpVersion ($ this ->phpVersion ),
39+ $ this ->checkNonStringableDynamicAccess ,
3740 );
3841 }
3942
4043 public function testClassConstant (): void
4144 {
4245 $ this ->phpVersion = PHP_VERSION_ID ;
46+ $ this ->checkNonStringableDynamicAccess = true ;
4347 $ this ->analyse (
4448 [
4549 __DIR__ . '/data/class-constant.php ' ,
@@ -103,6 +107,7 @@ public function testClassConstant(): void
103107 public function testClassConstantVisibility (): void
104108 {
105109 $ this ->phpVersion = PHP_VERSION_ID ;
110+ $ this ->checkNonStringableDynamicAccess = true ;
106111 $ this ->analyse ([__DIR__ . '/data/class-constant-visibility.php ' ], [
107112 [
108113 'Access to private constant PRIVATE_BAR of class ClassConstantVisibility\Bar. ' ,
@@ -172,6 +177,7 @@ public function testClassConstantVisibility(): void
172177 public function testClassExists (): void
173178 {
174179 $ this ->phpVersion = PHP_VERSION_ID ;
180+ $ this ->checkNonStringableDynamicAccess = true ;
175181 $ this ->analyse ([__DIR__ . '/data/class-exists.php ' ], [
176182 [
177183 'Class UnknownClass\Bar not found. ' ,
@@ -246,12 +252,14 @@ public static function dataClassConstantOnExpression(): array
246252 public function testClassConstantOnExpression (int $ phpVersion , array $ errors ): void
247253 {
248254 $ this ->phpVersion = $ phpVersion ;
255+ $ this ->checkNonStringableDynamicAccess = true ;
249256 $ this ->analyse ([__DIR__ . '/data/class-constant-on-expr.php ' ], $ errors );
250257 }
251258
252259 public function testAttributes (): void
253260 {
254261 $ this ->phpVersion = PHP_VERSION_ID ;
262+ $ this ->checkNonStringableDynamicAccess = true ;
255263 $ this ->analyse ([__DIR__ . '/data/class-constant-attribute.php ' ], [
256264 [
257265 'Access to undefined constant ClassConstantAttribute\Foo::BAR. ' ,
@@ -288,18 +296,21 @@ public function testAttributes(): void
288296 public function testRuleWithNullsafeVariant (): void
289297 {
290298 $ this ->phpVersion = PHP_VERSION_ID ;
299+ $ this ->checkNonStringableDynamicAccess = true ;
291300 $ this ->analyse ([__DIR__ . '/data/class-constant-nullsafe.php ' ], []);
292301 }
293302
294303 public function testBug7675 (): void
295304 {
296305 $ this ->phpVersion = PHP_VERSION_ID ;
306+ $ this ->checkNonStringableDynamicAccess = true ;
297307 $ this ->analyse ([__DIR__ . '/data/bug-7675.php ' ], []);
298308 }
299309
300310 public function testBug8034 (): void
301311 {
302312 $ this ->phpVersion = PHP_VERSION_ID ;
313+ $ this ->checkNonStringableDynamicAccess = true ;
303314 $ this ->analyse ([__DIR__ . '/data/bug-8034.php ' ], [
304315 [
305316 'Access to undefined constant static(Bug8034\HelloWorld)::FIELDS. ' ,
@@ -311,6 +322,7 @@ public function testBug8034(): void
311322 public function testClassConstFetchDefined (): void
312323 {
313324 $ this ->phpVersion = PHP_VERSION_ID ;
325+ $ this ->checkNonStringableDynamicAccess = true ;
314326 $ this ->analyse ([__DIR__ . '/data/class-const-fetch-defined.php ' ], [
315327 [
316328 'Access to undefined constant ClassConstFetchDefined\Foo::TEST. ' ,
@@ -412,6 +424,7 @@ public function testPhpstanInternalClass(): void
412424 $ tip = 'This is most likely unintentional. Did you mean to type \AClass? ' ;
413425
414426 $ this ->phpVersion = PHP_VERSION_ID ;
427+ $ this ->checkNonStringableDynamicAccess = true ;
415428 $ this ->analyse ([__DIR__ . '/data/phpstan-internal-class.php ' ], [
416429 [
417430 'Referencing prefixed PHPStan class: _PHPStan_156ee64ba\AClass. ' ,
@@ -425,6 +438,7 @@ public function testPhpstanInternalClass(): void
425438 public function testClassConstantAccessedOnTrait (): void
426439 {
427440 $ this ->phpVersion = PHP_VERSION_ID ;
441+ $ this ->checkNonStringableDynamicAccess = true ;
428442 $ this ->analyse ([__DIR__ . '/data/class-constant-accessed-on-trait.php ' ], [
429443 [
430444 'Cannot access constant TEST on trait ClassConstantAccessedOnTrait\Foo. ' ,
@@ -437,8 +451,17 @@ public function testClassConstantAccessedOnTrait(): void
437451 public function testDynamicAccess (): void
438452 {
439453 $ this ->phpVersion = PHP_VERSION_ID ;
454+ $ this ->checkNonStringableDynamicAccess = true ;
440455
441456 $ this ->analyse ([__DIR__ . '/data/dynamic-constant-access.php ' ], [
457+ [
458+ 'Access to undefined constant ClassConstantDynamicAccess\Foo::FOO. ' ,
459+ 17 ,
460+ ],
461+ [
462+ 'Cannot fetch class constant with a non-stringable type object. ' ,
463+ 19 ,
464+ ],
442465 [
443466 'Access to undefined constant ClassConstantDynamicAccess\Foo::FOO. ' ,
444467 20 ,
@@ -474,4 +497,41 @@ public function testDynamicAccess(): void
474497 ]);
475498 }
476499
500+ public function testStringableDynamicAccess (): void
501+ {
502+ if (PHP_VERSION_ID < 80300 ) {
503+ $ this ->markTestSkipped ('Test requires PHP 8.3. ' );
504+ }
505+
506+ $ this ->phpVersion = PHP_VERSION_ID ;
507+ $ this ->checkNonStringableDynamicAccess = true ;
508+
509+ $ this ->analyse ([__DIR__ . '/data/dynamic-constant-stringable-access.php ' ], [
510+ [
511+ 'Cannot fetch class constant with a non-stringable type mixed. ' ,
512+ 13 ,
513+ ],
514+ [
515+ 'Cannot fetch class constant with a non-stringable type string|null. ' ,
516+ 14 ,
517+ ],
518+ [
519+ 'Cannot fetch class constant with a non-stringable type Stringable|null. ' ,
520+ 15 ,
521+ ],
522+ [
523+ 'Cannot fetch class constant with a non-stringable type int. ' ,
524+ 16 ,
525+ ],
526+ [
527+ 'Cannot fetch class constant with a non-stringable type int|null. ' ,
528+ 17 ,
529+ ],
530+ [
531+ 'Cannot fetch class constant with a non-stringable type DateTime|string. ' ,
532+ 18 ,
533+ ],
534+ ]);
535+ }
536+
477537}
0 commit comments