fix(php): 修复trait使用语法中未指定trait名称时的别名处理

- 当trait别名语法中未指定具体trait时,现在正确地为所有相关trait创建别名映射
- 添加对多重trait使用的支持,处理如 use TraitA, TraitB { method as newMethod } 的语法
- 修复预处理阶段无法获取trait方法列表时的映射逻辑
- 增加对trait优先级语法中缺少trait名称的错误检查
- 添加测试用例验证trait方法冲突处理的正确性
pull/1/head
韩天峰 5 months ago
parent 583536a24e
commit 2ca129b0c1
  1. 40
      src/Php/Preprocessor.php
  2. 35
      tests/aot/trait/007.phpt

@ -613,23 +613,35 @@ class Preprocessor extends CompilerBase
protected function parseTraitUseOptions(Node\Stmt\TraitUse $traitUse, array &$aliases, array &$ignored): void protected function parseTraitUseOptions(Node\Stmt\TraitUse $traitUse, array &$aliases, array &$ignored): void
{ {
foreach ($traitUse->adaptations as $adaptation) { 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) { if ($adaptation instanceof Node\Stmt\TraitUseAdaptation\Alias) {
$trait1 = $this->getNamespacedClassName($adaptation->trait); $traits = [];
$methodName = $adaptation->method->toString(); if (!$adaptation->trait) {
/* // use THello1, THello2 {
* 例如: // hello as hello3;
* use TraitA { TraitA::method as newMethod} // }
* 这表示 TraitA::method() 会被重命名为 TraitA::newMethod() // 未指定 trait,将添加所有 trait 的别名映射,在预处理阶段无法获取 trait 的方法列表
*/ $traits = $traitUse->traits;
$aliases[$this->getFullMethodName($trait1, $methodName)] = [ } else {
'newName' => $adaptation->newName->toString(), $traits[] = $adaptation->trait;
'newModifier' => $adaptation->newModifier ?: 0, }
]; 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 instanceof Node\Stmt\TraitUseAdaptation\Precedence) {
if (!$adaptation->trait) {
$this->fatalError($traitUse, 'Trait precedence cannot be used without a trait');
}
$methodName = $adaptation->method->toString(); $methodName = $adaptation->method->toString();
/* /*
* 例如: * 例如:

@ -0,0 +1,35 @@
--TEST--
Method conflict in traits
--FILE--
<?php
trait THello1
{
public function hello()
{
echo 'Hello 1', PHP_EOL;
}
}
trait THello2
{
public function hello2()
{
echo 'Hello 2', PHP_EOL;
}
}
class TraitsTest
{
use THello1, THello2 {
hello as hello3;
}
}
function main()
{
$o = new TraitsTest;
$o->hello3();
}
?>
--EXPECT--
Hello 1
Loading…
Cancel
Save