如何将Scala代码块转换为字符串?能否通过Scala标准特性实现
结论
可以实现,核心依赖Scala标准提供的编译期宏特性,纯运行时API无法实现(Scala编译后会将代码转为JVM字节码,默认不会保留源代码字面量信息)。
Scala 2 实现示例
需要使用Scala 2标准的黑盒宏,直接将传入代码块的AST打印为源代码字符串:
import scala.reflect.macros.blackbox import scala.language.experimental.macros // 宏实现 def convertImpl(c: blackbox.Context)(fn: c.Tree): c.Tree = { import c.universe._ val codeLiteral = showCode(fn) Literal(Constant(codeLiteral)) } // 对外暴露的方法 def convert(fn: => Unit): String = macro convertImpl
你给出的测试用例可以直接运行通过,返回的字符串和你写的代码块内容完全匹配。
Scala 3 实现示例
Scala 3使用稳定的内联+引号特性实现,代码更简洁:
import scala.quoted.* import scala.language.implicitConversions inline def convert(inline fn: => Unit): String = ${ convertImpl('fn) } private def convertImpl(fn: Expr[Unit])(using Quotes): Expr[String] = { Expr(fn.show) }
适配场景的优势
- 所有测试代码直接写在代码块中,IDE可以正常完成语法高亮、索引、重构操作,完全符合你提到的频繁修改重构的需求
- 宏是编译期执行,刚好匹配你校验splain插件编译时错误的场景,不需要额外的源码解析步骤
- 如果需要完全保留原代码的换行、空格等格式,可以在宏实现中通过代码的位置信息,直接从源文件截取对应范围的文本即可。
内容的提问来源于stack exchange,提问作者tribbloid
相关产品推荐
相关产品推荐

