Merge pull request 'fix(stub): 修复 self/parent/static 类常量引用解析失败的问题' (#37) from stub-fix-self-parent-static-class-const-ref into master

Reviewed-on: #37
pull/40/head
韩天峰 1 month ago
commit 6ec34ea459
  1. 51
      src/gen_stub.php
  2. 81
      tests/compiler/self-class/003.phpt

@ -50,6 +50,18 @@ function getClassConstFetchClassName(Expr\ClassConstFetch $expr): string
return $className;
}
function resolveClassConstFetchClassName(Expr\ClassConstFetch $expr, string $currentClass): string
{
$className = getClassConstFetchClassName($expr);
if (strcasecmp($className, 'self') === 0 || strcasecmp($className, 'static') === 0) {
return $currentClass;
}
if (strcasecmp($className, 'parent') === 0) {
return getTranslator()->getParentClass($currentClass);
}
return $className;
}
/**
* @return FileInfo[]
*/
@ -2325,7 +2337,11 @@ class EvaluatedValue
}
if ($expr instanceof Expr\ClassConstFetch) {
$originatingConstName = new ClassConstName($expr->class, $expr->name->toString());
$className = resolveClassConstFetchClassName($expr, ClassInfo::$currentClass);
$originatingConstName = new ClassConstName(
new Name(ltrim($className, '\\')),
$expr->name->toString()
);
} else {
$originatingConstName = new ConstName($expr->name->getAttribute('namespacedName'), $expr->name->toString());
}
@ -2361,30 +2377,19 @@ class EvaluatedValue
if (strcasecmp($constName, 'class') === 0) {
// `::class` is a compile-time magic constant that resolves to the
// fully qualified class name of the referenced class.
$className = getClassConstFetchClassName($expr);
if (strcasecmp($className, 'self') === 0 || strcasecmp($className, 'static') === 0) {
return ClassInfo::$currentClass;
}
if (strcasecmp($className, 'parent') === 0) {
return getTranslator()->getParentClass(ClassInfo::$currentClass);
}
return ltrim($className, '\\');
}
$class = getClassConstFetchClassName($expr);
if ($class === 'self') {
$constName = ClassInfo::$currentClass . "::" . $constName;
if (isset($allConstInfos[$constName])) {
return $allConstInfos[$constName]->getValue($allConstInfos)->value;
} else {
return normalizeConstExprValue(
getTranslator()->getClassConstValue($expr, ClassInfo::$currentClass, $constName)
);
}
} else {
return normalizeConstExprValue(
getTranslator()->getClassConstValue($expr, $class, $constName, ClassInfo::$currentClass)
return ltrim(
resolveClassConstFetchClassName($expr, ClassInfo::$currentClass),
'\\'
);
}
$class = resolveClassConstFetchClassName($expr, ClassInfo::$currentClass);
$fqcnName = ltrim($class, '\\') . "::" . $constName;
if (isset($allConstInfos[$fqcnName])) {
return $allConstInfos[$fqcnName]->getValue($allConstInfos)->value;
}
return normalizeConstExprValue(
getTranslator()->getClassConstValue($expr, $class, $constName, ClassInfo::$currentClass)
);
} else {
$constName = $expr->name->__toString();
if (strtolower($constName) === "unknown") {

@ -0,0 +1,81 @@
--TEST--
Class constants referenced through self, parent, explicit names and runtime static
--FILE--
<?php
declare(strict_types=1);
namespace StubConstRef {
class Base
{
const INHERITED = 1;
const OVERRIDDEN = 2;
}
class Child extends Base
{
const LOCAL = 10;
const OVERRIDDEN = 20;
const SELF_LOCAL = self::LOCAL;
const SELF_INHERITED = self::INHERITED;
const PARENT_VALUE = parent::OVERRIDDEN;
public int $selfLocal = self::LOCAL;
public int $selfInherited = self::INHERITED;
public int $parentValue = parent::OVERRIDDEN;
public int $explicitValue = \StubConstRef\Base::INHERITED;
public function defaults(
int $self = self::LOCAL,
int $parent = parent::OVERRIDDEN
): array {
return [$self, $parent];
}
public function runtimeStatic(): int
{
return static::OVERRIDDEN;
}
}
class GrandChild extends Child
{
const OVERRIDDEN = 30;
}
}
namespace {
function main()
{
$test = new StubConstRef\Child;
var_dump(
StubConstRef\Child::SELF_LOCAL,
StubConstRef\Child::SELF_INHERITED,
StubConstRef\Child::PARENT_VALUE
);
var_dump(
$test->selfLocal,
$test->selfInherited,
$test->parentValue,
$test->explicitValue
);
var_dump($test->defaults());
var_dump((new StubConstRef\GrandChild)->runtimeStatic());
}
}
?>
--EXPECT--
int(10)
int(1)
int(2)
int(10)
int(1)
int(2)
int(1)
array(2) {
[0]=>
int(10)
[1]=>
int(2)
}
int(30)
Loading…
Cancel
Save