refactor(php): 重构方法重写检查逻辑

- 将 checkParentMethodCanBeOverridden 方法从 Preprocessor 类移动到 Translator 类
- 移除 Preprocessor 类中的方法重写检查实现
- 在 Translator 类中添加完整的父类方法重写检查功能
- 实现私有方法不能被重写的验证逻辑
- 添加对内置类私有方法的重写检查支持
- 保持原有的方法重写标记逻辑在 Translator 中继续工作
pull/1/head
韩天峰 3 months ago
parent b33cdeb086
commit a30205b058
  1. 48
      src/Php/Preprocessor.php
  2. 47
      src/Php/Translator.php

@ -504,37 +504,6 @@ class Preprocessor extends CompilerBase
return $this->parseIdentifier($v->name);
}
/**
* 检查父类方法是否可以被重写,私有方法不能被重写
*/
protected function checkParentMethodCanBeOverridden(Node\Stmt\ClassMethod $v, string $name): void
{
$classDef = $this->classDef;
while (true) {
$extends = $classDef->extends;
if (!$extends) {
break;
}
// 父类是内置类
if ($classDef->inheritedFromInternalClass) {
if (Reflection::getClassMethodModifiers($extends, $name) & \ReflectionMethod::IS_PRIVATE) {
goto _error;
}
break;
}
$classDef = $this->getClass($extends);
if ($classDef->hasMethod($this->method)) {
$methodDef = $classDef->getMethod($this->method);
if ($methodDef->flags & Modifiers::PRIVATE) {
_error:
$this->fatalError($v,
'Cannot override private method `' .
$classDef->getNamespacedName(false) . '::' . $this->method . '()`');
}
}
}
}
protected function parseClassConstDef(Node\Stmt\ClassConst $v): void
{
$this->resetFunction();
@ -633,6 +602,23 @@ class Preprocessor extends CompilerBase
}
}
$fullClassName = $this->getFullClassName();
$fullMethodName = $fullClassName . '::' . $this->method;
$this->classMethodOverride[strtolower($fullMethodName)] = false;
// 查找父类是否有同名方法,递归查找
$fullClassNameLower = strtolower($fullClassName);
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;
}
$fullClassNameLower = strtolower($parentClass);
}
$this->resetMethod();
}

@ -2290,6 +2290,37 @@ CODE;
return $code;
}
/**
* 检查父类方法是否可以被重写,私有方法不能被重写
*/
protected function checkParentMethodCanBeOverridden(Node\Stmt\ClassMethod $v, string $name): void
{
$classDef = $this->classDef;
while (true) {
$extends = $classDef->extends;
if (!$extends) {
break;
}
// 父类是内置类
if ($classDef->inheritedFromInternalClass) {
if (Reflection::getClassMethodModifiers($extends, $name) & \ReflectionMethod::IS_PRIVATE) {
goto _error;
}
break;
}
$classDef = $this->getClass($extends);
if ($classDef->hasMethod($this->method)) {
$methodDef = $classDef->getMethod($this->method);
if ($methodDef->flags & Modifiers::PRIVATE) {
_error:
$this->fatalError($v,
'Cannot override private method `' .
$classDef->getNamespacedName(false) . '::' . $this->method . '()`');
}
}
}
}
protected function parseClassMethod(Node\Stmt\ClassMethod $v, array &$methodCodes): void
{
$name = $this->getMethodName($v);
@ -2303,22 +2334,6 @@ CODE;
$methodCodes[$name] = $this->parseFunction($v);
}
$fullClassName = $this->getFullClassName();
$fullMethodName = $fullClassName . '::' . $this->method;
$this->classMethodOverride[strtolower($fullMethodName)] = false;
// 查找父类是否有同名方法,递归查找
$fullClassNameLower = strtolower($fullClassName);
while (isset($this->classExtends[$fullClassNameLower])) {
$parentClass = $this->classExtends[$fullClassNameLower];
$parentMethodLower = strtolower($parentClass . '::' . $v->name);
// 父类有同名方法,子类覆盖了父类方法,这种情况不能直接使用 C++ 函数,而是使用 ZendVM 动态调用
if (isset($this->classMethodOverride[$parentMethodLower])) {
$this->classMethodOverride[$parentMethodLower] = true;
}
$fullClassNameLower = strtolower($parentClass);
}
$this->resetMethod();
}

Loading…
Cancel
Save