From aea979fae1e436e97ca2fc00e0dad6ca2b888296 Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Wed, 15 Apr 2026 15:33:08 +0800 Subject: [PATCH] =?UTF-8?q?feat(php):=20=E6=94=AF=E6=8C=81trait=E6=96=B9?= =?UTF-8?q?=E6=B3=95=E5=88=AB=E5=90=8D=E5=92=8C=E8=AE=BF=E9=97=AE=E4=BF=AE?= =?UTF-8?q?=E9=A5=B0=E7=AC=A6=E8=BD=AC=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修改traitAliases数据结构以存储方法别名和新修饰符信息 - 实现trait方法别名时保留原始访问修饰符功能 - 添加对trait方法别名中newModifier属性的支持 - 更新翻译器中trait方法别名处理逻辑 - 扩展测试用例验证trait方法冲突解决机制 --- src/Php/Entity/ClassDef.php | 2 +- src/Php/Preprocessor.php | 8 ++++---- src/Php/Translator.php | 14 ++++++++++---- tests/aot/trait/005.phpt | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 50 insertions(+), 9 deletions(-) create mode 100644 tests/aot/trait/005.phpt diff --git a/src/Php/Entity/ClassDef.php b/src/Php/Entity/ClassDef.php index 409f16ca..dddab867 100644 --- a/src/Php/Entity/ClassDef.php +++ b/src/Php/Entity/ClassDef.php @@ -34,7 +34,7 @@ class ClassDef extends ClassLikeDef public ?Trait_ $trait = null; /** * FullMethodName -> NewMethodName - * @var array + * @var array */ public array $traitAliases = []; /** diff --git a/src/Php/Preprocessor.php b/src/Php/Preprocessor.php index 08b74ae2..27bc10dd 100644 --- a/src/Php/Preprocessor.php +++ b/src/Php/Preprocessor.php @@ -616,15 +616,15 @@ class Preprocessor extends CompilerBase if ($adaptation instanceof Node\Stmt\TraitUseAdaptation\Alias) { $trait1 = $this->getNamespacedClassName($adaptation->trait); $methodName = $adaptation->method->toString(); - if ($adaptation->newModifier) { - $this->fatalError($traitUse, "Trait `{$trait1}` cannot use `newModifier`"); - } /** * 例如: * use TraitA { TraitA::method as newMethod} * 这表示 TraitA::method() 会被重命名为 TraitA::newMethod() */ - $aliases[$this->getFullMethodName($trait1, $methodName)] = $adaptation->newName->toString(); + $aliases[$this->getFullMethodName($trait1, $methodName)] = array( + 'newName' => $adaptation->newName->toString(), + 'newModifier' => $adaptation->newModifier ?: $adaptation->newModifier->toString(), + ); } if ($adaptation instanceof Node\Stmt\TraitUseAdaptation\Precedence) { $methodName = $adaptation->method->toString(); diff --git a/src/Php/Translator.php b/src/Php/Translator.php index 4f58b29f..6f7bac93 100644 --- a/src/Php/Translator.php +++ b/src/Php/Translator.php @@ -972,8 +972,11 @@ class Translator extends Preprocessor $fullMethodName = $this->getFullMethodName($traitFullName, $methodName); if (isset($classDef->traitAliases[$fullMethodName])) { $alias = $classDef->traitAliases[$fullMethodName]; - $traitStmt->name = new Node\Identifier($alias); - $methodName = $alias; + $methodName = $alias['newName']; + $traitStmt->name = new Node\Identifier($methodName); + if ($alias['newModifier']) { + $traitStmt->flags = $alias['newModifier']; + } } if (isset($classDef->traitIgnored[$fullMethodName])) { unset($traitStmts[$k1]); @@ -1296,9 +1299,12 @@ class Translator extends Preprocessor $fullMethodName = $this->getFullMethodName($traitFullName, $traitMethodName); // Trait 设置了别名 if (isset($classDef->traitAliases[$fullMethodName])) { - $classMethodName = $classDef->traitAliases[$fullMethodName]; + $alias = $classDef->traitAliases[$fullMethodName]; $methodDef = clone $methodDef; - $methodDef->name = $classMethodName; + $classMethodName = $methodDef->name = $alias['newName']; + if ($alias['newModifier']) { + $methodDef->flags = $this->parseModifiers($alias['newModifier']); + } } // 设置了 insteadof 选项,此 Trait 的方法将不会被使用 if (isset($classDef->traitIgnored[$fullMethodName])) { diff --git a/tests/aot/trait/005.phpt b/tests/aot/trait/005.phpt new file mode 100644 index 00000000..7ac4844a --- /dev/null +++ b/tests/aot/trait/005.phpt @@ -0,0 +1,35 @@ +--TEST-- +Method conflict in traits +--FILE-- +hello2(); + $o->hello(); +} + +?> +--EXPECT-- +Hello 2 +Hello 1 \ No newline at end of file