1515use Go \ParserReflection \ReflectionClass ;
1616use Go \ParserReflection \ReflectionException ;
1717use Go \ParserReflection \ReflectionFileNamespace ;
18+ use Go \ParserReflection \ReflectionNamedType ;
1819use PhpParser \Node ;
1920use PhpParser \Node \Const_ ;
2021use PhpParser \Node \Expr ;
@@ -112,12 +113,17 @@ public function getConstExpression(): ?string
112113 // Clone node to avoid possible side-effects
113114 $ node = clone $ this ->nodeStack [$ this ->nodeLevel ];
114115 if ($ node instanceof Expr \ConstFetch) {
115- if ($ node ->name ->isFullyQualified ()) {
116+ $ constantNodeName = $ node ->name ;
117+ // Unpack fully-resolved name if we have it inside attribute
118+ if ($ constantNodeName ->hasAttribute ('resolvedName ' )) {
119+ $ constantNodeName = $ constantNodeName ->getAttribute ('resolvedName ' );
120+ }
121+ if ($ constantNodeName ->isFullyQualified ()) {
116122 // For full-qualified names we would like to remove leading "\"
117- $ node ->name = new Name (ltrim ($ node -> name ->toString (), '\\' ));
123+ $ node ->name = new Name (ltrim ($ constantNodeName ->toString (), '\\' ));
118124 } else {
119125 // For relative names we would like to add namespace prefix
120- $ node ->name = new Name ($ this ->resolveScalarMagicConstNamespace () . '\\' . $ node -> name ->toString ());
126+ $ node ->name = new Name ($ this ->resolveScalarMagicConstNamespace () . '\\' . $ constantNodeName ->toString ());
121127 }
122128 }
123129 // All long array nodes are pretty-printed by PHP in short format
@@ -185,6 +191,15 @@ protected function resolveNameFullyQualified(Name\FullyQualified $node): string
185191 return $ node ->toString ();
186192 }
187193
194+ private function resolveName (Name $ node ): string
195+ {
196+ if ($ node ->hasAttribute ('resolvedName ' )) {
197+ return $ node ->getAttribute ('resolvedName ' )->toString ();
198+ }
199+
200+ return $ node ->toString ();
201+ }
202+
188203 protected function resolveIdentifier (Node \Identifier $ node ): string
189204 {
190205 return $ node ->toString ();
@@ -332,8 +347,13 @@ protected function resolveExprConstFetch(Expr\ConstFetch $node)
332347 $ constantValue = null ;
333348 $ isResolved = false ;
334349
335- $ isFQNConstant = $ node ->name instanceof Node \Name \FullyQualified;
336- $ constantName = $ node ->name ->toString ();
350+ $ nodeConstantName = $ node ->name ;
351+ // If we have resolved type name
352+ if ($ nodeConstantName ->hasAttribute ('resolvedName ' )) {
353+ $ nodeConstantName = $ nodeConstantName ->getAttribute ('resolvedName ' );
354+ }
355+ $ isFQNConstant = $ nodeConstantName instanceof Node \Name \FullyQualified;
356+ $ constantName = $ nodeConstantName ->toString ();
337357
338358 if (!$ isFQNConstant && method_exists ($ this ->context , 'getFileName ' )) {
339359 $ fileName = $ this ->context ->getFileName ();
@@ -365,18 +385,29 @@ protected function resolveExprConstFetch(Expr\ConstFetch $node)
365385
366386 protected function resolveExprClassConstFetch (Expr \ClassConstFetch $ node )
367387 {
368- $ classToReflect = $ node ->class ;
369- if (!($ classToReflect instanceof Node \Name)) {
370- $ classToReflect = $ this ->resolve ($ classToReflect );
371- if (!is_string ($ classToReflect )) {
388+ $ classToReflectNodeName = $ node ->class ;
389+ if (!($ classToReflectNodeName instanceof Node \Name)) {
390+ $ classToReflectNodeName = $ this ->resolve ($ classToReflectNodeName );
391+ if (!is_string ($ classToReflectNodeName )) {
372392 throw new ReflectionException ("Unable to resolve class constant. " );
373393 }
374394 // Strings evaluated as class names are always treated as fully
375395 // qualified.
376- $ classToReflect = new Node \Name \FullyQualified (ltrim ($ classToReflect , '\\' ));
396+ $ classToReflectNodeName = new Node \Name \FullyQualified (ltrim ($ classToReflectNodeName , '\\' ));
397+ }
398+ // Unwrap resolved class name if we have it inside attributes
399+ if ($ classToReflectNodeName ->hasAttribute ('resolvedName ' )) {
400+ $ classToReflectNodeName = $ classToReflectNodeName ->getAttribute ('resolvedName ' );
401+ }
402+ $ refClass = $ this ->fetchReflectionClass ($ classToReflectNodeName );
403+ if (($ node ->name instanceof Expr \Error)) {
404+ $ constantName = '' ;
405+ } else {
406+ $ constantName = match (true ) {
407+ $ node ->name ->hasAttribute ('resolvedName ' ) => $ node ->name ->getAttribute ('resolvedName ' )->toString (),
408+ default => $ node ->name ->toString (),
409+ };
377410 }
378- $ refClass = $ this ->fetchReflectionClass ($ classToReflect );
379- $ constantName = ($ node ->name instanceof Expr \Error) ? '' : $ node ->name ->toString ();
380411
381412 // special handling of ::class constants
382413 if ('class ' === $ constantName ) {
@@ -385,7 +416,7 @@ protected function resolveExprClassConstFetch(Expr\ClassConstFetch $node)
385416
386417 $ this ->isConstant = true ;
387418 $ this ->isConstExpr = true ;
388- $ this ->constantName = $ classToReflect . ':: ' . $ constantName ;
419+ $ this ->constantName = $ classToReflectNodeName . ':: ' . $ constantName ;
389420
390421 return $ refClass ->getConstant ($ constantName );
391422 }
@@ -581,6 +612,10 @@ private function getDispatchMethodFor(Node $node): string
581612 */
582613 private function fetchReflectionClass (Node \Name $ node )
583614 {
615+ // If we have already resolved node name, we should use it instead
616+ if ($ node ->hasAttribute ('resolvedName ' )) {
617+ $ node = $ node ->getAttribute ('resolvedName ' );
618+ }
584619 $ className = $ node ->toString ();
585620 $ isFQNClass = $ node instanceof Node \Name \FullyQualified;
586621 if ($ isFQNClass ) {
0 commit comments