feat(stubgen): 支持类常量表达式求值和类上下文跟踪

- 扩展常量表达式求值器以支持 ClassConstFetch 节点
- 实现对 self::CONST 和 CLASS::class 语法的解析和求值
- 添加当前类上下文跟踪机制以处理自引用常量
- 更新字符串和数值类型的表达式打印逻辑
- 增强错误处理以提供更详细的类型信息
pull/1/head
韩天峰 6 months ago
parent 78f3ca8025
commit 0e0f232571
  1. 36
      bin/gen_stub.php

@ -2296,15 +2296,31 @@ class EvaluatedValue
$evaluator = new ConstExprEvaluator(
static function (Expr $expr) use ($allConstInfos, &$isUnknownConstValue) {
// $expr is a ConstFetch with a name of a C macro here
if (!$expr instanceof Expr\ConstFetch) {
throw new Exception("Expression at line " . $expr->getStartLine() . " must be a global, non-magic constant");
if (!($expr instanceof Expr\ConstFetch) and !($expr instanceof Expr\ClassConstFetch)) {
_error:
throw new Exception("Expression at line " . $expr->getStartLine() . " must be a global, non-magic constant, " . $expr->getType() . " given");
}
if ($expr instanceof Expr\ClassConstFetch) {
$class = $expr->class->toString();
if ($class === 'self') {
$constName = ClassInfo::$currentClass->name->toString() . "::" . $expr->name->__toString();
if (isset($allConstInfos[$constName])) {
return $allConstInfos[$constName]->getValue($allConstInfos)->value;
} else {
throw new Exception("Class constant `$constName` not found");
}
} elseif ($expr->name->__toString() === 'class') {
return $class;
}
goto _error;
} else {
$constName = $expr->name->__toString();
if (strtolower($constName) === "unknown") {
$isUnknownConstValue = true;
return null;
}
}
foreach ($allConstInfos as $const) {
if ($constName != $const->cValue) {
@ -2423,10 +2439,22 @@ class EvaluatedValue
$expr = $prettyPrinter->prettyPrintExpr($this->expr);
// PHP single-quote to C double-quote string
if ($this->type->isString()) {
if (!($this->expr instanceof String_)) {
if (
$this->expr instanceof PhpParser\Node\Expr\ClassConstFetch
) {
if ($this->expr->class instanceof PhpParser\Node\Name\FullyQualified and
$this->expr->name instanceof PhpParser\Node\Identifier and
$this->expr->name->__toString() === 'class') {
$expr = '"' . addcslashes($this->expr->class->name, '\\') . '"';
} else {
var_dump($this->value);
}
} elseif (!($this->expr instanceof String_)) {
throw new Exception("Expression at line " . $this->expr->getStartLine() . " must be a scalar string");
}
$expr = preg_replace("/(^'|'$)/", '"', $expr);
} elseif ($this->type->isInt() or $this->type->isFloat()) {
return strval($this->value);
} else {
if ($this->expr instanceof Expr\ConstFetch) {
$value = constant($this->expr->name->__toString());
@ -3425,6 +3453,7 @@ class AttributeInfo {
}
class ClassInfo {
static public ?self $currentClass = null;
public /* readonly */ Name $name;
private int $flags;
public string $type;
@ -3501,6 +3530,7 @@ class ClassInfo {
$this->cond = $cond;
$this->phpVersionIdMinimumCompatibility = $minimumPhpVersionIdCompatibility;
$this->isUndocumentable = $isUndocumentable;
self::$currentClass = $this;
}
/** @param array<string, ConstInfo> $allConstInfos */

Loading…
Cancel
Save