From 2ca129b0c114b397f2ea33dd26afed0a07f18406 Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Thu, 16 Apr 2026 14:54:38 +0800 Subject: [PATCH] =?UTF-8?q?fix(php):=20=E4=BF=AE=E5=A4=8Dtrait=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E8=AF=AD=E6=B3=95=E4=B8=AD=E6=9C=AA=E6=8C=87=E5=AE=9A?= =?UTF-8?q?trait=E5=90=8D=E7=A7=B0=E6=97=B6=E7=9A=84=E5=88=AB=E5=90=8D?= =?UTF-8?q?=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 当trait别名语法中未指定具体trait时,现在正确地为所有相关trait创建别名映射 - 添加对多重trait使用的支持,处理如 use TraitA, TraitB { method as newMethod } 的语法 - 修复预处理阶段无法获取trait方法列表时的映射逻辑 - 增加对trait优先级语法中缺少trait名称的错误检查 - 添加测试用例验证trait方法冲突处理的正确性 --- src/Php/Preprocessor.php | 40 ++++++++++++++++++++++++++-------------- tests/aot/trait/007.phpt | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 14 deletions(-) create mode 100644 tests/aot/trait/007.phpt diff --git a/src/Php/Preprocessor.php b/src/Php/Preprocessor.php index 6f2e3c4d..a5901523 100644 --- a/src/Php/Preprocessor.php +++ b/src/Php/Preprocessor.php @@ -613,23 +613,35 @@ class Preprocessor extends CompilerBase protected function parseTraitUseOptions(Node\Stmt\TraitUse $traitUse, array &$aliases, array &$ignored): void { foreach ($traitUse->adaptations as $adaptation) { - if (!$adaptation->trait) { - $this->fatalError($traitUse, 'Trait `use` cannot use `use` without `as`'); - } if ($adaptation instanceof Node\Stmt\TraitUseAdaptation\Alias) { - $trait1 = $this->getNamespacedClassName($adaptation->trait); - $methodName = $adaptation->method->toString(); - /* - * 例如: - * use TraitA { TraitA::method as newMethod} - * 这表示 TraitA::method() 会被重命名为 TraitA::newMethod() - */ - $aliases[$this->getFullMethodName($trait1, $methodName)] = [ - 'newName' => $adaptation->newName->toString(), - 'newModifier' => $adaptation->newModifier ?: 0, - ]; + $traits = []; + if (!$adaptation->trait) { + // use THello1, THello2 { + // hello as hello3; + // } + // 未指定 trait,将添加所有 trait 的别名映射,在预处理阶段无法获取 trait 的方法列表 + $traits = $traitUse->traits; + } else { + $traits[] = $adaptation->trait; + } + foreach ($traits as $trait) { + $traitName = $this->getNamespacedClassName($trait); + $methodName = $adaptation->method->toString(); + /* + * 例如: + * use TraitA { TraitA::method as newMethod} + * 这表示 TraitA::method() 会被重命名为 TraitA::newMethod() + */ + $aliases[$this->getFullMethodName($traitName, $methodName)] = [ + 'newName' => $adaptation->newName->toString(), + 'newModifier' => $adaptation->newModifier ?: 0, + ]; + } } if ($adaptation instanceof Node\Stmt\TraitUseAdaptation\Precedence) { + if (!$adaptation->trait) { + $this->fatalError($traitUse, 'Trait precedence cannot be used without a trait'); + } $methodName = $adaptation->method->toString(); /* * 例如: diff --git a/tests/aot/trait/007.phpt b/tests/aot/trait/007.phpt new file mode 100644 index 00000000..1fc1e375 --- /dev/null +++ b/tests/aot/trait/007.phpt @@ -0,0 +1,35 @@ +--TEST-- +Method conflict in traits +--FILE-- +hello3(); +} +?> +--EXPECT-- +Hello 1 \ No newline at end of file