feat(di): 代理类错误可直接定位原始源码(非代理文件) - #7795
Open
tw2066 wants to merge 1 commit into
Open
Conversation
- 在Ast类中新增buildLineMap方法用于构建代理代码与原始代码的行号映射关系 - 新增LineMapFixer类用于将代理文件中的异常位置转换回原始源码位置 - 在ProxyManager中集成行号映射生成功能并添加line-map.php缓存文件 - 更新扫描配置支持line_map选项控制是否启用行号映射 - 在异常处理器中集成行号映射功能,使异常堆栈显示原始代码位置 - 添加LineMapInspector和LineMapInspectorFactory用于Whoops异常显示的行号转换 - 新增相关测试验证行号映射功能的正确性和异常处理流程
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
代理类异常行号修正(Proxy Line Map)改动说明
版本基线
Hyperf 3.2 使用 php-parser v5 的
ParserFactory::createForNewestSupportedVersion()和ClosureUse节点。line map 缓存版本提升为 3,升级后不会复用 Hyperf 3.1/php-parser v4 生成的代理映射。一、背景
Hyperf DI 使用 AST 重新生成代理类。重新打印、trait 注入和 AOP 方法改写都会改变代理文件行号,因此异常位置可能指向
runtime/container/proxy/*.proxy.php,无法直接定位原始源码。本方案在生成代理文件时同时生成
line-map.php,记录代理文件与原始文件的行号区间。运行时由异常 formatter 在生成日志或错误输出时应用映射,不修改异常对象。二、设计原则
try/catch。DefaultFormatter在生成异常文本时统一应用映射,代理方法和 dispatcher 都不捕获或改写异常。hyperf/exception-handler不强依赖hyperf/di,formatter 仅在LineMapFixer存在时调用。三、运行流程
生成阶段
ScanConfig::getLineMap()->Scanner->ProxyManager->Ast::buildLineMap()->line-map.phpline-map.php格式:映射只收集目标 class/trait/enum 的方法,避免同一文件中其他类的同名方法覆盖结果。语句精确映射要求节点类型和顶层表达式类型一致;遇到无法识别的 Visitor 结构变化时停止该方法的后续语句对齐。运行时只使用可靠的语句级映射,不根据方法范围猜测源码位置。
展示阶段
因此代理类方法和
ProxyTrait::__proxyCall()都不会为了行号映射生成以下代码:四、配置
config/autoload/annotations.php:line_map默认值为true:trueline-map.php,异常 formatter 输出原始源码位置false首次启用、map 格式升级或某个代理缺少 map 条目时,
ProxyManager会强制重新生成相关代理,避免复用不兼容缓存。旧版本遗留的__hyperf_exception__方法包装在关闭功能时也会触发一次重新生成。五、边界
file/line/trace的 API。$e->getFile()、$e->getLine()和$e->getTrace()始终返回真实的代理执行位置。FormatterInterface。业务自定义异常 handler 如果直接拼接$e->getFile(),需要改为注入FormatterInterface并调用format($e),或显式调用LineMapFixer::resolveLocation()。line-map.php是运行时生成产物,不应提交到版本库。六、并发与缓存
map 写入使用每进程唯一临时文件、文件锁和同目录
rename(),避免多个进程共享固定.tmp文件。加载缓存按代理目录隔离,支持同一进程读取不同代理目录。七、测试
覆盖范围包括: