From 59c9477bf5ede1f650824d625be7a3db48f766f3 Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Wed, 1 Jul 2026 08:45:09 +0800 Subject: [PATCH] =?UTF-8?q?refactor(php):=20=E9=87=8D=E6=9E=84=E5=B1=9E?= =?UTF-8?q?=E6=80=A7=E8=AE=BF=E9=97=AE=E8=A7=A3=E6=9E=90=E5=99=A8=E4=BB=A5?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E5=8F=AA=E8=AF=BB=E4=B8=8A=E4=B8=8B=E6=96=87?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 PropertyAccessResolver 从依赖 CompilerBase 大类改为依赖 PropertyAccessContext 接口 - 在 CompilerBase 中实现 PropertyAccessContext 接口并提供 getClassDef 和 getParentClass 方法 - 移除 PropertyAccessResolver 构造函数中的闭包参数,改用接口方法调用 - 更新 Preprocessor 中的父类获取逻辑以直接使用命名空间类名解析 - 修改 Translator 中的父类解析方式以保持一致性 - 在重构计划文档中添加只读接口设计原则说明 --- docs/REFACTORING_PLAN.md | 2 ++ src/Php/CompilerBase.php | 32 ++++++++++----------- src/Php/Preprocessor.php | 7 +---- src/Php/Resolver/PropertyAccessResolver.php | 16 +++-------- src/Php/Translator.php | 2 +- 5 files changed, 23 insertions(+), 36 deletions(-) diff --git a/docs/REFACTORING_PLAN.md b/docs/REFACTORING_PLAN.md index b97deaf9..5e20b703 100644 --- a/docs/REFACTORING_PLAN.md +++ b/docs/REFACTORING_PLAN.md @@ -21,6 +21,7 @@ 5. 优先使用小型 service/helper、明确 DTO、resolver、emitter;仅在边界稳定后再引入 Visitor、Strategy 等模式。 6. 所有错误信息保持 PHP 风格,不暴露实现细节,不使用 “AOT 禁止” 这类表述。 7. 每个阶段必须有 phpunit 或 phpt 回归验证,尤其是属性、类型、调用、继承、异常等高风险路径。 +8. 面向 resolver/emitter 暴露的编译器接口优先保持只读。只读查询接口可以按需设为 public,写操作必须格外谨慎,避免绕过统一状态管理。 ## 目标架构方向 @@ -240,6 +241,7 @@ - 旧的 `CompilerBase::findNativeProperty()` 泛型入口已移除,避免后续继续扩散带 `$static` 布尔参数的访问模式。 - `CompilerBase::isSameClassName()`、`isSameOrSubclassOf()`、`canAccessProtectedProperty()` 已委托 resolver,避免规则继续扩散。 - 已添加 `prepare/convert/idle` 编译阶段状态;`PropertyAccessResolver` 只能在 convert 阶段创建和使用,避免预处理阶段误用不完整的类表状态。 +- `PropertyAccessResolver` 已改为依赖 `PropertyAccessContext` 只读接口,而不是完整依赖 `CompilerBase` 大类。 - 当前迁移保持生成代码不变,后续阶段再统一 read/write emitter。 验证: diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index edf43899..9d0fc935 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -43,6 +43,7 @@ use PhpAot\Php\Platform\Macos; use PhpAot\Php\Platform\PlatformBase; use PhpAot\Php\Platform\PlatformFactory; use PhpAot\Php\Platform\Windows; +use PhpAot\Php\Resolver\PropertyAccessContext; use PhpAot\Php\Resolver\PropertyAccessResult; use PhpAot\Php\Resolver\PropertyAccessResolver; use PhpParser\Modifiers; @@ -64,7 +65,7 @@ use PhpParser\ParserFactory; use PhpParser\PhpVersion; use PhpParser\PrettyPrinter; -class CompilerBase extends \PhpAot\Core\Translator +class CompilerBase extends \PhpAot\Core\Translator implements PropertyAccessContext { use AstNodeType; use FuncCallOptimizer; @@ -1919,6 +1920,16 @@ class CompilerBase extends \PhpAot\Core\Translator return $this->classes[$this->escapeClass($name)]; } + public function getClassDef(string $name): ?ClassDef + { + return $this->classes[$this->escapeClass($name)] ?? null; + } + + public function getParentClass(string $class): string + { + return $this->classExtends[strtolower(ltrim($class, '\\'))] ?? ''; + } + protected function hasClass(string $name): bool { return array_key_exists($this->escapeClass($name), $this->classes); @@ -2813,16 +2824,7 @@ class CompilerBase extends \PhpAot\Core\Translator } /** - * Expand a Big* compound-assignment into `$v = Type::method($v, $rhs)`. - * - * BigInt/BigDecimal/BigFloat are immutable Box types — Variant operator+= - * goes through ZendVM add_function which does not understand them, so we - * must emit the static-method form instead. - */ - /** - * Generate the C++ expression for a Big* binary operation. - * - * @param NodeAbstract $errorNode node to blame on unsupported operators + * Report a compiler fatal error. */ public function error(string $msg): never { @@ -2837,7 +2839,7 @@ class CompilerBase extends \PhpAot\Core\Translator } } - protected function fatalError(Node $node, string $msg): never + public function fatalError(NodeAbstract $node, string $msg): never { $this->error("{$msg} in {$this->file}:{$node->getStartLine()}"); } @@ -5838,11 +5840,7 @@ class CompilerBase extends \PhpAot\Core\Translator private function createPropertyAccessResolver(): PropertyAccessResolver { $this->assertCompilerPhase(self::PHASE_CONVERT, 'PropertyAccessResolver'); - return new PropertyAccessResolver( - fn(string $class): ?ClassDef => $this->classes[$this->escapeClass($class)] ?? null, - fn(string $class): string => $this->classExtends[strtolower(ltrim($class, '\\'))] ?? '', - fn(NodeAbstract $expr, string $message) => $this->fatalError($expr, $message), - ); + return new PropertyAccessResolver($this); } protected function isSameClassName(string $classA, string $classB): bool diff --git a/src/Php/Preprocessor.php b/src/Php/Preprocessor.php index 9422772a..d9efe66b 100644 --- a/src/Php/Preprocessor.php +++ b/src/Php/Preprocessor.php @@ -456,11 +456,6 @@ class Preprocessor extends CompilerBase } } - protected function getParentClass(NodeAbstract $extends): string - { - return $this->getNamespacedClassName($this->parseIdentifier($extends)); - } - protected function prepareClass(Node\Stmt\Class_|Node\Stmt\Trait_|Node\Stmt\Enum_ $class): string { $this->resetClass(); @@ -481,7 +476,7 @@ class Preprocessor extends CompilerBase $this->addClass($fullClassName, $this->classDef); if (!empty($class->extends)) { - $this->parentClass = $this->getParentClass($class->extends); + $this->parentClass = $this->getNamespacedClassName($this->parseIdentifier($class->extends)); $parentClassLower = strtolower($this->parentClass); if ($parentClassLower === $fullClassNameLower) { $this->fatalError($class, "Class {$fullClassName} cannot extend itself"); diff --git a/src/Php/Resolver/PropertyAccessResolver.php b/src/Php/Resolver/PropertyAccessResolver.php index 9fe2a1ca..09ed0379 100644 --- a/src/Php/Resolver/PropertyAccessResolver.php +++ b/src/Php/Resolver/PropertyAccessResolver.php @@ -8,20 +8,12 @@ namespace PhpAot\Php\Resolver; -use Closure; -use PhpAot\Php\Entity\ClassDef; use PhpParser\NodeAbstract; final class PropertyAccessResolver { - /** - * @param Closure(string): ?ClassDef $getClassDef - * @param Closure(string): string $getParentClass - */ public function __construct( - private readonly Closure $getClassDef, - private readonly Closure $getParentClass, - private readonly Closure $fatalError, + private readonly PropertyAccessContext $compiler, ) { } @@ -38,7 +30,7 @@ final class PropertyAccessResolver if ($class === $parent) { return true; } - $class = ($this->getParentClass)($class); + $class = $this->compiler->getParentClass($class); } return false; } @@ -63,7 +55,7 @@ final class PropertyAccessResolver $findClass = $class; while (true) { - $classDef = ($this->getClassDef)($findClass); + $classDef = $this->compiler->getClassDef($findClass); if ($classDef === null) { break; } @@ -155,6 +147,6 @@ final class PropertyAccessResolver private function fatal(NodeAbstract $expr, string $message): never { - ($this->fatalError)($expr, $message); + $this->compiler->fatalError($expr, $message); } } diff --git a/src/Php/Translator.php b/src/Php/Translator.php index 0d8134e7..5b95d499 100644 --- a/src/Php/Translator.php +++ b/src/Php/Translator.php @@ -2776,7 +2776,7 @@ CODE; // 如果不是继承自内置类,需要检查父类是否存在,在预处理阶段只需检查了是否继承内置类 // 目前不允许继承自动态加载的自定义类 if ($this->classDef->extends and !$this->classDef->inheritedFromInternalClass) { - $parentClass = $this->getParentClass($class->extends); + $parentClass = $this->getNamespacedClassName($this->parseIdentifier($class->extends)); if ($this->hasClass($parentClass)) { $parent = $this->getClass($parentClass); // 父类是 final 无法继承