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

- 当trait别名语法中未指定具体trait时,现在正确地为所有相关trait创建别名映射
- 添加对多重trait使用的支持,处理如 use TraitA, TraitB { method as newMethod } 的语法
- 修复预处理阶段无法获取trait方法列表时的映射逻辑
- 增加对trait优先级语法中缺少trait名称的错误检查
- 添加测试用例验证trait方法冲突处理的正确性
pull/1/head
韩天峰 4 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
{
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();
/*
* 例如:

@ -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