@@ -45,6 +45,9 @@ final class ConstantResolver
4545 /** @var array<string, true> */
4646 private array $ currentlyResolving = [];
4747
48+ /** @var array<string, Type|null> */
49+ private array $ configuredTypesCache = [];
50+
4851 /**
4952 * @param string[] $dynamicConstantNames
5053 * @param int|array{min: int, max: int}|null $phpVersion
@@ -414,16 +417,52 @@ private function getMaxPhpVersion(): ?PhpVersion
414417 return $ this ->composerPhpVersionFactory ->getMaxVersion ();
415418 }
416419
420+ public function getConfiguredGlobalConstantType (string $ constantName ): ?Type
421+ {
422+ if (array_key_exists ($ constantName , $ this ->configuredTypesCache )) {
423+ return $ this ->configuredTypesCache [$ constantName ];
424+ }
425+
426+ $ result = null ;
427+ if (array_key_exists ($ constantName , $ this ->dynamicConstantNames )) {
428+ $ phpdocTypes = $ this ->dynamicConstantNames [$ constantName ];
429+ if ($ this ->container !== null ) {
430+ $ typeStringResolver = $ this ->container ->getByType (TypeStringResolver::class);
431+ $ result = $ typeStringResolver ->resolve ($ phpdocTypes , new NameScope (null , [], className: null ));
432+ }
433+ }
434+
435+ $ this ->configuredTypesCache [$ constantName ] = $ result ;
436+
437+ return $ result ;
438+ }
439+
440+ public function getConfiguredClassConstantType (string $ className , string $ constantName ): ?Type
441+ {
442+ $ lookupConstantName = sprintf ('%s::%s ' , $ className , $ constantName );
443+ if (array_key_exists ($ lookupConstantName , $ this ->configuredTypesCache )) {
444+ return $ this ->configuredTypesCache [$ lookupConstantName ];
445+ }
446+
447+ $ result = null ;
448+ if (array_key_exists ($ lookupConstantName , $ this ->dynamicConstantNames )) {
449+ $ phpdocTypes = $ this ->dynamicConstantNames [$ lookupConstantName ];
450+ if ($ this ->container !== null ) {
451+ $ typeStringResolver = $ this ->container ->getByType (TypeStringResolver::class);
452+ $ result = $ typeStringResolver ->resolve ($ phpdocTypes , new NameScope (null , [], $ className ));
453+ }
454+ }
455+
456+ $ this ->configuredTypesCache [$ lookupConstantName ] = $ result ;
457+
458+ return $ result ;
459+ }
460+
417461 public function resolveConstantType (string $ constantName , Type $ constantType ): Type
418462 {
419463 if ($ constantType ->isConstantValue ()->yes ()) {
420464 if (array_key_exists ($ constantName , $ this ->dynamicConstantNames )) {
421- $ phpdocTypes = $ this ->dynamicConstantNames [$ constantName ];
422- if ($ this ->container !== null ) {
423- $ typeStringResolver = $ this ->container ->getByType (TypeStringResolver::class);
424- return $ typeStringResolver ->resolve ($ phpdocTypes , new NameScope (null , [], className: null ));
425- }
426- return $ constantType ;
465+ return $ this ->getConfiguredGlobalConstantType ($ constantName ) ?? $ constantType ;
427466 }
428467 if (in_array ($ constantName , $ this ->dynamicConstantNames , true )) {
429468 return $ this ->generalizeDynamicConstantType ($ constantType );
@@ -438,10 +477,9 @@ public function resolveClassConstantType(string $className, string $constantName
438477 $ lookupConstantName = sprintf ('%s::%s ' , $ className , $ constantName );
439478 if (array_key_exists ($ lookupConstantName , $ this ->dynamicConstantNames )) {
440479 if ($ constantType ->isConstantValue ()->yes ()) {
441- $ phpdocTypes = $ this ->dynamicConstantNames [$ lookupConstantName ];
442- if ($ this ->container !== null ) {
443- $ typeStringResolver = $ this ->container ->getByType (TypeStringResolver::class);
444- return $ typeStringResolver ->resolve ($ phpdocTypes , new NameScope (null , [], $ className ));
480+ $ explicitType = $ this ->getConfiguredClassConstantType ($ className , $ constantName );
481+ if ($ explicitType !== null ) {
482+ return $ explicitType ;
445483 }
446484 }
447485
0 commit comments