refactor(Php): 优化方法重写检测逻辑以支持子类预处理顺序

- 提取 fullMethodName 的小写转换为独立变量
- 添加对子类是否已覆盖方法的检查机制
- 实现递归检查所有子类及其后代子类的同名方法定义
- 更新父类方法重写标记逻辑以支持动态调用处理
- 添加完整的文档注释说明新的方法重写检测功能
pull/1/head
韩天峰 3 months ago
parent a30205b058
commit f803a0fd41
  1. 33
      src/Php/Preprocessor.php

@ -605,14 +605,17 @@ class Preprocessor extends CompilerBase
$fullClassName = $this->getFullClassName();
$fullMethodName = $fullClassName . '::' . $this->method;
$this->classMethodOverride[strtolower($fullMethodName)] = false;
// 查找父类是否有同名方法,递归查找
$fullMethodNameLower = strtolower($fullMethodName);
$fullClassNameLower = strtolower($fullClassName);
// 检查子类是否已覆盖此方法(子类先于父类被预处理的情况)
$isOverridden = $this->isMethodOverriddenInSubClasses($fullClassNameLower, $this->method);
$this->classMethodOverride[$fullMethodNameLower] = $isOverridden;
// 查找父类是否有同名方法,递归向上标记父类方法已被覆盖
while (isset($this->classExtends[$fullClassNameLower])) {
$parentClass = $this->classExtends[$fullClassNameLower];
$parentMethodLower = strtolower($parentClass . '::' . $this->method);
// 父类有同名方法,子类覆盖了父类方法,这种情况不能直接使用 C++ 函数,而是使用 ZendVM 动态调用
if (isset($this->classMethodOverride[$parentMethodLower])) {
$this->classMethodOverride[$parentMethodLower] = true;
}
@ -622,6 +625,30 @@ class Preprocessor extends CompilerBase
$this->resetMethod();
}
/**
* 递归检查所有子类(及子类的子类)是否已定义了同名方法,用于处理子类先于父类被预处理的情况。
*/
private function isMethodOverriddenInSubClasses(string $classNameLower, string $method): bool
{
if (!isset($this->classSubClasses[$classNameLower])) {
return false;
}
$stack = $this->classSubClasses[$classNameLower];
while (!empty($stack)) {
$subClass = array_shift($stack);
$subMethodLower = $subClass . '::' . strtolower($method);
if (isset($this->classMethodOverride[$subMethodLower])) {
return true;
}
if (isset($this->classSubClasses[$subClass])) {
foreach ($this->classSubClasses[$subClass] as $grandChild) {
$stack[] = $grandChild;
}
}
}
return false;
}
protected function parseInterface(Node\Stmt\Interface_ $v): void
{
$name = $this->parseIdentifier($v->name);

Loading…
Cancel
Save