什么 Groovy 语言功能使用 Spock 来实现其条件测试 DSL?

What Groovy language feature uses Spock to implement its condition testing DSL?

作为一个不会说 Groovy 的 Kotlin/Java 程序员,我想知道 Spock 框架使用什么语言特性来进行“条件测试”,或者换句话说,Kotlin 中缺少什么来归档相同。我指的是这个

def test() {
  // ...
  then:
  foo == 3
  bar == "a"
}

我的猜测是带有断言的代码块作为参数传递给函数 then(),它以某种方式访问​​ Groovy 解释器到 运行 语句块语句,所以它可以在继续下一条语句之前检查结果是否为 true。或者是否有 Groovy 语言功能使它更容易?

Spock 语法是有效的 Groovy 语法。例如,then: 只是一个标签。 Spock 发挥其魔力的方式是——我将在这里简化——在 Groovy 编译器中注册自己,以便在 Spock 规范上应用 AST (abstract syntax tree) transformations

Groovy 编译有几个阶段的 AST 转换。基本上,开发人员可以连接到它们中的每一个,注册转换器。 AFAIK,Spock 仅关注名为 SEMANTIC_ANALYSIS 的单个阶段,参见 here:

@GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS)
public class SpockTransform implements ASTTransformation {
  // ...
}

通过将 Groovy 代码转换成一系列更复杂的注释、(嵌套)方法调用和其他语言元素,它实现了它的魔力并将 Spock DSL 转换成可以在 JVM 中执行的东西Groovy 运行时。如果您有兴趣,只需查看您的 Maven 或 Gradle Spock 模块的 target/test-classes 目录,然后使用一个好的反编译器打开一些 class 文件,例如集成在 IntelliJ IDEA 中的那个,叫做 Fernflower。但是当你第一次看到它的时候,你的头一定会爆炸。我只是粗略地浏览了几眼就感到惊讶,甚至没有假装开始深入理解其中的大部分内容。但是,嘿 - 你问了,我正在回答。

我不会说 Kotlin,但似乎在 Kotlin 中您主要使用 lambdas and extension functions 而不是 AST 转换来创建 DSL。