Scala runtime compilation场景下如何获取报错信息的行号
问题根因
你遇到的行号和位置标识缺失是ToolBox处理动态代码的默认行为,核心有两个原因:
- 调用
tb.parse()解析代码字符串时,默认不会给生成的语法树绑定源码位置信息,编译器报错时没有位置可输出 - 你当前的
compileError()方法里执行了.drop(2)操作,刚好把报错信息里带位置的前两行内容删除了
解决方法
方法1(适配Scala 2.12+版本)
调用parse方法时传入虚拟文件名参数,绑定代码和位置的映射关系,同时去掉多余的drop(2)操作:
// 修改parse调用 val tree = tb.parse(code, virtualFileName = "dynamic.scala") tb.eval(tree) // 修改compileError的信息提取逻辑,去掉drop(2) case te: ToolBoxError => te.message
修改后你拿到的报错就会和原生编译的格式一致,包含文件名、行号、代码片段和位置光标。
方法2(适配Scala老版本)
如果用的是不支持virtualFileName参数的老版本Scala,可以手动给语法树附加位置信息:
import scala.reflect.internal.util.{RangePosition, VirtualFile} // 构造虚拟源文件绑定代码内容 val vFile = new VirtualFile("dynamic.scala") val writer = new java.io.PrintWriter(vFile.output) writer.write(code) writer.close() // 构造全量位置信息附加到语法树 val pos = RangePosition(vFile, 0, 0, code.length) val tree = tb.parse(code).setPos(pos) tb.eval(tree)
对齐行号偏移的补充说明
ToolBox执行动态代码时会默认给你的代码套一层包装对象,可能会导致报错行号比你原始代码的行号多2~3行,你可以在构造ToolBox时传入-Xprint:typer选项查看生成的完整代码,调整位置偏移量即可对齐原始代码的行号。
内容的提问来源于stack exchange,提问作者tribbloid
相关产品推荐
相关产品推荐

