15
15
use Go \ParserReflection \ReflectionClass ;
16
16
use Go \ParserReflection \ReflectionException ;
17
17
use Go \ParserReflection \ReflectionFileNamespace ;
18
+ use Go \ParserReflection \ReflectionNamedType ;
18
19
use PhpParser \Node ;
19
20
use PhpParser \Node \Const_ ;
20
21
use PhpParser \Node \Expr ;
@@ -112,12 +113,17 @@ public function getConstExpression(): ?string
112
113
// Clone node to avoid possible side-effects
113
114
$ node = clone $ this ->nodeStack [$ this ->nodeLevel ];
114
115
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 ()) {
116
122
// 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 (), '\\' ));
118
124
} else {
119
125
// 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 ());
121
127
}
122
128
}
123
129
// All long array nodes are pretty-printed by PHP in short format
@@ -185,6 +191,15 @@ protected function resolveNameFullyQualified(Name\FullyQualified $node): string
185
191
return $ node ->toString ();
186
192
}
187
193
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
+
188
203
protected function resolveIdentifier (Node \Identifier $ node ): string
189
204
{
190
205
return $ node ->toString ();
@@ -332,8 +347,13 @@ protected function resolveExprConstFetch(Expr\ConstFetch $node)
332
347
$ constantValue = null ;
333
348
$ isResolved = false ;
334
349
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 ();
337
357
338
358
if (!$ isFQNConstant && method_exists ($ this ->context , 'getFileName ' )) {
339
359
$ fileName = $ this ->context ->getFileName ();
@@ -365,18 +385,29 @@ protected function resolveExprConstFetch(Expr\ConstFetch $node)
365
385
366
386
protected function resolveExprClassConstFetch (Expr \ClassConstFetch $ node )
367
387
{
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 )) {
372
392
throw new ReflectionException ("Unable to resolve class constant. " );
373
393
}
374
394
// Strings evaluated as class names are always treated as fully
375
395
// 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
+ };
377
410
}
378
- $ refClass = $ this ->fetchReflectionClass ($ classToReflect );
379
- $ constantName = ($ node ->name instanceof Expr \Error) ? '' : $ node ->name ->toString ();
380
411
381
412
// special handling of ::class constants
382
413
if ('class ' === $ constantName ) {
@@ -385,7 +416,7 @@ protected function resolveExprClassConstFetch(Expr\ClassConstFetch $node)
385
416
386
417
$ this ->isConstant = true ;
387
418
$ this ->isConstExpr = true ;
388
- $ this ->constantName = $ classToReflect . ':: ' . $ constantName ;
419
+ $ this ->constantName = $ classToReflectNodeName . ':: ' . $ constantName ;
389
420
390
421
return $ refClass ->getConstant ($ constantName );
391
422
}
@@ -581,6 +612,10 @@ private function getDispatchMethodFor(Node $node): string
581
612
*/
582
613
private function fetchReflectionClass (Node \Name $ node )
583
614
{
615
+ // If we have already resolved node name, we should use it instead
616
+ if ($ node ->hasAttribute ('resolvedName ' )) {
617
+ $ node = $ node ->getAttribute ('resolvedName ' );
618
+ }
584
619
$ className = $ node ->toString ();
585
620
$ isFQNClass = $ node instanceof Node \Name \FullyQualified;
586
621
if ($ isFQNClass ) {
0 commit comments