Jenkins管道使用groovy-cps解释器以连续传递样式执行Groovy代码。这不是普通的Groovy,您可以直接在IDE或Groovy Shell中执行。
Groovy CPS转换您的代码以支持延续传递样式和正确的Groovy表达式,例如:
a = b = c = 0
被转换成更像是的东西:
eval(
var("a"),
assign(
eval(
var("b"),
assign(
eval(
var("c"),
assign(0)
)
)
)
)
)
CPS解释器中此表达式的问题在于,赋值不返回任何值,因此该null
值被赋给了变量b
,并且变量也发生了同样的事情a
。
如果您想深入了解CPS调用块,则可以克隆groovy-cps项目并在com.cloudbees.groovy.cps.CpsTransformerTest
该类中编写一个简单的测试用例。
@Test
void testMultiVariablesInlineCPS() {
def cps = parseCps('''
int a, b, c
a = b = c = 0
''')
println cps
}
然后,您可以在处放置一个断点println cps
并运行调试器。当您打开检查窗口时,您将看到与此类似的图片:
附带说明一下,请记住,当将代码编译为字节码时,Groovy编译器还会转换单行分配。如果您编译一个简单的Groovy脚本,例如:
int a, b, c
a = b = c = 0
println "$a $b $c"
然后在IDE中打开其类文件以将字节码反编译为Java等效文件,您将看到类似以下内容:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
import groovy.lang.Binding;
import groovy.lang.Script;
import org.codehaus.groovy.runtime.GStringImpl;
import org.codehaus.groovy.runtime.InvokerHelper;
import org.codehaus.groovy.runtime.callsite.CallSite;
public class test extends Script {
public test() {
CallSite[] var1 = $getCallSiteArray();
}
public test(Binding context) {
CallSite[] var2 = $getCallSiteArray();
super(context);
}
public static void main(String... args) {
CallSite[] var1 = $getCallSiteArray();
var1[0].call(InvokerHelper.class, test.class, args);
}
public Object run() {
CallSite[] var1 = $getCallSiteArray();
int a = 0;
int b = 0;
int c = 0;
byte var5 = 0;
return var1[1].callCurrent(this, new GStringImpl(new Object[]{Integer.valueOf(var5), Integer.valueOf(var5), Integer.valueOf(var5)}, new String[]{"", " ", " ", ""}));
}
}