From 394c5ee0b7fd30198dff98a98825d604ec489e8b Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Thu, 9 Apr 2026 16:20:38 +0800 Subject: [PATCH] =?UTF-8?q?refactor(php):=20=E4=BC=98=E5=8C=96=E7=BC=96?= =?UTF-8?q?=E8=AF=91=E5=99=A8=E5=9F=BA=E7=A1=80=E7=B1=BB=E5=92=8C=E9=A2=84?= =?UTF-8?q?=E5=A4=84=E7=90=86=E5=99=A8=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除了未使用的 PropertyDef 导入声明 - 添加了 getRelativePath 方法用于获取相对路径 - 调整了方法调用返回类型检测的条件判断逻辑 - 修改了常量和别名解析的条件判断结构 - 重构了类继承检查逻辑,改进了内部类继承关系处理 - 更新了代码格式化时的路径显示为相对路径 - 重写了循环依赖解决算法的实现位置 - 修复了引用参数默认值的处理方式 - 统一了多个文件中的路径显示为相对路径格式 --- src/Php/CompilerBase.php | 25 +++++--- src/Php/Preprocessor.php | 119 +++++++++++++++++++-------------------- src/Php/Translator.php | 4 +- 3 files changed, 79 insertions(+), 69 deletions(-) diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index 4e96c857..69fd1992 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -15,7 +15,6 @@ use PhpAot\Php\Entity\ConstantDef; use PhpAot\Php\Entity\FunctionDef; use PhpAot\Php\Entity\InterfaceDef; use PhpAot\Php\Entity\MethodDef; -use PhpAot\Php\Entity\PropertyDef; use PhpAot\Php\Exception\DynamicCall; use PhpAot\Php\Exception\PlaceHolder; use PhpAot\Php\Exception\Redo; @@ -563,6 +562,12 @@ class CompilerBase extends \PhpAot\Core\Translator return false; } + protected function getRelativePath($path, $cwd = ''): string + { + $cwd = $cwd ?: getcwd(); + return ltrim($this->removeCommonPrefix($cwd, $path), '/'); + } + protected function removeCommonPrefix(string $short, string $long): string { $len = min(strlen($short), strlen($long)); @@ -1769,7 +1774,8 @@ class CompilerBase extends \PhpAot\Core\Translator if ($nativeFunc) { $funcDef = $this->functions[$nativeFunc]; return $funcDef->returnType; - } elseif ($this->isTypedObject($object)) { + } + if ($this->isTypedObject($object)) { return $this->detectMethodCallReturnType($this->getObjectType($object), $method); } } @@ -3045,7 +3051,8 @@ class CompilerBase extends \PhpAot\Core\Translator } if ($this->isInternalConstant($name)) { return 'php::constant(' . $this->getLiteralString($name) . ')'; - } elseif (isset($this->useAliases[$name])) { + } + if (isset($this->useAliases[$name])) { $name = $this->useAliases[$name]; } else { $fullName = $this->getNamespacedClassName($name); @@ -3133,14 +3140,18 @@ class CompilerBase extends \PhpAot\Core\Translator protected function isInheritedFrom(string $class, string $expected): bool { - if ($this->isInternalClass($class) and ($this->isInternalClass($expected) or $this->isInternalInterface($expected))) { - return $class === $expected or is_subclass_of($class, $expected); - } + $internal = ($this->isInternalClass($expected) or $this->isInternalInterface($expected)); + while (true) { if (strcasecmp($class, $expected) === 0) { return true; } if (!$this->hasClass($class)) { + // 原生类继承自一个内置类,例如: UserError extends Exception ,然后 $expected 预期是 Throwable + // 这种情况,需要使用 ZendVM 获取继承关系 + if ($this->isInternalClass($class) and $internal) { + return $class === $expected or is_subclass_of($class, $expected); + } return false; } $classDef = $this->getClass($class); @@ -3363,7 +3374,7 @@ class CompilerBase extends \PhpAot\Core\Translator protected function formatCppCode(string $file): void { $cmd = 'cd ' . $this->rootPath . ' && clang-format -i ' . $file; - $this->climate->info('format: ' . $file); + $this->climate->info('format: ' . $this->getRelativePath($file)); $this->climate->comment($cmd); shell_exec($cmd); } diff --git a/src/Php/Preprocessor.php b/src/Php/Preprocessor.php index 7d773dcf..0ed93328 100644 --- a/src/Php/Preprocessor.php +++ b/src/Php/Preprocessor.php @@ -59,7 +59,7 @@ class Preprocessor extends CompilerBase $this->climate->yellow('Warning: Circular dependency detected, attempting to resolve...'); $circularNodes = $e->getNodes(); $this->climate->darkGray('Circular path: ' . implode(' -> ', $circularNodes)); - + // 使用打破循环后的依赖关系重新排序 $sortedFiles = $this->resolveCircularDependencies($fileDeps, $circularNodes); } @@ -70,63 +70,8 @@ class Preprocessor extends CompilerBase $sortedFiles[] = $file; } } - - $list = $sortedFiles; - } - /** - * 解决循环依赖问题 - * - * @param array $fileDeps 所有文件的依赖关系 - * @param array $circularNodes 循环依赖中的节点 - * @return array 排序后的文件列表 - * @throws ElementNotFoundException - */ - protected function resolveCircularDependencies(array $fileDeps, array $circularNodes): array - { - // 找出循环依赖中最少的边来打破循环 - // 策略:移除被依赖次数最少的文件的依赖关系 - $depCount = []; - foreach ($circularNodes as $node) { - $depCount[$node] = 0; - // 统计该节点在循环中被其他节点依赖的次数 - foreach ($circularNodes as $otherNode) { - if (isset($fileDeps[$otherNode]) && in_array($node, $fileDeps[$otherNode])) { - $depCount[$node]++; - } - } - } - - // 找到被依赖最少的节点,打破它的某个依赖 - asort($depCount); - $breakNode = key($depCount); - - $this->climate->darkGray("Breaking circular dependency at: {$breakNode}"); - - // 创建新的依赖关系,移除导致循环的依赖 - $resolvedDeps = $fileDeps; - if (isset($resolvedDeps[$breakNode])) { - // 移除该节点对循环中其他节点的依赖 - $resolvedDeps[$breakNode] = array_filter( - $resolvedDeps[$breakNode], - fn($dep) => !in_array($dep, $circularNodes) || $dep === $breakNode - ); - } - - // 使用修正后的依赖关系重新排序 - $sorter = new StringSort(); - foreach ($resolvedDeps as $file => $deps) { - $sorter->add($file, $deps); - } - - try { - return $sorter->sort(); - } catch (CircularDependencyException $e) { - // 如果仍然存在循环,递归处理 - $remainingCircular = $e->getNodes(); - $this->climate->yellow('Still has circular dependency, continuing to resolve...'); - return $this->resolveCircularDependencies($resolvedDeps, $remainingCircular); - } + $list = $sortedFiles; } public function getCppFile(string $file): string @@ -172,7 +117,7 @@ class Preprocessor extends CompilerBase $this->resetClass(); $this->resetNamespace(); - $this->climate->info('prepare: ' . $this->file); + $this->climate->info('prepare: ' . $this->getRelativePath($this->file)); try { $ast = $this->parser->parse($phpCode); } catch (\PhpParser\Error $e) { @@ -215,7 +160,61 @@ class Preprocessor extends CompilerBase $this->fatalError($v, 'Unsupported statement: ' . $type); } } + } + + /** + * 解决循环依赖问题 + * + * @param array $fileDeps 所有文件的依赖关系 + * @param array $circularNodes 循环依赖中的节点 + * @return array 排序后的文件列表 + * @throws ElementNotFoundException + */ + protected function resolveCircularDependencies(array $fileDeps, array $circularNodes): array + { + // 找出循环依赖中最少的边来打破循环 + // 策略:移除被依赖次数最少的文件的依赖关系 + $depCount = []; + foreach ($circularNodes as $node) { + $depCount[$node] = 0; + // 统计该节点在循环中被其他节点依赖的次数 + foreach ($circularNodes as $otherNode) { + if (isset($fileDeps[$otherNode]) && in_array($node, $fileDeps[$otherNode])) { + $depCount[$node]++; + } + } + } + + // 找到被依赖最少的节点,打破它的某个依赖 + asort($depCount); + $breakNode = key($depCount); + + $this->climate->darkGray("Breaking circular dependency at: {$breakNode}"); + + // 创建新的依赖关系,移除导致循环的依赖 + $resolvedDeps = $fileDeps; + if (isset($resolvedDeps[$breakNode])) { + // 移除该节点对循环中其他节点的依赖 + $resolvedDeps[$breakNode] = array_filter( + $resolvedDeps[$breakNode], + fn ($dep) => !in_array($dep, $circularNodes) || $dep === $breakNode + ); + } + + // 使用修正后的依赖关系重新排序 + $sorter = new StringSort(); + foreach ($resolvedDeps as $file => $deps) { + $sorter->add($file, $deps); + } + try { + return $sorter->sort(); + } catch (CircularDependencyException $e) { + // 如果仍然存在循环,递归处理 + $remainingCircular = $e->getNodes(); + $this->climate->yellow('Still has circular dependency, continuing to resolve...'); + return $this->resolveCircularDependencies($resolvedDeps, $remainingCircular); + } } protected function findSymbolUsing(NodeAbstract $ast) @@ -356,7 +355,7 @@ class Preprocessor extends CompilerBase $argInfo->default = 'nullptr'; $argInfo->defaultValue = null; } else { - $this->fatalError($param, 'Only null and empty array can be used as default value for reference parameter'); + $argInfo->default = 'php::newReference(' . $this->parseParamDefaultValue($param->default) . ')'; } } else { $argInfo->default = $this->parseParamDefaultValue($param->default); @@ -453,7 +452,7 @@ class Preprocessor extends CompilerBase if ($class instanceof Node\Stmt\Enum_) { $flags = Modifiers::PUBLIC; - } else if (!$class instanceof Node\Stmt\Trait_) { + } elseif (!$class instanceof Node\Stmt\Trait_) { $flags = $class->flags; } else { $flags = Modifiers::PUBLIC; diff --git a/src/Php/Translator.php b/src/Php/Translator.php index e04e8e02..23330978 100644 --- a/src/Php/Translator.php +++ b/src/Php/Translator.php @@ -662,7 +662,7 @@ class Translator extends Preprocessor protected function doConvert(string $phpCode): string { - $this->climate->info('convert: ' . $this->file); + $this->climate->info('convert: ' . $this->getRelativePath($this->file)); $ast = $this->parser->parse($phpCode); $traverser = new NodeTraverser(); @@ -855,7 +855,7 @@ class Translator extends Preprocessor $genStubCmd = PHP_BINARY . ' ' . $this->rootPath . '/bin/gen_stub.php -f -o ' . $this->getIncludeDir() . '/' . $headerFile . ' ' . $file; $output = shell_exec($genStubCmd); - $this->climate->info('generate stub file: ' . $file); + $this->climate->info('generate stub file: ' . $this->getRelativePath($file)); $this->climate->comment($genStubCmd); if (!str_contains($output, 'Saved')) {