From 7eed77138ad83449908e5908942edf96004105fd Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Wed, 25 Mar 2026 19:49:51 +0800 Subject: [PATCH] =?UTF-8?q?feat(php):=20=E6=B7=BB=E5=8A=A0=E5=AF=B9=20thro?= =?UTF-8?q?w=20=E8=AF=AD=E5=8F=A5=E7=9A=84=E6=94=AF=E6=8C=81=E5=B9=B6?= =?UTF-8?q?=E6=94=B9=E8=BF=9B=20switch=20case=20=E9=AA=8C=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 AstNodeType 中添加 isThrowExpr 方法用于检测 throw 表达式 - 修改 CompilerBase 中的 switch case 验证逻辑,支持以 throw 结尾的 case - 更新 parseThrow 方法以正确处理不同类型的异常对象 - 将最低 PHP 版本兼容性要求从 8.0 更新到 8.4 --- bin/gen_stub.php | 2 +- src/Php/AstNodeType.php | 8 ++++++++ src/Php/CompilerBase.php | 15 ++++++++++----- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/bin/gen_stub.php b/bin/gen_stub.php index 9826d10c..0364cde8 100755 --- a/bin/gen_stub.php +++ b/bin/gen_stub.php @@ -4252,7 +4252,7 @@ class FileInfo { public bool $generateClassEntries = true; private bool $isUndocumentable = false; private bool $legacyArginfoGeneration = false; - private ?int $minimumPhpVersionIdCompatibility = PHP_80_VERSION_ID; + private ?int $minimumPhpVersionIdCompatibility = PHP_84_VERSION_ID; /** @param array $fileTags */ public function __construct(array $fileTags) { diff --git a/src/Php/AstNodeType.php b/src/Php/AstNodeType.php index e5e7baad..825c6b19 100644 --- a/src/Php/AstNodeType.php +++ b/src/Php/AstNodeType.php @@ -122,6 +122,14 @@ trait AstNodeType return $expr instanceof Node\Stmt\Break_; } + protected function isThrowExpr(NodeAbstract $expr): bool + { + if ($expr instanceof Node\Stmt\Expression) { + $expr = $expr->expr; + } + return $expr instanceof Expr\Throw_; + } + protected function isExitExpr(NodeAbstract $expr): bool { if ($expr instanceof Node\Stmt\Expression) { diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index 352b1634..d1a1bed4 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -3351,8 +3351,12 @@ class CompilerBase extends \PhpAot\Core\Translator $stmts = $stmts[0]->stmts; } $lastExpr = end($stmts); - if (!$this->isReturnExpr($lastExpr) and !$this->isExitExpr($lastExpr) and !$this->isBreakExpr($lastExpr)) { - $this->fatalError($case, 'switch case must end with return or break or exit, ' . $lastExpr->getType() . ' given'); + if (!$this->isReturnExpr($lastExpr) + and !$this->isExitExpr($lastExpr) + and !$this->isBreakExpr($lastExpr) + and !$this->isThrowExpr($lastExpr) + ) { + $this->fatalError($case, 'switch case must end with return/break/exit/throw, ' . $lastExpr->getType() . ' given'); } if ($condList) { @@ -3959,10 +3963,11 @@ class CompilerBase extends \PhpAot\Core\Translator protected function parseThrow(mixed $expr): string { if (!$this->isVarExpr($expr->expr) and $expr->expr->getType() != self::EXPR_NEW) { - $this->fatalError($expr, 'The throw statement only accepts a object variable'); + $ex = $this->convertToObject($expr->expr); + } else { + $ex = $this->parseIdentifier($expr->expr); } - - return 'php::throwException(' . $this->parseIdentifier($expr->expr) . ')'; + return 'php::throwException(' . $ex . ')'; } protected function parseTryCatch(mixed $v): string