diff --git a/src/Psalm/Internal/PhpVisitor/Reflector/ExpressionResolver.php b/src/Psalm/Internal/PhpVisitor/Reflector/ExpressionResolver.php index 20c75007515..840675acf01 100644 --- a/src/Psalm/Internal/PhpVisitor/Reflector/ExpressionResolver.php +++ b/src/Psalm/Internal/PhpVisitor/Reflector/ExpressionResolver.php @@ -305,12 +305,25 @@ public static function getUnresolvedClassConstExpr( && $stmt->var->class instanceof PhpParser\Node\Name && $stmt->var->name instanceof PhpParser\Node\Identifier && $stmt->name instanceof PhpParser\Node\Identifier - && in_array($stmt->name->name, ['name', 'value', true]) + && in_array($stmt->name->name, ['name', 'value'], true) + && ($stmt->var->class->parts !== ['self'] || $fq_classlike_name !== null) + && $stmt->var->class->parts !== ['static'] + && ($stmt->var->class->parts !== ['parent'] || $parent_fq_class_name !== null) ) { - $enum_fq_class_name = ClassLikeAnalyzer::getFQCLNFromNameObject( - $stmt->var->class, - $aliases, - ); + + if ($stmt->var->class->parts === ['self']) { + $enum_fq_class_name = $fq_classlike_name; + } else { + if ($stmt->var->class->parts === ['parent']) { + assert($parent_fq_class_name !== null); + $enum_fq_class_name = $parent_fq_class_name; + } else { + $enum_fq_class_name = ClassLikeAnalyzer::getFQCLNFromNameObject( + $stmt->var->class, + $aliases, + ); + } + } if ($stmt->name->name === 'value') { return new EnumValueFetch($enum_fq_class_name, $stmt->var->name->name); } elseif ($stmt->name->name === 'name') { diff --git a/tests/ConstantTest.php b/tests/ConstantTest.php index 5e3dc9e7b35..2133cd2f45b 100644 --- a/tests/ConstantTest.php +++ b/tests/ConstantTest.php @@ -1655,6 +1655,22 @@ enum BES: string { 'ignored_issues' => [], 'php_version' => '8.2', ], + 'constantEnumSelfReference' => [ + 'code' => 'value . self::B->value; + } + + class Foo { + public const CONCAT_STR = "a" . Bar::STR . "e"; + } + ', + 'assertions' => [], + 'ignored_issues' => [], + 'php_version' => '8.2', + ], 'classConstWithParamOut' => [ 'code' => '